Eu sou novo em gevents e greenlets. Encontrei uma boa documentação sobre como trabalhar com eles, mas nenhuma me deu justificativa sobre como e quando devo usar os greenlets!
- No que eles são realmente bons?
- É uma boa ideia usá-los em um servidor proxy ou não?
- Por que não tópicos?
O que não tenho certeza é como eles podem nos fornecer simultaneidade se forem basicamente co-rotinas.
threading.Thread
é realmente um encadeamento do SO com todas as ramificações. Portanto, não é tão simples assim. A propósito, Jython não tem GIL AFAIK e PyPy tentando se livrar dele também.Respostas:
Os greenlets fornecem simultaneidade, mas não paralelismo. Simultaneidade é quando o código pode ser executado independentemente de outro código. Paralelismo é a execução de código simultâneo simultaneamente. O paralelismo é particularmente útil quando há muito trabalho a ser feito no espaço do usuário, e isso geralmente envolve coisas pesadas na CPU. A simultaneidade é útil para desmembrar problemas, permitindo que diferentes partes sejam agendadas e gerenciadas mais facilmente em paralelo.
Os greenlets realmente brilham na programação de rede em que as interações com um soquete podem ocorrer independentemente das interações com outros soquetes. Este é um exemplo clássico de simultaneidade. Como cada greenlet é executado em seu próprio contexto, você pode continuar usando APIs síncronas sem segmentação. Isso é bom porque os threads são muito caros em termos de memória virtual e sobrecarga do kernel; portanto, a simultaneidade que você pode obter com os threads é significativamente menor. Além disso, a segmentação em Python é mais cara e mais limitada do que o normal devido ao GIL. Alternativas à simultaneidade são geralmente projetos como Twisted, libevent, libuv, node.js etc., em que todo o seu código compartilha o mesmo contexto de execução e registra manipuladores de eventos.
É uma excelente ideia usar greenlets (com suporte de rede apropriado, como por meio de gevent) para escrever um proxy, pois o processamento de solicitações é capaz de executar independentemente e deve ser escrito como tal.
Os greenlets proporcionam simultaneidade pelas razões que mencionei anteriormente. Concorrência não é paralelismo. Ao ocultar o registro de eventos e executar o agendamento para você em chamadas que normalmente bloqueariam o encadeamento atual, projetos como gevent expõem essa simultaneidade sem exigir a alteração de uma API assíncrona e a um custo significativamente menor para o seu sistema.
fonte
import hashlib def checksum_md5(filename): md5 = hashlib.md5() with open(filename,'rb') as f: for chunk in iter(lambda: f.read(8192), b''): md5.update(chunk) return md5.digest()
Tomando a resposta do @ Max e adicionando alguma relevância para o dimensionamento, você pode ver a diferença. Consegui isso alterando os URLs a serem preenchidos da seguinte maneira:
Eu tive que abandonar a versão multiprocesso, pois ela caía antes dos 500; mas em 10.000 iterações:
Então você pode ver que há alguma diferença significativa na E / S usando o gevent
fonte
Corrigindo a resposta do @TemporalBeing acima, os greenlets não são "mais rápidos" que os threads e é uma técnica de programação incorreta gerar 60000 threads para resolver um problema de simultaneidade, um pequeno conjunto de threads é apropriado. Aqui está uma comparação mais razoável (do meu post no reddit em resposta a pessoas que citam este post no SO).
Aqui estão alguns resultados:
o mal-entendido que todos têm sobre E / S não bloqueadoras com Python é a crença de que o intérprete Python pode prestar atenção ao trabalho de recuperar resultados de soquetes em larga escala mais rapidamente do que as próprias conexões de rede podem devolver E / S. Embora isso certamente seja verdade em alguns casos, não é quase tão freqüentemente quanto as pessoas pensam, porque o intérprete Python é muito, muito lento. No meu blog aqui , ilustro alguns perfis gráficos que mostram que, mesmo para coisas muito simples, se você estiver lidando com acesso rápido e nítido à rede a coisas como bancos de dados ou servidores DNS, esses serviços poderão retornar muito mais rapidamente que o código Python pode atender a muitos milhares dessas conexões.
fonte
Isso é interessante o suficiente para analisar. Aqui está um código para comparar o desempenho de greenlets versus pool de multiprocessamento versus multi-threading:
aqui estão os resultados:
Penso que o greenlet alega que não está vinculado pelo GIL, ao contrário da biblioteca multithreading. Além disso, o documento Greenlet diz que se destina a operações de rede. Para uma operação intensiva em rede, a troca de threads é boa e você pode ver que a abordagem de multithreading é bastante rápida. Também é sempre preferível usar as bibliotecas oficiais do python; Eu tentei instalar o greenlet no windows e encontrou um problema de dependência da dll, então eu executei este teste em um linux vm. Sempre tente escrever um código com a esperança de que seja executado em qualquer máquina.
fonte
getsockbyname
os resultados são armazenados em cache no nível do sistema operacional (pelo menos na minha máquina). Quando invocado em um DNS anteriormente desconhecido ou expirado, ele efetivamente realiza uma consulta de rede, o que pode levar algum tempo. Quando invocado em um nome de host que foi resolvido recentemente, ele retornará a resposta muito mais rapidamente. Consequentemente, sua metodologia de medição é falha aqui. Isso explica seus resultados estranhos - o gevent não pode ser muito pior do que o multithreading - ambos não são realmente paralelos no nível da VM.using_gevent() 421.442985535ms using_multiprocessing() 394.540071487ms using_multithreading() 402.48298645ms