Perl内存使用情况分析和泄漏检测?

时间:2009-08-31 22:54:41

标签: perl debugging memory-leaks memory-management profiler

我在Perl上编写了一个在Linux上运行的持久性网络服务。

不幸的是,随着它的运行,它的Resident Stack Size(RSS)只会慢慢地增长,增长和增长。

尽管我努力消除所有不需要的哈希键并删除对象的所有引用,否则会导致引用计数保留在原位并阻碍垃圾收集。

是否有任何好的工具可以在Perl程序中分析与各种本机数据原语,祝福哈希引用对象等相关的内存使用情况?你用什么来追踪内存泄漏?

我不习惯在Perl调试器或任何各种交互式分析器中花费时间,因此我们将非常感谢温暖,温和,非深奥的回应。 : - )

5 个答案:

答案 0 :(得分:14)

您可以在其中一个对象中使用循环引用。当垃圾收集器出现以释放此对象时,循环引用意味着该引用引用的所有内容永远不会被释放。您可以使用Devel::CycleTest::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实现的模块。如果它可能是你自己的代码,那么找一些可能有些可疑的东西:

  • 绝对使用Inline :: C或XS代码
  • 直接使用参考文献,例如\@list\%hash,而不是预先分配的引用,如[qw(foo bar)](前者创建了另一个可能丢失的引用;在后者中,只有一个引用可以担心,这是通常存储在本地词法标量中
  • 间接操纵变量,例如$$foo其中$foo被修改,可导致变量自动生成(尽管您需要禁用strict 'refs'检查)

答案 3 :(得分:3)

我最近使用NYTProf作为大型Perl应用程序的分析器。它不跟踪内存使用情况,但它会跟踪所有已执行的代码路径,这有助于找出泄漏源自何处。如果您泄漏的是稀缺的资源,例如数据库连接,那么跟踪它们被分配和关闭的位置对于发现泄漏很有帮助。

答案 4 :(得分:2)

Perl手册中包含了一个很好的指南:Debugging Perl memory usage