我有一个需要在后台不断运行的 perl 脚本。它由几个.pm
模块文件和一个主.pl
文件组成。程序所做的是定期收集一些数据,进行一些计算,最后更新记录在文件中的结果。
所有关键数据结构都在.pl
文件中声明,并且在任何文件our
中都没有声明包变量。.pm
我使用模块中的函数arena_table()
在Devel::Gladiator
主循环中生成了一些关于arena的信息,发现typeSCALAR
和的SVsGLOB
在缓慢增加,导致内存使用量逐渐增加。
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
,只有 type 的 SVs 在SCALAR
增加,GLOB
s 的数量最终会进入稳定状态。我怀疑这dclone
可能会导致问题。
我的问题是,
- 该模块提供的信息究竟是什么意思?perldoc 中的陈述对于像我这样的 perl 新手来说有点模糊。
- 还有,降低长时间运行的 perl 脚本的内存使用的常用技巧是什么?
- 我知道包变量存储在竞技场中,但是词法变量呢?他们消耗的内存是如何管理的?