[Cascavel-pm] Problema com pipe

Alceu R. de Freitas Jr. glasswalk3r em yahoo.com.br
Quinta Fevereiro 18 10:27:18 PST 2010


Olá Gabriel,

Que comando é esse que você chama externamente? Por que algumas vezes você recebe timeout? Simplesmente porque o processo externo que você está executando demora?

Não é possível você substituir esse processo externo por código Perl equivalente? Você evitaria um fork adicional e possivelmente tornaria mais fácil identificar erros.

Já executou um profile do seu programa para identificar quais áreas tomam mais tempo de execução do seu programa? Eu escrevi um artigo sobre isso no perl.org.br.

Dê uma olhada no Parallel::ForkManager (http://search.cpan.org/~dlux/Parallel-ForkManager-0.7.5/ForkManager.pm) e veja se ele não te ajuda.

Se o hardware que você não der conta do recado mesmo você tendo otimizado o código, verifique se você não pode usar o OpenMosix para distribuir a carga. Mas só vale a pena se seu processo não realizar muito I/O.

Abraços,
Alceu

> 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


Mais detalhes sobre a lista de discussão Cascavel-pm