Pergunta

Existe uma solução mais rápida do que minha solução 'ZCAT' real para os arquivos Gunzip com Perl?

Um pouco de referência:

#!/usr/bin/perl

use strict;
use warnings;
use Benchmark qw(cmpthese timethese);
use IO::Uncompress::Gunzip qw(gunzip);

my $re = qr/test/;

my $bench = timethese($ARGV[1], {

  zcat => sub {
    if (defined open(my $FILE, "-|", "zcat " . $ARGV[0]))
    {
      while (<$FILE>)
      {
        print $_  if ($_ =~ $re);
      }
      close($FILE);
    }
  },

  io_gunzip => sub {
    my $z = new IO::Uncompress::Gunzip $ARGV[0];
    while (<$z>)
    {
      print $_  if ($_ =~ $re);
    }
  },

  io_gunzip_getline => sub {
    my $z = new IO::Uncompress::Gunzip $ARGV[0];
    while (my $line = $z->getline())
    {
      print $line if ($line =~ $re);
    }
  },

} );

cmpthese $bench;

1;

Dê -me estes resultados:

# zcat test.gz|wc -l
566
# zcat test2.gz|wc -l
60459

# ./zip_test.pl test.gz 500
Benchmark: timing 500 iterations of io_gunzip, io_gunzip_getline, zcat...
 io_gunzip:  4 wallclock secs ( 3.01 usr +  0.01 sys =  3.02 CPU) @ 165.56/s (n=500)
io_gunzip_getline:  3 wallclock secs ( 2.58 usr +  0.03 sys =  2.61 CPU) @ 191.57/s (n=500)
      zcat:  2 wallclock secs ( 0.20 usr  0.34 sys +  0.55 cusr  1.10 csys =  2.19 CPU) @ 228.31/s (n=500)
                   Rate         io_gunzip io_gunzip_getline              zcat
io_gunzip         166/s                --              -14%              -27%
io_gunzip_getline 192/s               16%                --              -16%
zcat              228/s               38%               19%                --

# ./zip_test.pl test2.gz 50
Benchmark: timing 50 iterations of io_gunzip, io_gunzip_getline, zcat...
 io_gunzip: 31 wallclock secs (29.67 usr +  0.11 sys = 29.78 CPU) @  1.68/s (n=50)
io_gunzip_getline: 26 wallclock secs (24.86 usr +  0.04 sys = 24.90 CPU) @  2.01/s (n=50)
      zcat:  5 wallclock secs ( 2.42 usr  0.19 sys +  1.19 cusr  0.27 csys =  4.07 CPU) @ 12.29/s (n=50)
                    Rate         io_gunzip io_gunzip_getline              zcat
io_gunzip         1.68/s                --              -16%              -86%
io_gunzip_getline 2.01/s               20%                --              -84%
zcat              12.3/s              632%              512%                --

E eu também não entendo por que "while (<$z>)"É mais lento que"while (my $line = $z->getline())"...

Foi útil?

Solução 2

Eu atualizei minha referência com Perlio :: gzip Como Runrig sugeriu.

Meu benchmark atualizado:

#!/usr/bin/perl

use strict;
use warnings;
use Benchmark qw(cmpthese timethese);
use IO::Uncompress::Gunzip qw(gunzip);
use PerlIO::gzip;

my $re = qr/test/;

my $bench = timethese($ARGV[1], {

  zcat => sub {
    if (defined open(my $FILE, "-|", "zcat " . $ARGV[0]))
    {
      while (<$FILE>)
      {
        print $_  if ($_ =~ $re);
      }
      close($FILE);
    }
  },

  io_gunzip => sub {
    my $z = new IO::Uncompress::Gunzip $ARGV[0];
    while (<$z>)
    {
      print $_  if ($_ =~ $re);
    }
  },

  io_gunzip_getline => sub {
    my $z = new IO::Uncompress::Gunzip $ARGV[0];
    while (my $line = $z->getline())
    {
      print $line if ($line =~ $re);
    }
  },

  perlio_gzip => sub {
    if (defined open(my $FILE, "<:gzip", $ARGV[0]))
    {
      while (<$FILE>)
      {
        print $_  if ($_ =~ $re);
      }
      close($FILE);
    }
  },

} );

cmpthese $bench;

1;

Novos resultados:

# zcat test.gz| wc -l
566
# zcat test2.gz| wc -l
60459
# zcat test3.gz| wc -l
604590
# ./zip_test.pl test.gz 1000
Benchmark: timing 1000 iterations of io_gunzip, io_gunzip_getline, perlio_gzip, zcat...
 io_gunzip:  6 wallclock secs ( 6.07 usr +  0.03 sys =  6.10 CPU) @ 163.93/s (n=1000)
io_gunzip_getline:  6 wallclock secs ( 5.23 usr +  0.02 sys =  5.25 CPU) @ 190.48/s (n=1000)
perlio_gzip:  0 wallclock secs ( 0.62 usr +  0.01 sys =  0.63 CPU) @ 1587.30/s (n=1000)
      zcat:  6 wallclock secs ( 0.37 usr  0.98 sys +  0.94 cusr  2.86 csys =  5.15 CPU) @ 194.17/s (n=1000)
                    Rate    io_gunzip io_gunzip_getline         zcat perlio_gzip
io_gunzip          164/s           --              -14%         -16%        -90%
io_gunzip_getline  190/s          16%                --          -2%        -88%
zcat               194/s          18%                2%           --        -88%
perlio_gzip       1587/s         868%              733%         717%          --
# ./zip_test.pl test2.gz 50
Benchmark: timing 50 iterations of io_gunzip, io_gunzip_getline, perlio_gzip, zcat...
 io_gunzip: 30 wallclock secs (29.50 usr +  0.11 sys = 29.61 CPU) @  1.69/s (n=50)
io_gunzip_getline: 25 wallclock secs (24.85 usr +  0.10 sys = 24.95 CPU) @  2.00/s (n=50)
perlio_gzip:  4 wallclock secs ( 3.22 usr +  0.01 sys =  3.23 CPU) @ 15.48/s (n=50)
      zcat:  4 wallclock secs ( 2.35 usr  0.23 sys +  1.29 cusr  0.28 csys =  4.15 CPU) @ 12.05/s (n=50)
                    Rate    io_gunzip io_gunzip_getline         zcat perlio_gzip
io_gunzip         1.69/s           --              -16%         -86%        -89%
io_gunzip_getline 2.00/s          19%                --         -83%        -87%
zcat              12.0/s         613%              501%           --        -22%
perlio_gzip       15.5/s         817%              672%          28%          --
# ./zip_test.pl test3.gz 50
Benchmark: timing 50 iterations of io_gunzip, io_gunzip_getline, perlio_gzip, zcat...
 io_gunzip: 303 wallclock secs (299.28 usr +  1.30 sys = 300.58 CPU) @  0.17/s (n=50)
io_gunzip_getline: 250 wallclock secs (248.26 usr +  0.79 sys = 249.05 CPU) @  0.20/s (n=50)
perlio_gzip: 32 wallclock secs (32.03 usr +  0.20 sys = 32.23 CPU) @  1.55/s (n=50)
      zcat: 44 wallclock secs (24.64 usr  1.83 sys + 11.93 cusr  1.62 csys = 40.02 CPU) @  1.25/s (n=50)
                  s/iter    io_gunzip io_gunzip_getline         zcat perlio_gzip
io_gunzip           6.01           --              -17%         -87%        -89%
io_gunzip_getline   4.98          21%                --         -84%        -87%
zcat               0.800         651%              522%           --        -19%
perlio_gzip        0.645         833%              673%          24%          --

Perlio :: gzip é a solução mais rápida!

Outras dicas

No hardware típico da área de trabalho, o ZCAT é quase certo de ser limitado em dados não triviais (seus arquivos de amostra são terrivelmente triviais, eles serão tampeados com certeza), nesse caso não haverá nenhum Otimização em nível de código que funcionará para você. Importar um GZIP externo parece perfeito para mim.

E eu também não entendo porque while (<$z>) é mais lento que while (my $line = $z->getline())...

Porque $z é um objeto auto -amarrado, objetos vinculados são notoriamente lentos e <$z> usa a interface de objeto amarrado para chamar getline() em vez de chamar diretamente o método.

Também você pode tentar Perlio-Gzip Mas eu suspeito que não será nada/muito mais rápido que o outro módulo.

A última vez que tentei, desova um externo gunzip foi consideravelmente mais rápido do que usar um módulo Perl (assim como o seu programa de referência). Suspeito que seja todo o método chamado envolvido em amarrar um arquivo de arquivo.

eu espero <$z> é mais lento que $z->getline por um motivo semelhante. Há mais mágica envolvida em descobrir que o primeiro precisa ser traduzido para o segundo.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top