2010-01-25 17 views
6

A Perl lenguaje para eliminar valores duplicados de una matriz:¿El uso de undef como valores hash guarda cualquier memoria en Perl?

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

¿Es más barato de usar esta versión:

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

I probado con estos de una sola línea, y parece que es cierto en algunas versiones de 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

¿Tiene problemas de memoria o solo tiene curiosidad? –

+0

Curioso. Como veo, el cambio difícilmente puede ahorrar una notable cantidad de ram. –

Respuesta

8

Bueno, undef se supone que es un valor de peso mosca, lo que significa que todas las referencias a él apuntan a t el mismo dato No lo entiendes por otros literales. Aún necesita la sobrecarga de la ranura que lo hace referencia. Sin embargo, no veo que guarde ningún recuerdo para mí en Perl 5.10 o 5.11 en Mac OS X. Si bien perl puede no estar usando más memoria en el caso undef, apuesto a que está anticipando el uso de más memoria para que lo agarre de todos modos. Sin embargo, no estoy interesado en investigar el uso de la memoria en el interior ahora mismo.

Devel::Peek es bastante práctico para mostrar este tipo de cosas:

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

La salida se ve un poco de miedo al principio, pero se ve que el undef valores son NULL(0x0) en lugar de los valores de cadena individuales (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 me da resultados idénticos también. ¿Quizás Perl comenzó a almacenar en memoria caché pequeños enteros, como Python? :-) –

+0

Lo probé con el mismo valor y diferentes valores para cada tecla y obtuve los mismos resultados. Creo que Perl probablemente está agarrando una gran parte de la memoria a la espera de llenarla de valores más tarde. –

+1

5.10 y superior son mucho mejores al usar memoria mínima para cosas que son solo una referencia o solo una referencia. Antes, un sv tenía dos partes, una que tenía refcnt, banderas y un puntero al resto; solo un undef terminaría sin segunda parte. Ahora la estructura inicial tiene un campo adicional que solía almacenarse en la segunda estructura (de qué campo depende el tipo). – ysth

Cuestiones relacionadas