我用Perl在Linux上编写了一个持久的网络服务。不幸的是,随着运行时间的增加,它的Resident Stack Size(RSS)会缓慢但肯定地增长,尽管我已经努力清除了所有不需要的哈希键,并删除了对对象的所有引用,否则将使引用计数保持不变并阻碍垃圾收集。
是否有任何好的工具可以分析Perl程序中各种本地数据基元、散列引用对象等所使用的内存?您用什么来跟踪内存泄漏?
我通常不会花时间在Perl调试器或任何交互式分析器上,因此希望得到一个温暖、温和的非晦涩回答 :-)
我用Perl在Linux上编写了一个持久的网络服务。不幸的是,随着运行时间的增加,它的Resident Stack Size(RSS)会缓慢但肯定地增长,尽管我已经努力清除了所有不需要的哈希键,并删除了对对象的所有引用,否则将使引用计数保持不变并阻碍垃圾收集。
是否有任何好的工具可以分析Perl程序中各种本地数据基元、散列引用对象等所使用的内存?您用什么来跟踪内存泄漏?
我通常不会花时间在Perl调试器或任何交互式分析器上,因此希望得到一个温暖、温和的非晦涩回答 :-)
你的对象之一可能存在循环引用。当垃圾回收器来处理回收该对象时,循环引用意味着该引用所引用的一切都永远不会被释放。您可以使用Devel::Cycle和Test::Memory::Cycle来检查循环引用。另外一个尝试的方法(虽然在生产代码中可能会变得昂贵,因此建议在未设置调试标志时禁用它)是在所有对象的析构函数中检查循环引用:
# make this be the parent class for all objects you want to check;
# or alternatively, stuff this into the UNIVERSAL class's destructor
package My::Parent;
use strict;
use warnings;
use Devel::Cycle; # exports find_cycle() by default
sub DESTROY
{
my $this = shift;
# callback will be called for every cycle found
find_cycle($this, sub {
my $path = shift;
foreach (@$path)
{
my ($type,$index,$ref,$value) = @$_;
print STDERR "Circular reference found while destroying object of type " .
ref($this) . "! reftype: $type\n";
# print other diagnostics if needed; see docs for find_cycle()
}
});
# perhaps add code to weaken any circular references found,
# so that destructor can Do The Right Thing
}
Circular reference found while destroying object of type ActiveState::Config::Node! reftype: ARRAY
] - Chankey PathakDevel::Leak::NoteSV()
?如果我找到答案,我会编辑这个回复。use Devel::Leak;
my $handle; # apparently this doesn't need to be anything at all
my $leaveCount = 0;
my $enterCount = Devel::Leak::NoteSV($handle);
print STDERR "ENTER: $enterCount SVs\n";
# ... code that may leak
$leaveCount = Devel::Leak::CheckSV($handle);
print STDERR "\nLEAVE: $leaveCount SVs\n";
我会尽可能地将代码放在中间部分,让 leaveCount 检查尽可能靠近执行结束(如果有的话) -- 在大多数变量已被解除分配的情况下(如果您无法使变量超出范围,可以将 undef 分配给它以释放其指向的任何内容)。
下一步该尝试什么(不确定是否最好在Alex上面的问题后面发表评论):除了Devel::Leak之外,我会尝试以下方法:
尝试消除程序中“不必要”的部分,或将其分成单独的可执行文件(它们可以使用信号进行通信,或者通过命令行参数相互调用)--目标是将可执行文件简化为仍然展示错误行为的最小代码量。如果您确定不是您的代码在做这件事,请减少使用的外部模块数量,特别是那些具有XS实现的模块。如果可能是您自己的代码,请寻找任何可能存在问题的地方:
\@list
或\%hash
,而不是预分配的引用,如[ qw(foo bar) ](前者创建另一个引用,可能会丢失;在后者中,只有一个引用需要担心,通常存储在本地词法标量中$$foo
其中修改了$foo
,这可能会导致变量的自动初始化(虽然您需要禁用strict 'refs'
检查)我最近使用NYTProf作为一个大型Perl应用程序的分析工具。它不跟踪内存使用情况,但它可以追踪所有执行的代码路径,这有助于找出泄漏源。如果你泄漏的是稀缺资源,如数据库连接,追踪它们的分配和关闭位置将有助于找出泄漏。