<html><head><style type="text/css"><!-- DIV {margin:0px;} --></style></head><body><div style="font-family:times new roman,new york,times,serif;font-size:12pt"><div>Para aqueles que tiverem dúvidas, segue pagina de onde retirei a estrutura do código.<br><br><span><a target="_blank" href="http://www.wellho.net/solutions/perl-controlling-multiple-asyncronous-processes-in-perl.html">http://www.wellho.net/solutions/perl-controlling-multiple-asyncronous-processes-in-perl.html</a></span><br></div><div style="font-family: times new roman,new york,times,serif; font-size: 12pt;"><br><br><div style="font-family: arial,helvetica,sans-serif; font-size: 13px;"><font face="Tahoma" size="2"><hr size="1"><b><span style="font-weight: bold;">De:</span></b> Daniel de Oliveira Mantovani <daniel.oliveira.mantovani@gmail.com><br><b><span style="font-weight: bold;">Para:</span></b> Cascavel Perl Mongers <cascavel-pm@pm.org><br><b><span style="font-weight:
bold;">Enviadas:</span></b> Quinta-feira, 18 de Fevereiro de 2010 13:11:16<br><b><span style="font-weight: bold;">Assunto:</span></b> Re: [Cascavel-pm] Problema com pipe<br></font><br>Você acha mesmo que executar 80 comandos de uma vez e elevar o load da<br>máquina ao infinito e além vai resolver o problema ?<br><br>Me parece que o problema é muito além de um script ou dois. Uma hora<br>esse "treco" vai parar, se já é que não para. Agora é a hora de<br>"sentar, pensar e refazer"<br><br>Da uma lida em: perldoc perlipc vai te ajudar nesse seu "treco".<br><br>2010/2/18 Gabriel Sancinetti <<a ymailto="mailto:gabrielssan@yahoo.com" href="mailto:gabrielssan@yahoo.com">gabrielssan@yahoo.com</a>>:<br>> Olá,<br>><br>> Estou trabalhando com perl há alguns meses e recentemente me deparei com um<br>> grande desafio.(pelo menos para mim).<br>> Não sei se esta lista é a adequada, mas ja gastei 4 semanas pesquisando no<br>> google
e nada de solução.<br>><br>> Enfim...<br>> Preciso reduzir o tempo de execução de um script de aproximadamente 50<br>> minutos para 8 minutos.<br>> 1 - Este scrip faz mais de 2 mil "chamadas externas" de sistema operacional<br>> ( `comando` ) com timeout de 5 a 10 seguntos.<br>> 2 - É necessário processar o STDOUT e EXIT STATUS do comando em um processo<br>> único não necessáriamente em sequencia.<br>><br>> A solução com certeza deve implementar alguma forma de paralelismo.<br>> Não consegui desenvolver uma forma de utilizar "open" no script. Então perdi<br>> para uma solução de baixo nível.<br>><br>> Encontrei uma solução que quase atendeu minhas expectativas, mas estou com<br>> problemas de nível de Sistema Operacional nela.<br>><br>> Recomendo que deem uma olhada no código pois agora irei descrever o problema<br>> deste código.<br>><br>> O meu problema é a ocorrencia de
grande quantidade de TIMEOUTs, isto é, o<br>> processo pai não recebe/processa as respostas dos filhos.<br>> Separei as chamadas de sistema em grupos de 80 comandos.<br>> Quando executo o script sem o sleep tanto no processo pai quanto no processo<br>> filho chego q ter mais de 50% de perda de respostas, (TIMEOUT)<br>> Conforme adiciono tempo ao sleep no processo filho, consigo reduzir a<br>> quantidade de TIMEOUTS considerávelmente, mas longe do satizfatório.<br>> Já quando adiciono o sleep antes do fork do processo filho a ocorrencia de<br>> TIMEOUTs cai a menos de 0.5%, mas o tempo de execução do script se aproxima<br>> do original (40 minutos).<br>><br>> Acredito que meu problema esteja no processamento do sinal (kill), mas<br>> também pode ser no pipe. Não acredito que seja no pipe pois não ocorre erros<br>> no syswrite e no sysread, etc.<br>> Já estou quase certo de que terei que refazer tudo de
outro jeito, mas estou<br>> sem idéias e preciso da opinião de pessoas mais experientes.<br>><br>> Então, agradeço desde já a atenção de vocês e espero susgestões para<br>> corrigir este script ou para refazer de outro jeito.<br>><br>> Cordialmente,<br>><br>> Gabriel<br>><br>> ps: Ignorem erros de sintaxe e identação pois editei o codigo no corpo da<br>> mensagem.<br>><br>> #########################################################################################################<br>> my $gotone;<br>> sub doneit {<br>> $gotone=$gotone+1;<br>> # logMsg("Got one! ($gotone)");<br>> }<br>><br>> $SIG{USR1} = \&doneit;<br>> my $parent = $$;<br>> $kids=0;<br>> $gotone=0;<br>><br>> #Para não sobrecarregar o servidor, a lista de comandos é dividida em grupos<br>> de 80. (@CHECKS = (cmd1 .. cmd80))<br>> foreach my $checkID (@CHECKS)
{<br>><br>> pipe *{$checkID},PIPEN;<br>><br>> #Espera do processo pai antes de cada fork para testes<br>> # Este tempo de espera é diferencial na ocorrencia da falha<br>> # sleep(10);<br>><br>> $PIDs{$checkID} = fork();<br>> if (not defined $PIDs{$checkID}) {<br>> logMsg("ERROR: Fork FAILURE!!!");<br>><br>> } elsif ($PIDs{$checkID} == 0) {<br>> # Processo
filho executa espera diminuindo probalidade de<br>> sobrecarga de respostas para processo pai.<br>> my $random_number = rand();<br>> # my $random_wait = $random_number*3;<br>> sleep($random_wait);<br>><br>> my $saida;<br>> $saida = `cmdN`;<br>> my $exit_value = $? >> 8;<br>><br>> #Escreve saida no pipe para processo pai.<br>>
my $write = syswrite PIPEN, "$exit_value;$saida";<br>> if (!defined($write)) {<br>> logMsg("ERROR (write pipe): $!");<br>> }<br>><br>> close *{$checkID};<br>> kill "USR1",$parent;<br>> exit();<br>> # fim do processo filho<br>> } else {<br>>
# Contagem de número de processos filhos no pai (80)<br>> $kids++;<br>> }<br>> }<br>><br>> # While para processamento de respostas dos processos filhos<br>> # deve ser garantido que todos filhos serão processados<br>> while ($kids > 0) {<br>><br>> # Aguarda 10 segundos depois de receber ultimo sinal (USR1).<br>> $gotone é uma variavel global que contabiliza o numero de processos filhos<br>> que ja responderam. Esta variavel é decrementada de acordo com o<br>> processamento dos filhos para controle de TIMEOUT.<br>>
my $timeout = 10;<br>> # While para espera de resposta/sinal de processos filhos<br>> while ( $gotone < 1 && $timeout > 0) {<br>> sleep 1;<br>> $timeout=$timeout-1;<br>> }<br>><br>> # if para encerrar processamento. Informa número de processos<br>> filhos que não responderam.<br>> # teoricamente este if nunca deve ser processado. ESTE É O<br>> PROBLEMA.<br>>
if ($timeout <= 0) {<br>> logMsg("TIMEOUT!!! $kids checks não responderam a tempo.");<br>> $kids =0;<br>> next;<br>> }<br>><br>><br>> $gotone=$gotone-1;<br>><br>> #for para saber qual filho respondeu (sysread irá falhar até<br>> encontrar)<br>> foreach my $checkID (@CHECKS) {<br>><br>> my $win = "";<br>>
my $rin = $win;<br>> vec($rin, fileno(*{$checkID}), 1) = 1;<br>> my $ein = $rin ;<br>> if (select($rin,$win,$ein,0)) {<br>> my $response;<br>> my $read = sysread($checkID,$response,512);<br>> #if (!defined($read)) {<br>> # logMsg("ERROR (read pipe): $!");<br>>
#}<br>> #else { next;}<br>><br>> my $saida="";<br>> my $exit_value="";<br>> ($exit_value,$saida) = split(';',$response);<br>> $saida =~ s/[\r\n]//g;<br>> $saida = $saida;<br>><br>> # Executa processamento da
resposta<br>><br>> close *{$checkID};<br>> $kids=$kids-1;<br>> last;<br>> }<br>> }<br>> }<br>> my $kid;<br>> do {<br>> $kid = waitpid(-1, WNOHANG);<br>> } while $kid > 0;<br>> }<br>><br>><br>><br>><br>><br>><br>><br>><br>>
________________________________<br>> Veja quais são os assuntos do momento no Yahoo! + Buscados: Top 10 -<br>> Celebridades - Música - Esportes<br>> _______________________________________________<br>> Cascavel-pm mailing list<br>> <a ymailto="mailto:Cascavel-pm@pm.org" href="mailto:Cascavel-pm@pm.org">Cascavel-pm@pm.org</a><br>> <a href="http://mail.pm.org/mailman/listinfo/cascavel-pm" target="_blank">http://mail.pm.org/mailman/listinfo/cascavel-pm</a><br>><br><br><br><br>-- <br>"If you’ve never written anything thoughtful, then you’ve never had<br>any difficult, important, or interesting thoughts. That’s the secret:<br>people who don’t write, are people who don’t think."<br>_______________________________________________<br>Cascavel-pm mailing list<br><a ymailto="mailto:Cascavel-pm@pm.org" href="mailto:Cascavel-pm@pm.org">Cascavel-pm@pm.org</a><br><a href="http://mail.pm.org/mailman/listinfo/cascavel-pm"
target="_blank">http://mail.pm.org/mailman/listinfo/cascavel-pm</a><br></div></div>
</div><br>
<hr size=1>Veja quais são os assuntos do momento no Yahoo! + Buscados: <a href="http://br.rd.yahoo.com/mail/taglines/mail/*http://br.maisbuscados.yahoo.com/">Top 10</a> - <a href="http://br.rd.yahoo.com/mail/taglines/mail/*http://br.maisbuscados.yahoo.com/celebridades/">Celebridades</a> - <a href="http://br.rd.yahoo.com/mail/taglines/mail/*http://br.maisbuscados.yahoo.com/m%C3%BAsica/">Música</a> - <a href="http://br.rd.yahoo.com/mail/taglines/mail/*http://br.maisbuscados.yahoo.com/esportes/">Esportes</a></body></html>