我在Perl上编写了一个在Linux上运行的持久性网络服务。
不幸的是,随着它的运行,它的Resident Stack Size(RSS)只会慢慢地增长,增长和增长。
尽管我努力消除所有不需要的哈希键并删除对象的所有引用,否则会导致引用计数保留在原位并阻碍垃圾收集。
是否有任何好的工具可以在Perl程序中分析与各种本机数据原语,祝福哈希引用对象等相关的内存使用情况?你用什么来追踪内存泄漏?
我不习惯在Perl调试器或任何各种交互式分析器中花费时间,因此我们将非常感谢温暖,温和,非深奥的回应。 : - )
答案 0 :(得分:14)
您可以在其中一个对象中使用循环引用。当垃圾收集器出现以释放此对象时,循环引用意味着该引用引用的所有内容永远不会被释放。您可以使用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
}
答案 1 :(得分:10)
您可以使用Devel::Leak搜索内存泄漏。但是,文档很稀疏...例如,只有将$ handle引用传递给Devel::Leak::NoteSV()
的位置? f我找到了答案,我将编辑此回复。
好吧事实证明使用这个模块非常简单(代码从Apache::Leak无耻地窃取):
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以释放它指向的任何东西。
答案 2 :(得分:4)
接下来要尝试什么(不知道在上面的Alex问题之后这是否最好放在评论中):我接下来会尝试什么(除了Devel :: Leak):
尝试消除程序的“不必要”部分,或将其划分为单独的可执行文件(它们可以使用信号进行通信,或者使用命令行参数调用彼此) - 目标是归结为可执行文件到仍然表现出不良行为的最少量代码。如果您确定不是您的代码正在执行此操作,请减少您正在使用的外部模块的数量,尤其是那些具有XS实现的模块。如果它可能是你自己的代码,那么找一些可能有些可疑的东西:
\@list
或\%hash
,而不是预先分配的引用,如[qw(foo bar)](前者创建了另一个可能丢失的引用;在后者中,只有一个引用可以担心,这是通常存储在本地词法标量中$$foo
其中$foo
被修改,可导致变量自动生成(尽管您需要禁用strict 'refs'
检查)答案 3 :(得分:3)
我最近使用NYTProf作为大型Perl应用程序的分析器。它不跟踪内存使用情况,但它会跟踪所有已执行的代码路径,这有助于找出泄漏源自何处。如果您泄漏的是稀缺的资源,例如数据库连接,那么跟踪它们被分配和关闭的位置对于发现泄漏很有帮助。
答案 4 :(得分:2)
Perl手册中包含了一个很好的指南:Debugging Perl memory usage