Perl内存使用情况分析和泄漏检测?
我在Perl上编写了一个运行在Linux上的持久networking服务。
不幸的是,随着它的运行,其驻留堆栈大小(RSS)正在增长,并且缓慢而稳定地增长和增长。
尽pipe我尽了最大努力来清除所有不需要的散列键,并删除了所有对象的引用,否则这些引用会导致引用计数停留在原位并阻碍垃圾回收。
是否有任何好的工具来分析与Perl程序中的各种本地数据原语,受祝福的哈希引用对象等有关的内存使用情况? 你用什么来追踪内存泄漏?
我不习惯在Perldebugging器或任何各种交互式分析器中花费时间,所以我们将不胜感激。 🙂
你可以在你的对象中有一个循环引用。 当垃圾收集器来解除分配这个对象时,循环引用意味着该引用引用的所有内容都不会被释放。 您可以使用Devel :: Cycle和Test :: Memory :: Cycle检查循环引用。 有一件事要尝试(尽pipe在生产代码中可能会变得昂贵,所以当debugging标志没有设置的时候我会禁用它)正在检查所有对象的析构函数中的循环引用:
# 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 }
您可以使用Devel :: Leak来search内存泄漏。 然而,文档是相当稀疏…例如,只是在哪里得到的$处理引用传递给Devel::Leak::NoteSV()
? 如果我find答案,我会编辑这个答案。
好吧,事实certificate,使用这个模块非常简单(从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检查尽可能接近执行结束(如果有的话) – 在大多数variables被释放后尽可能(如果你不能得到一个超出范围的variables,你可以指定undef来释放它所指向的任何东西)。
下一步尝试(不知道是否这是最好的评论之后,亚历克斯的问题上面虽然):我会尝试下一步(除了Devel ::泄漏):
尽量消除程序中“不必要”的部分,或将其分割成单独的可执行文件(它们可以使用信号进行通信,也可以使用命令行参数进行调用) – 目标是将可执行文件归结为最小量仍然performance出不良行为的代码 。 如果你确定这不是你的代码,那么减less你使用的外部模块的数量,特别是那些有XS实现的模块。 如果这也许是你自己的代码,那么寻找任何可能的诡计:
- 绝对使用Inline :: C或XS代码
- 直接使用引用(例如
\@list
或\%hash
,而不是像[qw(foo bar)]这样的预先分配的引用(前者创build另一个可能会丢失的引用;后者只有一个参考值得担心,它通常存储在本地的词法标量中 - 间接操作variables,例如
$$foo
,其中$foo
被修改,这会导致variables的自动变化(尽pipe您需要禁用strict 'refs'
检查)
Perl手册中包含了一个很好的指导: debuggingPerl内存使用情况
我最近使用NYTProf作为一个大的Perl应用程序的分析器。 它不会跟踪内存使用情况,但它会跟踪所有已执行的代码path,这有助于查明泄漏源于何处。 如果你泄漏的是像数据库连接这样的稀缺资源,那么追踪它们被分配和closures的位置对于发现泄漏有很大的帮助。