2010-10-05 31 views
5

我有一個310MB大小的文本文件(未壓縮)。當使用PerlIO::gzip打開文件並將其解壓縮到內存中時,在perl內存不足之前,該文件很容易填充2GB的RAM。當我在Perl中將文件讀入內存時,爲什麼會耗盡這麼多內存?

打開文件如下:

open FOO, "<:gzip", "file.gz" or die $!; 
my @lines = <FOO>; 

很顯然,這是很容易在Perl中打開gzip壓縮文件超級方便的方法,但它佔用的空間,一個可笑的金額!我的下一步是將文件解壓縮到HD,將文件的行讀取到@lines,在@lines上進行操作,然後將其壓縮回去。有沒有人知道爲什麼打開一個壓縮文件時消耗超過7倍的內存?有沒有人有另一種想法,我可以如何解壓縮這個gzip文件到內存中,而不會佔用大量的內存?

+0

也,Perl 5.12.1 64在Mac OS X 10.6 – 2010-10-05 01:09:19

+8

你剛纔問的問題第七千標記在stackoverflow上的'perl'。恭喜! :-) – rafl 2010-10-05 01:36:06

回答

17

當你這樣做:

my @lines = <FOO>; 

要創建一個使用,因爲在file線儘可能多元素的數組。每行100個字符,即大約340萬個數組條目。每個數組條目都有相關的開銷,這意味着內存佔用量將遠遠大於文件的未壓縮大小。

您可以避免sl and並逐行處理文件。這裏有一個例子:

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
22

您正在將文件的所有內容讀取到@lines陣列中。當然,這會將所有未壓縮的內容拉入內存。你可能會想,而不是從你的手柄線,由線讀取,只保持一條線在同一時間內存:

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

由於壓縮需要一些空間來處理,所以這不會在內存中保留一行。 – 2011-03-30 08:41:42

-6

有了這麼大的文件,我看到的只有一個解決辦法:你可以使用命令行解壓縮/壓縮文件。請您在Perl操作,然後再使用外部工具來壓縮/解壓縮文件:

+1

可以在Perl 5中執行所有這些操作,而無需藉助外部工具。問題是將所有數據一次讀入內存,而不是逐行處理。 – 2010-10-05 17:10:11

相關問題