【发布时间】:2013-01-07 03:33:56
【问题描述】:
我从数据库中接收到大约 7000 个对象,并将每个项目写入一个 JSON 文件。
大约 2000 个对象后,perl 以 Out of memory 错误终止。一开始,所有数据库对象都被接收,显然它们完全适合内存。错误发生在循环期间。
我对 perl 很陌生,我不知道为什么会发生这种情况。在我看来,循环中没有内存分配在每次迭代后都无法释放。
这是我的代码:
use lib '../AcePerl/blib/lib','../AcePerl/blib/arch';
use Ace;
use JSON;
use Data::Structure::Util qw( unbless );
use List::MoreUtils;
use strict vars;
use constant HOST => $ENV{ACEDB_HOST} || 'mining.wormbase.org';
use constant PORT => $ENV{ACEDB_PORT} || 2005;
$|=1;
my $json = JSON->new->allow_nonref;
print "Opening the database....";
my $db = Ace->connect(-host=>HOST,-port=>PORT
-cache => {
cache_root => '/usr/tmp/acedb',
cache_depth => 4,
default_expires_in => '1 week'
}
) || die "Connection failure: ",Ace->error;
print "done.\n";
#my @anatomies = $db->list('Anatomy_Term','WBbt:000547*');
my @anatomies = $db->fetch(-name => '*',
-class => 'Anatomy_Term',
-fill => true,
# -count => 10
);
#my @anatomies = $db->list('Anatomy_Term','*');
print scalar(@anatomies), " anatomy terms found!\n";
my $i = 0;
my $c;
sub wbstr {
my $arg = $_[0];
if(!defined $arg) {
return undef;
}else{
return $arg->name;}
}
# parse anatomy terms for cells
my %anatomy_data;
open (MYFILE, '>anatomy-data2.txt');
print MYFILE '{';
my $parent;
my $first;
my $ancestor;
my $expr_ancestor;
my $is_a;
foreach $c (@anatomies) {
if($i!=0) {
print MYFILE ',';
}
$i++;
print MYFILE $json->encode(wbstr($c)), ':{';
print MYFILE '"term":', $json->encode(wbstr($c->Term)), ',';
print MYFILE '"definition":', $json->encode(wbstr($c->Definition)), ',';
print MYFILE '"synonym":', $json->encode(wbstr($c->Synonym)), ',';
print MYFILE '"parents":[';
$first = true;
foreach $parent ($c->CELL_p) {
if($first eq false) {
print MYFILE ',';
}
print MYFILE $json->encode(wbstr($parent));
$first = false;
}
print MYFILE '],';
print MYFILE '"ancestors":[';
$first = true;
foreach $ancestor ($c->Ancestor) {
if($first eq false) {
print MYFILE ',';
}
print MYFILE $json->encode(wbstr($ancestor));
$first = false;
}
print MYFILE '],';
print MYFILE '"expr_ancestors":[';
$first = true;
foreach $expr_ancestor ($c->Expr_ancestor) {
if($first eq false) {
print MYFILE ',';
}
print MYFILE $json->encode(wbstr($expr_ancestor));
$first = false;
}
print MYFILE '],';
print MYFILE '"is_a":[';
$first = true;
foreach $is_a ($c->IS_A_p) {
if($first eq false) {
print MYFILE ',';
}
print MYFILE $json->encode(wbstr($is_a));
$first = false;
}
print MYFILE ']}';
}
print MYFILE '}';
print "Done\n";
close (MYFILE);
【问题讨论】:
-
注:
true和false在 Perl 中不是保留字。 -
您应该使用
use warnings; use strict;运行。您可能隐藏了许多错误。事实上,你说$first = true的地方应该发出警告,因为那是$first = "true"的古老等价物。添加警告/严格,看看会发生什么。它可能无法解决您的记忆问题,但会导致您正在做的坏事。 -
好的,我最好使用 fetch_many() 而不是 fetch()。这样我就不会遇到记忆问题。 ;)
-
我想知道如果您在处理完
shift条目超出@anatomies之后,行为是否会改变? -
@user2004469 那么这是通过使用 fetch_many() 解决的吗?那么请自己回答。
标签: perl