[SP-pm] downloader survey
Stanislaw Pusep
creaktive at gmail.com
Mon Oct 24 06:20:17 PDT 2011
Thiago, muito obrigado pela excelente resposta!
Realmente, há muita coisa a ser considerada, todavia, ainda estou longe de
chegar no gargalo do TCP/IP em si.
O que eu percebi é que, infelizmente, não existe nenhum módulo no CPAN
apropriado para gerenciar downloads de listas longas de URLs (as minhas
listas são de ~500 mil URLs de arquivos estáticos por sessão). Sim, é
possível usar LWP e apelar para um fork(), mas aí vi que consumia RAM/CPU
demais, *quando comparado a um processo externo*.
E, para mim, como programador Perl, é deveras frustrante delegar os
downloads ao lftp (http://lftp.yar.ru/)... Afinal, o que o lftp tem de tão
bom que eu não possa fazer em Perl?! ;)
Então, implementei o AnyEvent::Net::Curl::Queued, que é capaz de gerenciar
filas bem grandes de downloads, de forma assíncrona. Mas será que compensa
usá-lo ao invés do lftp? Para isso, comecei fazendo benchmarks.
Agradeço a todos pelas sugestões! Seguem as minhas observações:
1. Eden, você está certo, os "filhotes" do LWP tem uma inicialização
muito lenta; e o mais curioso é que boa parte da inicialização não está no
new() propriamente dito, mas é feita durante o primeiro request(). Então,
para ser justo, dividi a minha fila de downloads em 10 filas separadas, e
aloquei um fork() para cada uma;
2. LWP::Curl e AnyEvent::Multi::Curl são ambos derivados do WWW::Curl.
Não vale a pena testar o WWW::Curl "cru", na minha opinião;
3. LWP::Curl + forks é mais rápido do que a interface CLI do curl (ambos
paralelizados do mesmo jeito que o LWP, com 10 filas independentes)!!!
Atribuo isso a uma esquisitice do curl na hora de extrair as informações
sobre o download: por alguma razão, esse processo é MUITO lento;
4. wget tem o menor overhead de todas as alternativas por ser
ridiculamente simples. Quase não tem dependências, por isso a sua
inicialização é quase que instantânea;
5. AnyEvent::HTTP é a melhor alternativa para acessar uma quantidade
limitada de URLs *em paralelo*. Porém, para listas razoavelmente grandes,
gerenciamento via callbacks e closures é meio tenebroso...
6. Reiterando: o *MEU* interesse se restringe a pegar meio milhão de URLs
e baixar de forma mais eficiente possível (isso é, o gargalo deve ser minha
bandwidth, não minha CPU/RAM). Nesse caso, pouco me importa a possibilidade
de fazer parsing de headers, gerenciar cookies ou processamento de HTML.
Isso é, quando eu quiser, devo poder habilitar tudo isso; mas o default deve
ser OFF. Portanto, o meu "Holy Grail" seria um libwget, que gerencia filas,
extrai links e faz downloads recursivos :)
Para fechar, segue a tabela de benchmark atualizada:
URL/s WWW::Mechanize LWP::UserAgent HTTP::Lite
HTTP::Tiny AnyEvent::Curl::Multi lftp AnyEvent::Net::Curl::Queued
AnyEvent::HTTP curl LWP::Curl wget
WWW::Mechanize 196 -- -60%
-80% -85% -86% -88%
-89% -92% -97% -97% -100%
LWP::UserAgent 484 148% --
-51% -63% -66% -70%
-72% -80% -93% -93% -99%
HTTP::Lite 989 405% 104%
-- -25% -32% -39%
-42% -59% -85% -86% -99%
HTTP::Tiny 1312 569% 170%
33% -- -9% -19%
-23% -46% -80% -82% -99%
AnyEvent::Curl::Multi 1446 638% 198%
46% 10% -- -10%
-16% -41% -78% -80% -98%
lftp 1609 722% 232%
63% 23% 11% --
-6% -34% -75% -77% -98%
AnyEvent::Net::Curl::Queued 1713 773% 253%
73% 30% 18% 6%
-- -30% -74% -76% -98%
AnyEvent::HTTP 2437 1144% 403%
146% 86% 69% 51%
42% -- -63% -66% -97%
curl 6512 3228% 1244%
559% 397% 351% 305%
281% 167% -- -8% -93%
LWP::Curl 7110 3524% 1364%
618% 442% 391% 341%
315% 191% 9% -- -92%
wget 88875 45240% 18215%
8877% 6675% 6045% 5418%
5092% 3544% 1262% 1151% --
ABS()
2011/10/20 Thiago Rondon <thiago em aware.com.br>
> On Thu, Oct 20, 2011 at 05:25:20PM -0200, Stanislaw Pusep wrote:
> > OK, aqui vai o spoiler: estou fazendo benchmark (de overhead) de todos
> os
> > HTTP agents que conheAS:o. E oA LWP estA! *MUITO* feio na fita:
> > https://metacpan.org/module/AnyEvent::Net::Curl::Queued#OVERHEAD
> > ABS()
>
> Stan,
>
> Eu vou apontar para outro lado, já que me parece que teu objetivo é
> perfomance para efetuar download de arquivos via http (tcp), e você
> já esta testando as alternativas que há como módulo para realizar
> tua tarefa. :)
>
> Me parece que teu caso é:
>
> - Uso do protocolo HTTP para baixar arquivos ;
> - Encontrar o melhor algoritimo para trabalhar em paralelo no seu
> aplicativo;
> - Verificar se você tem "banda" necessária para este trabalho.
>
> Primeiramente, é interessante saber, quanto de banda você tem
> disponível ? Qual o tamanho dos arquivos que você vai efetuar download ?
> Ou seja, qual sua capacidade para buscar os arquivos, e qual
> 'concorrencia' ?
>
> Como é um caso para conectividade em paralelo, é interessante levantar
> alguns pontos da tua rede e do teu sistema operacional para saber se ele
> suporta e esta preparado para esta demanda. Isto pode afetar o
> comportamento
> de alguns módulos.
>
> Apesar do kernel 2.6 já ter muita coisa para o "autotuning" na pilha
> TCP, é interessante olhar para alguns parametros, tais como:
>
> - net/core/[r,w]mem_max e net/ipv4/tcp_[r,w]mem pode ser muito interessante
> em
> casos onde há conexões em paralelo, com excesso uso de conexões e
> dados.
>
> - net/ipv4/tcp_available_congestion_control - Este é um assunto que vale
> ler, dependendo do local, da 'qualidade do link' você pode optar por
> um algoritimo, se tiver banda em excesso e etc, pode ser outra. Há
> muita atualização destes algoritimos ao longo do desenvolvimento do
> kernel 2.6, vale verificar e atualizar o kernel se você for alterar
> este parametro.
>
> - txqueuelen é um bom parametro também para ser trabalhado, pois pode te
> oferecer uma boa perfomance neste cenário também, este parametro é
> efetuado no device, por exemplo 'ifconfig eth0 txqueuelen 100000'
>
> Em relação ao algoritimo de concorrencia, dependendo da quantidade que
> você quer, e se você esta de olho em perfomance, é interessante olhar
> para o epoll no Linux. Eu ainda não usei os módulos que trabalham
> diretamente com ele, como o IO::Epool, mas há muita coisa surgindo
> baseado nesta caracteristica "nova" que esta disponível no kernel,
> tais como nginx e etc. Fica uma pergunta.. Será que isto vai fazer
> realmente diferença ? Eu não sei, mas gostaria de ver seus resultados
> aqui. :)
>
> Agora, o HTTP você pode utilizar o keep alive, dependendo também das
> suas requisições, são para o mesmo host ? Se você tiver uma lista, é
> uma boa ordenar por host, e dividir elas entre os processos que você
> vai separar, ou seja, se você tiver 30 arquivos no host X, e 30 no
> arquivo Y, organize eles para se aproveitar do keep alive, ou se for
> tudo diferente desative ele.
>
> Se os arquivos não foram compactados, e dependendo do tipo, e se
> banda for um 'problema', talvez vale apena ativar a compactação para
> buscar os arquivos, onde os servidores suportarem.
>
> Se a lista for 'grande' e 'diversificada', use o dns cache, e vá
> resolvando os nomes antes, para economizar uma etapa na hora que
> for para 'buscar'.
>
> Tome cuidado com roteadores bizarros que 'zoem' o MTU, isto pode
> afetar bastante, um MTU alto pode te ajudar com transferir pacotes
> com dados grandes.
>
> Enfim, foram ideias que tive agora sobre o problema. :)
>
> Acredito que o restante da discussão, é o que você já tá procurando,
> que é como os módulos trabalham, e efetuam a tarefa que você quer,
> mas poste os resultados aqui, pois também estou curioso. :-)
>
> Ps.: Lembre-se que todos os valores no /proc são volateis, então use o
> sysctl
> para manter ele persistente no teu sistema. :)
>
> Abs!
> -Thiago Rondon
> =begin disclaimer
> Sao Paulo Perl Mongers: http://sao-paulo.pm.org/
> SaoPaulo-pm mailing list: SaoPaulo-pm em pm.org
> L<http://mail.pm.org/mailman/listinfo/saopaulo-pm>
> =end disclaimer
>
-------------- Pr�xima Parte ----------
Um anexo em HTML foi limpo...
URL: <http://mail.pm.org/pipermail/saopaulo-pm/attachments/20111024/0ac020eb/attachment-0001.html>
More information about the SaoPaulo-pm
mailing list