2012-11-04 26 views
3

數我有在其操作期間使用一些許多對象(約3或4)班一個Perl庫。修補一類算創建的對象

在測試代碼,我想,以確保它是不是太多(我不是在談論內存泄漏,我知道如何檢查)。爲此,我想我可以統計每個使用的對象,並檢查測試數據上運行期間使用的最大值。然後,我會比較獲得的數字和一些關於庫應該使用多少對象的猜測。

不過,我已經得到了實現這個問題。我想到了兩種可能的方式:

  • 攔截Package::newPackage::DESTROY。然而,這有一點小問題,在該包中,new並不總是返回一個新對象。有時候,它會使用一個已存在的對象(對象被用作不可變對象,所以它不應該太重要)。所以我必須跟蹤每個單獨的對象以查看它是否存在。

  • 截距Package::blessPackage::DESTROY。這應該有效,但似乎有點不正統。

的問題是,它的那些方式是更容易成功(也許有什麼在類似情況下通常使用),其次,如何將我甚至實現第二個方法(我將不得不重寫Package::bless爲所有有問題的軟件包或只有基礎類等)。

+1

爲什麼你關心有多少物體在使用? – Schwern

+0

@Shwern:如問題中所述,估計庫的內存使用情況。更確切地說,我需要它來確保沒有錯誤導致例如。二次存儲器複雜度。 – jpalecek

回答

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->(@_); 
}; 

這大概是最野蠻的方法,但必須在沒有第三方模塊工作;)

2

商店看到的對象ID的哈希值,以確保你算每個對象只有一次。你可以使用Hash::Util::FieldHashObject::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. 

或者,由於創建的每個對象將被破壞,只有當一個對象被銷燬計數。

+0

計數被銷燬的對象不會是好事,因爲我想知道最大數量的對象*同時活着*。 – jpalecek

+0

在這種情況下,請使用idhash。當對象被銷燬時,他們會自動從哈希中刪除自己。我會用一個例子來更新。 – Schwern

2

關於如何攔截保佑(不是封裝::保佑,保佑是內建的,而不是某種方法),大多數內建的保險都是可覆蓋的(見http://perldoc.perl.org/perlsub.html#Overriding-Built-in-Functions)。替換祝福函數將執行你的跟蹤(如果祝福你的目標類中的對象),然後調用CORE :: bless來實際執行祝福。