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는 사소한 데이터에 대해 I/O 제한적이지만 (샘플 파일은 끔찍하게 사소하고 확실히 버퍼링 될 것입니다). 당신에게 효과가있는 코드 수준 최적화. 외부 GZIP를 산란하는 것은 나에게 완벽 해 보입니다.
그리고 나는 또한 이유를 이해하지 못합니다
while (<$z>)
보다 느립니다while (my $line = $z->getline())
...
왜냐하면 $z
자체 묶인 물체이며, 묶인 물체는 악명 높고 느리고 <$z>
묶인 객체 인터페이스를 사용하여 호출합니다 getline()
방법을 직접 호출하는 대신.
또한 시도 할 수 있습니다 Perlio-Gzip 그러나 나는 그것이 다른 모듈보다 훨씬 빠르지 않을 것이라고 생각합니다.
마지막으로 시도했을 때 외부를 산란 gunzip
PERL 모듈을 사용하는 것보다 훨씬 빠릅니다 (벤치 마크 쇼와 마찬가지로). 파일 핸들링과 관련된 모든 메소드 호출이라고 생각합니다.
나는 기대 <$z>
보다 느립니다 $z->getline
비슷한 이유로. 첫 번째가 두 번째로 번역되어야한다는 것을 알아내는 데 더 많은 마법이 있습니다.