2010-01-25 7 views
6

Un Perl linguaggio per la rimozione di valori duplicati di un array:L'utilizzo di undef come valori hash salva qualsiasi memoria in Perl?

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

È più conveniente per utilizzare questa versione:

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

ho provato con queste battute, e sembra che sia vero in alcune versioni di Perl:

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

Sei in esecuzione problemi di memoria o sei solo curioso? –

+0

Curioso. Come vedo, il cambiamento difficilmente può salvare una quantità notevole di ram. –

risposta

8

Beh, undef si suppone essere un valore peso mosca, il che significa che tutti i riferimenti ad esso puntano a t lui stesso dato. Non lo ottieni per altri letterali. Hai comunque bisogno del sovraccarico dello slot che lo fa riferimento però. Tuttavia, non lo vedo salvando alcun ricordo per me su Perl 5.10 o 5.11 su Mac OS X. Mentre perl potrebbe non utilizzare più memoria nel caso undef, scommetto che si prevede di utilizzare più memoria in modo che lo riprenda comunque. Tuttavia, non sono entusiasta di indagare sull'uso della memoria negli interni in questo momento.

Devel::Peek è piuttosto comodo per mostrare questo genere di cose:

#!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); 

L'output è un po 'paura all'inizio, ma si vede che i valori undef sono NULL(0x0) invece di valori stringa individuali (PV):

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 mi dà anche risultati identici. Forse perl ha iniziato a mettere in cache piccoli int, come python? :-) –

+0

L'ho provato con lo stesso valore e valori diversi per ogni chiave e ho ottenuto gli stessi risultati. Penso che Perl stia probabilmente afferrando un grosso pezzo di memoria in previsione di riempirlo di valori in seguito. –

+1

5.10 e versioni successive sono molto più efficienti nell'utilizzare la memoria minima per cose che sono solo int o solo riferimenti. Prima, uno sv aveva due parti, una che aveva refcnt, bandiere e un puntatore al resto; solo un undef finirebbe senza avere una seconda parte. Ora la struttura iniziale ha un campo aggiuntivo che prima era memorizzato nella seconda struttura (quale campo dipende dal tipo). – ysth