2016-09-22 1 views
1

я быть_наст многопоточная программа (около 20 нитей, смесь производителя/потребителей со многими очередями)python: socket.sendall() hogs GIL?

в одном из потоков, он выскакивает строку из очереди и отправить его на удаленную программу

# it starts the thread like this 
workQ = Queue.Queue() 
stop_thr_event = threading.Event() 
t = threading.Thread(target=worker, args=(stop_thr_event,)) 


# in the thread's worker function 
def worker(stop_event): 
    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 
    server_address = (myhost, int(myport)) 
    sock.connect(server_address) 
    while True: 
     try: 
      item = workQ.get(timeout=1) 

      if print_only: 
       print item 
      else: 
       if item.startswith("key:"): 
        item = "{%s}" % item 
        sock.sendall(item) 

      workQ.task_done() 
     except Queue.Empty, msg: 
      if stop_event.isSet(): 
       break 

с перерывами, моя программа будет просто повесить, ни один из потоков не делают любую работу

после проб и ошибок, я обнаружил, что моя программа зависает только с этой нитью

моих только догадывались s - то, что sendall() забивает GIL, и вся моя программа зависает

1) это даже правдоподобная теория?
2) если моя теория верна, что я могу сделать так, чтобы sendall() не свивал GIL? сделать его неблокированной отправкой?

ответ

2

Вы ошибаетесь. Никакие сетевые действия не выполняются GIL, и sendall() не является исключением!

item=workQ.get() 
socket.sendall() **# may take long time here.** 
workQ.task_done() 

Поскольку SendAll() может занять много времени, и другие темы, которые используют workQ не может взять свою очередь запустить перед вызовом task_done() ==> поэтому, кажется, что вся ваша программа в откосе ,

+0

if i dont ctrl c, он просто запустится вечно, поэтому я не знаю, что вы подразумеваете под sendall(), просто занимает много времени. если это займет много времени, разве это не закончилось бы, а не повесить? – ealeon

+0

можно ли отправитьall(), чтобы его повесили? – ealeon

+0

например, если клиент, который получает sendall(), не получает, отменяет ли sendall()? – ealeon

1

GIL-hogging не приведет к зависанию программы. Это может повредить работе программы, но это далеко не повешено. Скорее всего, вы испытываете некоторую форму deadlock. GIL не может участвовать в тупике, потому что переводчик постоянно выпускает и повторно приобретает его, приобретая или отпуская GIL, как правило, не зависит от приобретения или отпускания каких-либо других ресурсов, а другие блокировки также не зависят от GIL.

Ваше использование замка stop_thr_event довольно своеобразно. Для мастера было бы более просто просто поместить в очередь ряд объектов «мы закончили, идем домой», а работникам - обнаружить эти объекты и вернуться, когда они будут распознаны. Это также связано с эмпирическим правилом, что единственными правильными значениями для timeout являются нуль и бесконечность (т. Е. Нет таймаута). В текущем случае ваш работник ждет одну секунду, проверит событие, ждет одну секунду и т. Д. И polling is a Bad Thing.

Теперь, если под «зависанием» вы подразумеваете, что программа иногда замерзает в течение коротких периодов времени до возобновления, то плохой производительности, поэтому, возможно, виноват GIL. Но сокет не проблема. Проблема в том, что у вас может быть большое количество потоков, борющихся за GIL (потому что они все пытаются опросить один раз в секунду), и если вы все еще на 2.x, у вас нет the new GIL. Устранение опроса поможет в этом.

+0

oops, который должен быть threading.Event(), а не lock() Хотя я не знаю, имеет ли это значение. и это событие не будет установлено до тех пор, пока у программы больше не останется работы.да, это может быть тупик где-то еще? другой ответ правда? Требуется ли task_done() для других использовать workQ? – ealeon

+0

да, я подумал о том, чтобы положить ядовитые таблетки, может быть, я должен изменить это – ealeon

+0

ohh, я не знал, что касается тайм-аута. плохое исправить это также – ealeon

Смежные вопросы