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)
上面的代码只是一个简化的样本.
最终脚本将所有值存储在哈希中,稍后将其写入数据库.
但首先,我必须解决那个记忆问题!
那是因为......你的内存不足了!
您不仅仅是存储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位值.
通常这意味着你的Perl内存不足,但你可能没有用完系统内存.首先,有一些方法可以在perl调试内核文档中获得有关perl内存使用情况的更多信息- 尽管你可能会发现自己正在重新编译perl.(另请注意该文档中关于perl对记忆的渴望的警告......)
但是,许多操作系统可以为每个进程或每个用户设置内存限制.例如,如果您使用的是Linux(或其他POSIX系统),则可能需要更改ulimits.输入'ulimit -a'并查看你的内存大小; 您的"最大内存大小"可能低于计算机内存 - 或者您的数据段大小有限.然后,您可以使用适当的选项重置它,例如ulimit -d 1048576,用于1GB数据段大小限制.
当然,还有另一种选择:如果您的情况允许,逐行处理文件.(上面的示例代码可以用这种方式重写.)