为什么我的Perl脚本死于"内存不足"异常?

Flo*_*Doo 1 database memory perl

我需要逐行读取200mb"空格"分隔文件并将其内容收集到一个数组中.

每次运行脚本时,Perl都会抛出"内存不足"异常,但我不明白为什么!

请问一些建议?

#!/usr/bin/perl -w
use strict;
use warnings;

open my $fh, "<", "../cnai_all.csd";
my @parse = ();

while (<$fh>) {
     my @words = split(/\s/,$_);
     push (@parse, \@words);
}

print scalar @parse;
Run Code Online (Sandbox Code Playgroud)

cnai文件看起来像这样:它包含11000行和4200个值,每行分隔"空格".

VALUE_GROUP_A VALUE_GROUP_B VALUE_GROUP_C 
VALUE_GROUP_A VALUE_GROUP_B VALUE_GROUP_C 
VALUE_GROUP_A VALUE_GROUP_B VALUE_GROUP_C 
VALUE_GROUP_A VALUE_GROUP_B VALUE_GROUP_C 
Run Code Online (Sandbox Code Playgroud)

上面的代码只是一个简化的样本.
最终脚本将所有值存储在哈希中,稍后将其写入数据库.

但首先,我必须解决那个记忆问题!

Jon*_*erg 6

那是因为......你的内存不足了!

您不仅仅是存储200MB的数据.您正在为每一行创建一个新的列表数据结构,其中包含所有相关的开销,并为每个单词创建一堆单独的字符串对象,以及所有相关的开销.

编辑:作为我们在这里谈论的那种开销的一个例子,每个值(包括字符串)都有以下开销:

/* start with 2 sv-head building blocks */
#define _SV_HEAD(ptrtype) \
    ptrtype sv_any;     /* pointer to body */   \
    U32     sv_refcnt;  /* how many references to us */ \
    U32     sv_flags    /* what we are */

#define _SV_HEAD_UNION \
    union {             \
    char*   svu_pv;     /* pointer to malloced string */    \
    IV      svu_iv;         \
    UV      svu_uv;         \
    SV*     svu_rv;     /* pointer to another SV */     \
    SV**    svu_array;      \
    HE**    svu_hash;       \
    GP* svu_gp;         \
    }   sv_u


struct STRUCT_SV {      /* struct sv { */
    _SV_HEAD(void*);
    _SV_HEAD_UNION;
};
Run Code Online (Sandbox Code Playgroud)

这样每个Perl对象至少有4个32位值.


Art*_*ski 5

通常这意味着你的Perl内存不足,但你可能没有用完系统内存.首先,有一些方法可以在perl调试内核文档中获得有关perl内存使用情况的更多信息- 尽管你可能会发现自己正在重新编译perl.(另请注意该文档中关于perl对记忆的渴望的警告......)

但是,许多操作系统可以为每个进程或每个用户设置内存限制.例如,如果您使用的是Linux(或其他POSIX系统),则可能需要更改ulimits.输入'ulimit -a'并查看你的内存大小; 您的"最大内存大小"可能低于计算机内存 - 或者您的数据段大小有限.然后,您可以使用适当的选项重置它,例如ulimit -d 1048576,用于1GB数据段大小限制.

当然,还有另一种选择:如果您的情况允许,逐行处理文件.(上面的示例代码可以用这种方式重写.)