当我在Perl中将文件读入内存时,为什么要耗尽这么多内存?

mik*_*ney 5 perl gzip

我有一个310MB大小的文本文件(未压缩).当使用PerlIO :: gzip打开文件并将其解压缩到内存中时,在perl内存不足之前,此文件很容易填充2GB的RAM.

该文件打开如下:

open FOO, "<:gzip", "file.gz" or die $!;
my @lines = <FOO>;
Run Code Online (Sandbox Code Playgroud)

显然,这是一种在perl中轻松打开gzip文件的超级便捷方式,但它占用了大量的空间!我的下一步是将文件解压缩到HD,将文件行读取到@lines,在@lines上操作,然后将其压缩.有没有人知道为什么打开压缩文件时消耗的内存超过7倍?有没有人有一个替代的想法,我怎么能解压缩这个gzip文件到内存而不占用大量的内存?

raf*_*afl 22

您正在将文件的所有内容读入@lines数组.当然,这会将所有未压缩的内容拉入内存.您可能想要的是逐行读取句柄,只在内存中保留一行:

open my $foo, '<:gzip', 'file.gz' or die $!;
while (my $line = <$fh>) {
    # process $line here
}
Run Code Online (Sandbox Code Playgroud)


Sin*_*nür 17

当你这样做时:

my @lines = <FOO>;
Run Code Online (Sandbox Code Playgroud)

你正在创建一个数组,其元素与行数一样多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 ".";
}
Run Code Online (Sandbox Code Playgroud)

没有问题.

要了解内存开销,请注意:

#!/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 );
Run Code Online (Sandbox Code Playgroud)

输出:

Scalar: 136
Array:  256