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

Ale*_*hov 33 debugging perl profiler memory-leaks memory-management

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

不幸的是,随着它的运行,它的Resident Stack Size(RSS)只是在缓慢但肯定地增长,增长和增长.

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

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

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

Eth*_*her 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
}
Run Code Online (Sandbox Code Playgroud)

  • 嗨以太 - 尝试了UNIVERSAL :: DESTROY(),运行服务很长一段时间并对它进行攻击,并没有得到任何东西.与此同时,RSS正在逐步上升.如果不是循环引用问题,还有什么可能呢? (2认同)
  • 我真的不确定如何在析构函数中查找内存泄漏会对您有所帮助.如果你正在泄漏,永远不会被称为DESTROY. (2认同)

Eth*_*her 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";
Run Code Online (Sandbox Code Playgroud)

我会在中间部分放置尽可能多的代码,尽可能将leaveCount检查尽可能接近执行结束(如果你有的话) - 在大多数变量被尽可能解除分配后(如果你不能得到)一个变量超出范围,你可以为它分配undef以释放它所指向的任何东西).