Question

Y at-il une solution plus rapide que ma solution 'zcat' réelle pour les dézipper des fichiers avec Perl?

Un peu de référence:

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

me donner ces résultats:

# 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%                --

Je ne comprends pas pourquoi « while (<$z>) » est plus lent que « while (my $line = $z->getline()) » ...

Était-ce utile?

La solution 2

Je mis à jour mon référence avec PerlIO :: gzip comme Runrig a suggéré.

Mon indice de référence mis à jour:

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

De nouveaux résultats:

# 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 est la solution la plus rapide!

Autres conseils

Sur le matériel de bureau typique, le zcat est presque certain d'être d'E / S limité sur des données non trivial (vos exemples de fichiers sont terriblement trivial, ils vont être mises en mémoire tampon pour sûr), auquel cas il n'y aura pas être une optimisation au niveau du code qui fonctionnera pour vous. Frai un gzip externe me semble parfait.

  

Je ne comprends pas pourquoi while (<$z>) est plus lent que while (my $line = $z->getline()) ...

Parce que $z est un auto objet lié, les objets liés sont notoirement lents, et <$z> utilise l'interface objet lié à appeler getline() plutôt que d'appeler directement la méthode.

Vous pouvez également essayer PerlIO-gzip mais je pense que ce ne sera pas être une / beaucoup plus rapide que l'autre module.

La dernière fois que je l'ai essayé, fraye un gunzip externe a été nettement plus rapide que d'utiliser un module Perl (comme vos repères montrent). Je soupçonne que ce sont tous les appels de méthode impliqués à lier un descripteur de fichier.

Je pense <$z> est plus lent que $z->getline pour une raison similaire. Il y a plus de magie impliquée dans déterminer que le premier doit être traduit dans la seconde.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top