2010-09-27 16 views
20

Perl'deki bir paketi nasıl tamamen sildiniz? Bu sadece paket değişkenleri değil, aynı zamanda Perl'in miras değişiklikleri ve diğer şeyleri ele almak için güncellediği herhangi bir sihirli tablo anlamına gelir.Perl'deki bir paketi nasıl tamamen silebilirim?

Bu basit testi: Aşağıdaki çıktıda

use warnings; use strict; 
use Test::LeakTrace; 
use Symbol 'delete_package'; 

leaktrace { 
    package test; 
    our $x = 1; 

    package main; 
    delete_package 'test'; 
}; 

sonuçları:

leaked ARRAY(0x81c930) from /lib/perl5/5.10.1/Symbol.pm line 166. 
leaked HASH(0x827760) from /lib/perl5/5.10.1/Symbol.pm line 166. 
leaked SCALAR(0x821920) from /lib/perl5/5.10.1/Symbol.pm line 166. 

Ben istek üzerine gönderebilir veri screenfuls içinde leaktrace sonuçlar için -verbose bayrağını kullanma. our @ISA olduğu

leaked ARRAY(0x81cd10) from so.pl line 32. 
leaked SCALAR(0x81c930) from so.pl line 32. 
leaked ARRAY(0x8219d0) from so.pl line 32. 
leaked HASH(0x8219c0) from so.pl line 32. 
leaked SCALAR(0x8219b0) from so.pl line 32. 
leaked HASH(0x8219a0) from so.pl line 32. 
leaked SCALAR(0x821970) from /lib/perl5/5.10.1/Symbol.pm line 161. 
leaked HASH(0x821950) from so.pl line 32. 
leaked SCALAR(0x821940) from so.pl line 32. 

Hat 32'dir: çizgi our @ISA = 'main';test paketine eklenirse

şeyler kötüleşir.

bunlar gerçekten sızıntı ve tercüman değil sadece gürültü olduğunu göstermek için:

my $num = 0; 
while (1) { 
    no strict 'refs'; 
    @{$num.'::ISA'} = 'main'; 
    delete_package $num++; 
} 

Yani sabit bir hızda bellek yiyeceğim, bir paketin kurtulmak için daha iyi bir yol yoktur Symbol'un delete_package'dan mı? Yardım etmek için yapmam gereken başka bir şey var mı?

ben 5.8.8, 5.10.1 de aynı davranışı gördük ve 5.12

+0

Harika bir soru, merakım sivridir, ama sormam gerek: Neden? –

+5

CPAN'daki "List :: Gen" modülümde, (http://search.cpan.org/perldoc?List::Gen), geçici bir pakete kapatma temelli bir nesne yükleyen bir "lanet işlevi" işlevine sahibim (standart yöntem çağrılarını kolaylaştırmak için) (yüksek hızda). 'delete_package' her şeyi temizler, ancak yukarıdaki '' curse '' yukarıdaki sorunlardan dolayı hala bellek sızdırıyor. Sızıntı çok büyük değil, ama orada ve mümkünse takmak istiyorum. –

+3

Henüz yapmadıysanız, bunu bir perl hatası olarak kaydedin. – ysth

cevap

4

Yani bu, sen keşfetti bile bir rapor tek perl'de bir hata değildir. Sabitlemenin kısa bir kısmı, bu sızıntıları önlemenin tek yolunun, probleminizi çözmek için başka bir yaklaşım seçmesidir.

Nasıl oluyor da, örneğin bir kapanış yerine yarı anonim bir pakete ihtiyacınız var? Bunlar, sızıntı yapmamak için yeterince kolaydır ve bazı yaratıcılık ile, hemen hemen her dış arabirimi üst üste uygulayabilirsiniz, örneğin, kapama coderefs'inizi kutsayarak ve onlar için yöntemler sağlayarak, bunlara aşırı yüklenme sağlayarak, vs.

+0

Bu nesnelerin kullanım şekli nedeniyle (sıkı iç döngü hesaplamaları), birden çok yönlendirme düzeyinden kaçınmaya çalışıyorum. Yani 'lanet', nesnelerini bir pakete yükler, böylece uygulamayı açığa çıkarmak yerine, '$ obj-> yöntemini (ve kalıtımın bazı yanlarını) saklayabilirsiniz.' $$ obj {method}() '. 'AUTOLOAD' veya bir ana sınıfta stub yöntemlerinin yüklenmesini kullanabilirdim, ancak her durumda en az 1 ek alt yordam çağrısı ve her aramada en az bir karma arama yaptı. –

+0

Yarı anonim paketlerin bu tür bir şeyi optimize etmenin iyi bir yolu olduğunu sanmıyorum. Birincisi, metod çağrıları, perl'in ilk çağrıdan sonra yöntem çözünürlüğünü önbelleğe almasına rağmen, bir coderef'e yapılan düz çağrılardan biraz daha yavaştır.Ek olarak, argümanların bir işleve aktarılması, ihtiyaç duyduğu argümanları kapatan bir coderef oluşturulmasından ölçülebilir derecede daha yavaştır. Ve "object" dediğimde, aynı zamanda '$$ obj {method}()' kullanarak değil, coderef'in kendisini kutsadığınızı da söylemedim. Ayrıca, 'AUTOLOAD' kullanmak da sıkı iç döngüleri optimize etmenin kötü bir yolu gibi görünüyor - bu ** yavaş **. İlk yorumumda belirtilen nedenlerden dolayı – rafl

+0

'AUTOLOAD' ve stub yöntemleri zaten devre dışıdır. Bununla birlikte, bir nesnede çağrılabilecek birçok yöntem olduğu için son kullanıcıya bir çeşit arabirim sağlamaya ihtiyacım var. Bulduğum en hızlı (çalışma zamanı değil, yaratma süresi) yöntemi, kapatma yöntemlerini anon paketlerine kurmak ve daha sonra bu pakete kutsanmış bir başvuru sağlamaktır. Bir liste için 'List :: Gen :: curse' ve onun jeneratörlerinin uygulanmasına bakınız. Optimize etmenin daha iyi bir yolu varsa, –

İlgili konular