Chinaunix

标题: perl out of memory [打印本页]

作者: qfmeal    时间: 2009-07-14 12:59
标题: perl out of memory
脚本需要读取几个较大的文件,有1000多万行,100多兆。

把这个文件加载到内存时出错。out of memory。

但是事实上这台机子内存有120G,

机子是 HP-UX 。 perl -v 5.8.8 不知道是不是perl 对内存有限制,还是系统对分配的内存有限制?
作者: flw    时间: 2009-07-14 13:12
120G 是整个系统的内存。
在 Linux 上,单个进程的最大内存限制是 3G。

试着优化一下你的程序吧。
解决同一个问题有很多种方式,但通常都没必要挑战这个极限。
作者: Perl_Er    时间: 2009-07-14 13:13
标题: 回复 #1 qfmeal 的帖子
你是怎么读的?把代码贴出来啊。
120G内存,难道是HP的superdome

[ 本帖最后由 Perl_Er 于 2009-7-14 13:15 编辑 ]
作者: DQP    时间: 2009-07-14 13:53
100多兆不算大 如果out of memory了 那你的程序肯定有别的问题.
作者: MMMIX    时间: 2009-07-14 14:15
原帖由 flw 于 2009-7-14 13:12 发表
120G 是整个系统的内存。
在 Linux 上,单个进程的最大内存限制是 3G。

楼主用的应该不是 Linux.
作者: qfmeal    时间: 2009-07-14 14:30
机子是惠普unix,64位机
perl版本是5.8.8
120G内存,20、30个CPU

之所以把那么大的文件读进内存,是因为,脚本里面要不断的在那个文件里面搜索数据.
我的代码其中读取文件的部分(我的代码比较烂...):


# 加载account数据

my $hash_account            = &get_account_hash();


sub get_account_hash
{
    my $file = "$ENV{OUT}/ocs_account.tmp";
    open FH,$file or die "open $file error!";
    my %hash;
&nbsp;&nbsp;&nbsp;&nbsp;while(<FH>)
&nbsp;&nbsp;&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;chomp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;my ($acc_id,$cust_id,@left) = split /\|/;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$hash{$cust_id} = [$acc_id,$cust_id,@left];
&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;&nbsp;close FH;
&nbsp;&nbsp;&nbsp;&nbsp;return \%hash;&nbsp;&nbsp;&nbsp;&nbsp;
}

作者: orangetouch    时间: 2009-07-15 10:29
>>> 1000多万行,100多兆
你一行才10几个字节?定长?
作者: lokchungk    时间: 2009-07-15 10:32
标题: 回复 #6 qfmeal 的帖子
請問這樣和把整個檔案讀到記憶體有什麼分別?
作者: Perl_Er    时间: 2009-07-15 10:46
标题: 回复 #6 qfmeal 的帖子
得到这些数据后,你想要做的是什么了?
作者: Perl小手    时间: 2009-07-15 11:46
只有100多M的文件应该不会out of memory啊. 除非你的server上还有别的啥东西在抢占资源。
作者: qfmeal    时间: 2009-07-15 15:35
每行的各个字段是由 | 分隔。不定长。
就像我建的那个hash。
$hash{$cust_id} = [$acc_id,$cust_id,@left];
将来要用这个hash的key和别的文件的数据找对应关系等许多操作。

因为要找对应关系,所以我不可能每找一次,就把这1000多万行的文件遍历一次吧。

[ 本帖最后由 qfmeal 于 2009-7-15 16:02 编辑 ]
作者: Perl_Er    时间: 2009-07-15 15:39
标题: 回复 #11 qfmeal 的帖子
你有没有数据库啊,如果很频繁的话。把这些数据存到数据库。那样操作会快些吧. 你的数据好像是informix export出来的数据
作者: qfmeal    时间: 2009-07-15 16:06
嗯   是从几个老系统数据库里导出来的数据。
现在要把这些数据移到新系统里。
老系统数据有很多冗余的和错误的,所以才有了这个需求:把旧数据筛选匹配转换后放到新系统的数据库。
作者: billypeng    时间: 2009-07-15 21:22
标题: 回复 #6 qfmeal 的帖子
建议你用BerkeleyDB管理数据,perl毕竟是一个脚本语言,管理内存方面不是它的强项。BerkeleyDB使用起来和hash差不多,但却是真正一个数据库系统(非关系型的),无论是处理速度还是管理数据量的大小,都能够达到你的要求,应用起来会给你更多的惊喜。
作者: Perl_Er    时间: 2009-07-16 07:30
BerkeleyDB 真的那么好用吗,有空去试试!
作者: qfmeal    时间: 2009-07-17 21:33
这个问题用设置 ulimit 的方法解决了
作者: yhou31    时间: 2010-04-02 14:25
我碰到类似的问题,设置了ulimit,还是内存溢出。程序是想用对照表中的记录替换源文件,如
源文件:
1
23
033
04567

对照表
1 first
23 second
033 thrid
04567 fourth

程序执行后将源文件内容替换为
first
second
thrid
fourth

程序如下:
#!/usr/bin/perl -w

use strict;

if (@ARGV != 3)
{
    print "You need input 3 argument,Usage: \t  $0 reflect-file tochange-file ou
tput-file \n";
    exit 1;
}

my $dic = shift;          #reflect
my %dich;                 #hash
my $file = shift;         #tochange file
my $outfile = shift;    #output file

unless(-e $dic)
{
    system "touch","$dic";
}

open(DIC,"$dic") or die "open reflect file failed $!";

while(<DIC>)
{
    chomp;
    (my $key,my $value) = split / /;
    $dich{$key} = $value;
}

close DIC;

open(F,"$file") or die "open tochange file failed $!";
open(DEST,">>$outfile") or die "open output file failed $!";

my $loop;
open(PT,"serialno.txt") or die "open serialno file failed $!";
while(<PT>)
{
    chomp;
    $loop=$_;
    last;
}

close PT;

my $str;
open(DIC,">>$dic") or die "open reflect file failed $!";
while(<F>)
{
    chomp;
    if(defined($dich{$_})){
        print DEST $dich{$_}."\n";
    }else{
        $str=sprintf("%s%014d",substr($_,0,4),++$loop);
        $dich{$_} = $str;
        print DIC $_." ".$str."\n";
        print DEST $dich{$_}."\n";
    }
}

open(PT,">serialno.txt") or die "open serialno file failed $!";
print PT $loop;

close DIC;
close F;
close DEST;
close PT;


说明:我的源文件有几千万行,这可能是导致out of memory的原因。
是否有其它解决办法?
作者: yybmsrs    时间: 2010-04-02 17:19
回复 17# yhou31


    可能是你内存还是太小了。导进数据库应该很方便。




欢迎光临 Chinaunix (http://bbs.chinaunix.net/) Powered by Discuz! X3.2