我有一个需要在后台不断运行的perl脚本。它由几个.pm
模块文件和一个主.pl
文件组成。该程序的作用是定期收集一些数据,进行一些计算,最后更新记录在文件中的结果。
所有关键数据结构都在.pl
文件中使用our
声明,并且在任何.pm
文件中都没有声明包变量。
我使用arena_table()
模块中的函数Devel::Gladiator
来生成主循环中有关竞技场的一些信息,并发现SCALAR
和GLOB
类型的SV正在缓慢增加,导致内存使用量逐渐增加。
arena_table
的输出(我重新格式化它们,省略标题。经过足够长的时间后,只有前两个数字增加):
2013-05-17@11:24:34 36235 3924 3661 3642 3376 2401 720 201 27 23 18 13 13 10 2 2 1 1 1 1 1 1 1 1 1 1
跑了一段时间后:
2013-05-17@12:05:10 50702 46169 36910 4151 3995 3924 2401 720 274 201 26 23 18 13 13 10 2 2 1 1 1 1 1 1 1 1 1
主循环类似于:
our %hash1 = ();
our %hash2 = ();
# and some more package variables ...
# all are hashes
do {
my $nowtime = time();
collect_data($nowtime);
if (calculate() == 1) {
update();
}
sleep 1;
get_mem_objects(); # calls arena_table()
} while (1);
get_mem_objects
除外,其他函数将对our
声明的全局哈希值进行操作。在update
中,程序将进行一些日志轮换,代码如下:
sub rotate_history() {
my $i = $main::HISTORY{'count'};
if ($i == $main::CONFIG{'times'}{'total'}) {
for ($i--; $i >= 1; $i--) {
$main::HISTORY{'data'}{$i} = dclone($main::HISTORY{'data'}{$i-1});
}
} else {
for (; $i >= 1; $i--) {
$main::HISTORY{'data'}{$i} = dclone($main::HISTORY{'data'}{$i-1});
}
}
$main::HISTORY{'data'}{'0'} = dclone(\%main::COLLECT);
if ($main::HISTORY{'count'} < $main::CONFIG{'times'}{'total'}) {
$main::HISTORY{'count'}++;
}
}
如果我评论对此函数的调用,在Devel::Gladiator
给出的最终报告中,只有SCALAR
类型的SV正在增加,GLOB
的数量最终会进入稳定的状态。我怀疑dclone
可能会导致此问题。
我的问题是,