3

操作中にいくつかの (約 3 または 4) クラスの多くのオブジェクトを使用する Perl ライブラリがあります。

コードのテストでは、多すぎないようにしたいと思います (メモリ リークについて話しているのではなく、それを確認する方法を知っています)。この目的のために、使用されたすべてのオブジェクトを数え、実行中に使用された最大値をテスト データで確認できると考えました。次に、得られた数を、ライブラリが使用する必要があるオブジェクトの数についての推測と比較します。

ただし、これを実装するには問題があります。私は2つの可能な方法を考えました:

  • インターセプトPackage::newPackage::DESTROY. ただし、これには、そのパッケージでnew常に新しいオブジェクトが返されるとは限らないという小さな問題があります。場合によっては、既存のものを使用します (オブジェクトは不変オブジェクトとして使用されるため、あまり問題にはなりません)。そのため、個々のオブジェクトを追跡して、それが以前に存在したかどうかを確認する必要があります。

  • インターセプトPackage::blessPackage::DESTROY. これは機能するはずですが、少し異例のようです。

問題は、これらの方法のどれが成功する可能性が高いか (おそらく、同様の状況で一般的に使用される方法)、2 番目の方法をどのように実装するか (Package::bless問題のすべてのパッケージまたは基本クラスのみをオーバーライドする必要があるかどうか) です。等。)。

4

4 に答える 4

2

このようなことを試してください(テストされていません):

my $Package_objects = {};
my $override_new = *Package::new{CODE};
*Package::new = sub {
    my $self = $override_new->(@_);
    # Interpolate $self as string to get "HASH(0x12345)"; save package name
    $Package_objects->{ "$self" } = 'Package';
    return $self;
};
my $override_dest = *Package::DESTROY{CODE};
*Package::DESTROY = sub {
    delete $Package_objects->{ "$_[0]" };
    $override_dest->(@_);
};

おそらくこれは最も野蛮な方法ですが、サードパーティのモジュールがなくても機能する必要があります;)

于 2012-11-04T08:21:22.427 に答える
2

表示されたオブジェクト ID のハッシュを保存して、各オブジェクトを 1 回だけカウントするようにします。Hash::Util::FieldHashまたはObject::IDを使用してそれを行うことができます。

idhash には、人為的にオブジェクトを存続させないという利点があります。各オブジェクトが破棄されると、そのエントリは idhash から削除されます。また、スレッド間で動作するという優れた利点もあります。

package Foo;

use strict;
use warnings;
use v5.10;

use Hash::Util::FieldHash qw(idhash register id);

idhash my %objects;

sub new {
    my $self = bless {}, shift;
    register $self, \%objects;
    $objects{$self} = 1;

    say "Creating ".id $self;

    my $num_objects = keys %objects;
    say "There are now $num_objects alive.";

    return $self;
}

sub DESTROY {
    my $self = shift;

    my $num_objects = keys(%objects) - 1;

    say "Destroying ".id $self;
    say "There are $num_objects left alive.";
}


{
    my $obj1 = Foo->new;            # 1 object
    my $obj2 = Foo->new;            # 2 objects
    {
        my $obj3 = Foo->new;        # 3 objects
    } # 2 objects
    my $obj4 = Foo->new;            # 3 objects
} # 0 objects
__END__
Creating 4303384168
There are now 1 alive.
Creating 4303542768
There are now 2 alive.
Creating 4303545192
There are now 3 alive.
Destroying 4303545192
There are 2 left alive.
Creating 4303638136
There are now 3 alive.
Destroying 4303542768
There are 2 left alive.
Destroying 4303384168
There are 1 left alive.
Destroying 4303638136
There are 0 left alive.

または、作成されたすべてのオブジェクトが破棄されるため、オブジェクトが破棄された場合のみカウントします。

于 2012-11-04T02:41:52.700 に答える
2

With regard to how to intercept bless (not Package::bless, bless is a builtin, not some kind of method), most builtins are overridable (see http://perldoc.perl.org/perlsub.html#Overriding-Built-in-Functions). The replacement bless function would perform your tracking (if blessing an object into your target class) and then call CORE::bless to actually perform the bless.

于 2012-11-04T07:29:49.157 に答える
1

で使用されているテクニックをご覧ください。

Devel-Leak-Object-1.01

さまざまな種類のオブジェクトの作成/破棄に関する統計を収集するための基礎として、ADAMK のコードを使用しました。

于 2012-11-04T15:37:41.767 に答える