繁体   English   中英

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

[英]Perl memory usage profiling and leak detection?

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

不幸的是,随着它的运行,其驻留堆栈大小(RSS)只是缓慢但肯定地增长,增长和增长。

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

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

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

您可以在其中一个对象中使用循环引用。 当垃圾收集器出现以释放此对象时,循环引用意味着该引用引用的所有内容永远不会被释放。 您可以使用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
}

您可以使用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以释放它所指向的任何东西)。

接下来要尝试什么(不知道在上面的Alex问题之后这是否最好放在评论中):我接下来会尝试什么(除了Devel :: Leak):

尝试消除程序的“不必要”部分,或将其划分为单独的可执行文件(它们可以使用信号进行通信,或者使用命令行参数相互调用) - 目标是将可执行文件分解为最小量代码仍然表现出不良行为 如果您确定不是您的代码正在执行此操作,请减少您正在使用的外部模块的数量,尤其是那些具有XS实现的模块。 如果它可能是你自己的代码,那么找一些可能有些可疑的东西:

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

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

Perl手册中包含了一个很好的指南: 调试Perl内存使用情况

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM