Pregunta

¿Hay una solución más rápida que mi solución real 'zcat' a gunzip archivos con Perl?

Un poco de referencia:

#!/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;

dame estos 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%                --

Y también no entiendo por qué "while (<$z>)" es más lenta que "while (my $line = $z->getline())" ...

¿Fue útil?

Solución 2

He actualizado mi punto de referencia con PerlIO :: gzip como Runrig sugirió.

Mi referencia actualización:

#!/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;

Los nuevos 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 es la solución más rápida!

Otros consejos

En el hardware de escritorio típico, el zcat es casi seguro que será de E / S limitado en los datos no triviales (los archivos de muestra son muy triviales, que van a ser amortiguada con seguridad), en cuyo caso no va a ser cualquier optimización a nivel de código que funcione para usted. Desove un gzip externa me parece perfecto.

  

Y también no entiendo por qué while (<$z>) es más lento que while (my $line = $z->getline()) ...

Debido $z es un objeto atado auto, los objetos vinculados son notoriamente lentos, y <$z> utiliza la interfaz de objeto atado a llamar getline() en lugar de llamar directamente el método.

También puede intentar PerlIO-gzip pero sospecho que no lo hará ser cualquier / mucho más rápido que el otro módulo.

La última vez que lo probé, generando un gunzip externa fue considerablemente más rápido que el uso de un módulo de Perl (al igual que sus puntos de referencia muestran). Sospecho que es todas las llamadas a métodos involucrados en atar un gestor de archivo.

espero <$z> es más lento que $z->getline por una razón similar. Hay más magia involucrada en averiguar que la primera tiene que ser traducido en el segundo.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top