我有一个310MB大小的文本文件(未压缩)。当使用PerlIO::gzip打开文件并将其解压缩到内存中时,在perl耗尽内存之前,此文件很容易填充2GB的RAM。
文件打开如下:
open FOO, "<:gzip", "file.gz" or die $!;
my @lines = <FOO>;
显然,这是一种在perl中轻松打开gzip文件的超级便捷方式,但它占用了大量的空间!我的下一步是将文件解压缩到HD,将文件行读取到@lines,在@lines上操作,然后将其压缩。有没有人知道为什么打开压缩文件时消耗的内存超过7倍?有没有人对如何将这个gzip压缩文件解压缩到内存中而不采用可笑的内存量有另一种想法?
答案 0 :(得分:22)
您正在将该文件的所有内容读入@lines
数组。当然,这会将所有未压缩的内容拉入内存。您可能想要的是逐行读取句柄,一次只在内存中保留一行:
open my $foo, '<:gzip', 'file.gz' or die $!;
while (my $line = <$fh>) {
# process $line here
}
答案 1 :(得分:17)
当你这样做时:
my @lines = <FOO>;
您正在创建一个数组,其元素与file
中的行数一样多。每行100个字符,大约有340万个数组条目。每个数组条目都会产生开销,这意味着内存占用量将远远大于文件的未压缩大小。
您可以逐行避免诽谤和处理文件。这是一个例子:
C:\Temp> dir file 2010/10/04 09:18 PM 328,000,000 file
C:\Temp> dir file.gz 2010/10/04 09:19 PM 1,112,975 file.gz
事实上,
#!/usr/bin/perl
use strict; use warnings;
use autodie;
use PerlIO::gzip;
open my $foo, '<:gzip', 'file.gz';
while ( my $line = <$foo> ) {
print ".";
}
没有问题。
要了解内存开销,请注意:
#!/usr/bin/perl
use strict; use warnings;
use Devel::Size qw( total_size );
my $x = 'x' x 100;
my @x = ('x' x 100);
printf "Scalar: %d\n", total_size( \$x );
printf "Array: %d\n", total_size( \@x );
输出:
Scalar: 136 Array: 256
答案 2 :(得分:-5)
有了这么大的文件,我只看到一个解决方案:你可以使用命令行来解压缩/压缩文件。在Perl中进行操作,然后再使用外部工具压缩/解压缩文件:)