vs. Comparação de Threads Bruno Menegola X Zen do Python 1. Bonito é melhor que feio. 2. Explícito é melhor que implícito. 3. Simples é melhor que complexo. 4. Complexo é melhor que complicado. 5. Plano é melhor que aninhado. 6. Esparso é melhor que denso. 7. Legibilidade conta. 8. Casos especiais não são especiais o bastante para se quebrar as regras. 9. Embora a simplicidade supere o purismo. 10. Erros nunca deveriam passar silenciosamente. 11. A menos que explicitamente silenciados. 12. Ao encarar a ambiguidade, recuse a tentação de adivinhar. 13. Deveria haver uma – e preferencialmente apenas uma – maneira óbvia de se fazer isto. 14. Embora aquela maneira possa não ser óbvia à primeira vista se você não for holandês. 15. Agora é melhor que nunca. 16. Embora nunca, seja muitas vezes melhor que pra já. 17. Se a implementação é difícil de explicar, é uma má idéia. 18. Se a implementação é fácil de explicar, pode ser uma boa idéia. 19. Namespaces são uma idéia estupenda – vamos fazer mais deles! X Interpretação vs. Compilação Interpretadores Python: Cpython, Jython, IronPython, PyPy, Python for S60 Python pode ser “compilado” apenas para seu bytecode (código intermediário) X Criação de Threads Por herança: from threading import Thread from time import sleep class Hello(Thread): def run(self): sleep(3) print 'Hello World!' thread = Hello() print 'Iniciando thread...' thread.start() print 'Thread iniciada.' X Criação de Threads Passando objeto invocável como parâmetro: from threading import Thread from time import sleep class Hello: def foo(self): sleep(3) print 'Hello World!' hello = Hello() thread = Thread(target=hello.foo) print 'Iniciando thread...' thread.start() print 'Thread iniciada.' X Construtor Thread class threading.Thread( group=None, target=None, name=None, args=(), kwargs={} ) Embora exista um parâmetro group, não existem grupos implementados ainda! X O que não há em Python Security Manager Métodos relacionados a ele, também não existem em threads Grupos Prioridade de thread Em Unix pode ser setado o parâmetro nice Estados não documentados? Troca de contexto com sleep e yield Usando time.sleep() obtêm-se o mesmo resultado time.sleep(0.0) para simular yield X Sincronização Python não utiliza monitores! Primitivas estão disponíveis: Lock Event Semaphore Condition X Sincronização Comportamento parecido com monitores utilizando instrução with e Lock: from threading import Thread, Lock from time import sleep def foo(id): with lock: for i in xrange(50): print id sleep(0.1) lock = Lock() t1 = Thread(target=foo, args=(1,)) t2 = Thread(target=foo, args=(2,)) t1.start() t2.start() X Desempenho from threading import Thread from time import sleep def buzy(): for i in xrange(1600000000): pass t1 = Thread(target=buzy) t2 = Thread(target=buzy) t1.start() sleep(30) t2.start() X Desempenho 160 140 120 Uso de CPU (%) 100 80 60 40 20 0 2 1 5 4 8 11 14 17 20 23 26 29 32 35 38 41 44 47 50 53 56 59 62 65 68 71 74 77 80 83 86 89 92 95 98 101 104 107 110 113 116 119 122 125 128 131 134 7 10 13 16 19 22 25 28 31 34 37 40 43 46 49 52 55 58 61 64 67 70 73 76 79 82 85 88 91 94 97 100 103 106 109 112 115 118 121 124 127 130 133 136 Tempo (s) X Global Interpreter Lock Lock para garantir escrita em memória pelo interpretador Basicamente o interpretador solta e readquire a cada 100 instruções de bytecode ou em possíveis IO bloqueantes Difícil se livrar dele devido a forma de implementação do interpretador X Considerações finais Python é realmente simples e facilita a criação e tratamento de threads Porém possui menos recursos que Java Tem o infame problema do GIL Obrigado! vs. Comparação de Threads Bruno Menegola