>>>>> "Stanislaw" == Stanislaw Pusep <[email protected]> writes:

    Stanislaw> Thiago, muito obrigado pela excelente resposta!
    Stanislaw> Realmente, há muita coisa a ser considerada, todavia, ainda 
estou longe de chegar no gargalo do TCP/IP em
    Stanislaw> si.
    Stanislaw> O que eu percebi é que, infelizmente, não existe nenhum módulo 
no CPAN apropriado para gerenciar downloads
    Stanislaw> de listas longas de URLs (as minhas listas são de ~500 mil URLs 
de arquivos estáticos por sessão). Sim, é
    Stanislaw> possível usar LWP e apelar para um fork(), mas aí vi que 
consumia RAM/CPU demais, *quando comparado a um
    Stanislaw> processo externo*.

Isso depende do processo externo e de como você está forkando. Se você
deixar pra modificar absolutamente o mínimo de dados dentro do processo
forkado, acho bem difícil que um processo completamente novo ocupe menos
memória, já que você se beneficia do copy-on-write.

    Stanislaw> E, para mim, como programador Perl, é deveras frustrante
    Stanislaw> delegar os downloads ao lftp (http://lftp.yar.ru/
    Stanislaw> )... Afinal, o que o lftp tem de tão bom que eu não possa
    Stanislaw> fazer em Perl?! ;) Então, implementei o
    Stanislaw> AnyEvent::Net::Curl::Queued, que é capaz de gerenciar
    Stanislaw> filas bem grandes de downloads, de forma assíncrona. Mas
    Stanislaw> será que compensa usá-lo ao invés do lftp? Para isso,
    Stanislaw> comecei fazendo benchmarks.  Agradeço a todos pelas
    Stanislaw> sugestões! Seguem as minhas observações:

    Stanislaw>  1. Eden, você está certo, os "filhotes" do LWP tem uma 
inicialização muito lenta; e o mais curioso é que
    Stanislaw>     boa parte da inicialização não está no new() propriamente 
dito, mas é feita durante o primeiro request
    Stanislaw>     (). Então, para ser justo, dividi a minha fila de downloads 
em 10 filas separadas, e aloquei um fork()
    Stanislaw>     para cada uma;

Se você fizer um "warm-up" antes de forkar, talvez tenha mais benefício.

    Stanislaw>  4. wget tem o menor overhead de todas as alternativas por ser 
ridiculamente simples. Quase não tem
    Stanislaw>     dependências, por isso a sua inicialização é quase
    Stanislaw>     que instantânea;

Mas ainda duvido que supere um processo com uma boa implementação
forkante.

    Stanislaw>  5. AnyEvent::HTTP é a melhor alternativa para acessar uma 
quantidade limitada de URLs *em paralelo*.
    Stanislaw>     Porém, para listas razoavelmente grandes, gerenciamento via 
callbacks e closures é meio tenebroso...
    Stanislaw>  6. Reiterando: o *MEU* interesse se restringe a pegar meio 
milhão de URLs e baixar de forma mais
    Stanislaw>     eficiente possível (isso é, o gargalo deve ser minha 
bandwidth, não minha CPU/RAM). Nesse caso, pouco
    Stanislaw>     me importa a possibilidade de fazer parsing de headers, 
gerenciar cookies ou processamento de HTML.
    Stanislaw>     Isso é, quando eu quiser, devo poder habilitar tudo isso; 
mas o default deve ser OFF. Portanto, o meu
    Stanislaw>     "Holy Grail" seria um libwget, que gerencia filas, extrai 
links e faz downloads recursivos :)

Mas e se o download precisar de auth, sessão via cookie, proxy, ou
qualquer uma das outras bizarrices do HTTP? Se você coletar casos de uso
típicos, pode implementar um handler otimizado pra cada caso,
introspectar os requisitos do download e fazer um lazy-loading da
implementação correta, isso tudo antes de forkar.

-- 
Eden Cardim
Software Engineer
http://bit.ly/edencardim
http://twitter.com/#!/edenc
+55 73 9986-3963
=begin disclaimer
   Sao Paulo Perl Mongers: http://sao-paulo.pm.org/
 SaoPaulo-pm mailing list: [email protected]
 L<http://mail.pm.org/mailman/listinfo/saopaulo-pm>
=end disclaimer

Responder a