34

Linux上で動作するPerlで永続的なネットワークサービスを作成しました。

残念ながら、実行すると、その常駐スタックサイズ(RSS)は、ゆっくりと、しかし確実に、大きくなり、大きくなり、大きくなります。

これは、不要なハッシュキーをすべて消去し、オブジェクトへのすべての参照を削除するための私の側の勤勉な努力にもかかわらずです。そうしないと、参照カウントがそのまま残り、ガベージコレクションが妨げられます。

Perlプログラム内のさまざまなネイティブデータプリミティブ、祝福されたハッシュ参照オブジェクトなどに関連するメモリ使用量をプロファイリングするための優れたツールはありますか?メモリリークを追跡するために何を使用しますか?

私はPerlデバッガーやさまざまなインタラクティブプロファイラーのいずれにも習慣的に時間を費やしていないので、温かく、穏やかで、非難解な応答をいただければ幸いです。:-)

4

5 に答える 5

15

オブジェクトの1つに循環参照を含めることができます。ガベージコレクターがこのオブジェクトの割り当てを解除するためにやってくると、循環参照は、その参照によって参照されるすべてのものが解放されることは決してないことを意味します。Devel::CycleおよびTest::Memory::Cycleを使用して循環参照を確認できます。試してみる1つのこと(本番コードではコストがかかる可能性があるため、デバッグフラグが設定されていない場合は無効にします)は、すべてのオブジェクトのデストラクタ内の循環参照をチェックすることです。

# 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
}
于 2009-09-01T01:19:33.547 に答える
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を割り当てて、指しているものをすべて解放できます)。

于 2009-09-01T01:23:15.820 に答える
4

次に試すこと(上記のAlexの質問の後にコメントに入れるのが最適かどうかはわかりませんが):次に試すこと(Devel :: Leak以外):

プログラムの「不要な」部分を削除するか、プログラムを個別の実行可能ファイルに分割してみてください(シグナルを使用して通信したり、コマンドライン引数を使用して相互に呼び出したりすることができます)。目標は、実行可能ファイルを最小限に抑えることです。まだ悪い振る舞いを示すコードの。それを実行しているのがコードではないことが確実な場合は、使用している外部モジュール、特にXS実装を備えたモジュールの数を減らしてください。おそらくそれがあなた自身のコードである場合は、潜在的に怪しいものを探してください。

  • 間違いなくInline::CまたはXSコードの使用
  • [qw(foo bar)]のような事前に割り当てられた参照ではなく、たとえば\@listまたはの参照を直接使用し\%hashます(前者は失われる可能性のある別の参照を作成します。後者では、心配する必要のある参照が1つだけあり、通常はローカル字句スカラー
  • 変数を間接的に操作します。たとえば、変更された$$foo場所では、変数の自動生存が発生する可能性があります(ただし、チェック$fooを無効にする必要があります)strict 'refs'
于 2009-09-01T03:18:24.433 に答える
3

私は最近、大規模なPerlアプリケーションのプロファイラーとしてNYTProfを使用しました。メモリ使用量は追跡しませんが、実行されたすべてのコードパスを追跡し、リークの発生場所を特定するのに役立ちます。リークしているのがデータベース接続などのリソースが不足している場合、それらが割り当てられて閉じられている場所を追跡することは、リークを見つけるのに大いに役立ちます。

于 2010-09-14T18:49:56.197 に答える
2

これに関する優れたガイドは、Perlのマニュアルに含まれています:Perlのメモリ使用量のデバッグ

于 2009-11-03T17:45:23.057 に答える