Perlでファイルをgunzipしするための最良の方法は何ですか?
-
20-09-2019 - |
質問
はPerlでファイルをgunzipして私の実際の「zcatの」ソリューションよりも早く解決策はありますか?
少しベンチマークます:
#!/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;
私にこれらの結果が得られます:
# 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% --
そして、私も理解していない理由を「while (<$z>)
」「while (my $line = $z->getline())
」より遅い...
解決 2
私は私のベンチマークを更新はPerlIO :: gzipののrunrigが示唆されているように。
私の更新ベンチマークます:
#!/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;
新しい結果:
# 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のの最速のソリューションです!
他のヒント
一般的なデスクトップのハードウェアでは、zcatのは、そこに行くされていない場合には、すべてが、私は/ Oの非自明なデータに限定されるように、特定の(あなたのサンプルファイルがひどくつまらないあり、それは確かにバッファリングされます)、ありますあなたのために動作する任意のコードレベルの最適化を可能にします。外部のgzipを産卵することは私には完璧なようです。
そして
より遅いなぜ私も理解していませんwhile (<$z>)
がwhile (my $line = $z->getline())
...
$z
自己関連付けられたオブジェクトであるため、は、関連付けられたオブジェクトは、悪名高い遅く、<$z>
直接メソッドを呼び出すのではなく、getline()
をコールに関連付けられたオブジェクト・インターフェースを使用します。
また君には PerlIOを-gzipのを試すことができますが、私はそれはないでしょう疑いいずれであっても/はるかに速く、他のモジュールよります。
私は、外部gunzip
を産卵、それを試みた最後の時間は、(あなたのベンチマークが示すと同じように)Perlモジュールを使用するよりもかなり速かったです。私はそれがファイルハンドルを結ぶに関係するすべてのメソッド呼び出しだ疑います。
私は<$z>
は、同様の理由$z->getline
より遅い期待しています。最初は、第二に翻訳する必要があることを考え出すに関わる多くの魔法があります。