2010-01-25 7 views
6

A Perl deyim:Undef değerini hash değerleri olarak kullanmak Perl'de herhangi bir belleği kaydeder mi? Diziden yinelenen değerleri kaldırmak için

@uniq = keys %{{map{$_=>1}@list}} 

daha ucuz bu sürümü kullanmaya mı:

@uniq = keys %{{map{$_=>undef}@list}} 

Bunları tek gömlekleri ile test ettik ve bu doğrudur gibi görünüyor Perl bazı sürümlerinde:

perl -e 'my %x; $x{$_} = 1 for 0..1000_000; system "ps -ovsz $$"' 
perl -e 'my %x; $x{$_} = undef for 0..1000_000; system "ps -ovsz $$"' 
+0

Bellek sorunlarıyla mı çalışıyorsunuz yoksa merak ediyor musunuz? –

+0

Meraklı. Gördüğüm gibi, değişim fark edilir miktarda ramdan çok az tasarruf edebilir. –

cevap

8

Eh, undef kendisine yapılan tüm başvurular t işaret, yani bir denge ağırlıklı değerini olması gerekiyordu Aynı veri. Bunu diğer hazırlıklar için anlamıyorsun. Yine de buna referans veren yuvanın tavanına ihtiyacınız var. Ancak, Mac OS X üzerinde Perl 5.10 veya 5.11 üzerinde benim için herhangi bir bellek kaydetme görmüyorum. perlundef durumunda daha fazla bellek kullanmıyor olabilir, daha fazla bellek kullanarak tahmin ediyor, bu yüzden onu zaten kapmak böylece. Bununla birlikte, şu anda içsellerde bellek kullanımını araştırmak istemiyorum.

Devel::Peek bu şeylerin türlü göstermek için oldukça kullanışlıdır: çıktı ilk başta biraz korkutucu görünüyor

#!perl 

use Devel::Peek; 

my $a = undef; 
my $b = undef; 

Dump($a); 
Dump($b); 


my %hash = map { $_, undef } 1 .. 3; 
$hash{4} = 'Hello'; 
Dump(\%hash); 

ancak undef değerleri NULL(0x0) yerine tek tek dize değerleri (PV) ait olduğunu görüyoruz:

SV = NULL(0x0) at 0x100208708 
    REFCNT = 1 
    FLAGS = (PADMY) 
SV = NULL(0x0) at 0x100208738 
    REFCNT = 1 
    FLAGS = (PADMY) 
SV = RV(0x100805018) at 0x100805008 
    REFCNT = 1 
    FLAGS = (TEMP,ROK) 
    RV = 0x100208780 
    SV = PVHV(0x100809ed8) at 0x100208780 
    REFCNT = 2 
    FLAGS = (PADMY,SHAREKEYS) 
    ARRAY = 0x100202200 (0:5, 1:2, 2:1) 
    hash quality = 91.7% 
    KEYS = 4 
    FILL = 3 
    MAX = 7 
    RITER = -1 
    EITER = 0x0 
    Elt "4" HASH = 0xb803eff9 
    SV = PV(0x100801c78) at 0x100804ed0 
     REFCNT = 1 
     FLAGS = (POK,pPOK) 
     PV = 0x100202a30 "Hello"\0 
     CUR = 5 
     LEN = 8 
    Elt "1" HASH = 0x806b80c9 
    SV = NULL(0x0) at 0x100820db0 
     REFCNT = 1 
     FLAGS =() 
    Elt "3" HASH = 0xa400c7f3 
    SV = NULL(0x0) at 0x100820df8 
     REFCNT = 1 
     FLAGS =() 
+0

5.10 bana da aynı sonuçları veriyor. Belki perl python gibi küçük harfleri önlemeye başladı? :-) –

+0

Her bir anahtar için aynı değer ve farklı değerler ile denedim ve aynı sonuçları aldım. Bence Perl, daha sonra değerlerle dolduracağı beklentisiyle büyük bir bellek parçasını ele geçiriyordur. –

+1

5.10 ve üstü, sadece bir int ya da sadece referans olan şeyler için minimum bellek kullanmanın çok daha iyi. Daha önce, bir sv iki bölümden oluşuyordu, bir tanesi geri çekildi, bayraklar ve geri kalanı için bir işaretçi vardı; sadece bir undef ikinci bir kısma sahip olmayacaktı. Şimdi ilk yapının, ikinci yapıda (tipine bağlı olan alan) depolanmak için kullanılan fazladan bir alanı vardır. – ysth

İlgili konular