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