[SP-pm] downloader survey

Eden Cardim edencardim at gmail.com
Mon Oct 24 08:35:03 PDT 2011


>>>>> "Stanislaw" == Stanislaw Pusep <creaktive em gmail.com> 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


More information about the SaoPaulo-pm mailing list