在Perl中使用undef作为散列值会节省内存吗?

在Perl中使用undef作为散列值会节省内存吗?,perl,Perl,用于从数组中删除重复值的Perl习惯用法: @uniq = keys %{{map{$_=>1}@list}} 使用此版本是否更便宜: @uniq = keys %{{map{$_=>undef}@list}} 我用这些一行程序对它进行了测试,在一些Perl版本上似乎是这样的: perl -e 'my %x; $x{$_} = 1 for 0..1000_000; system "ps -ovsz $$"' perl -e 'my %x; $x{$_} = undef for

用于从数组中删除重复值的Perl习惯用法:

@uniq = keys %{{map{$_=>1}@list}} 
使用此版本是否更便宜:

@uniq = keys %{{map{$_=>undef}@list}}
我用这些一行程序对它进行了测试,在一些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 $$"'

嗯,
undef
应该是一个flyweight值,这意味着对它的所有引用都指向同一个基准。对于其他文字,您无法获得该值。不过,您仍然需要引用它的插槽的开销。但是,我没有看到它在Mac OS X上的Perl 5.10或5.11上为我节省任何内存。虽然
Perl
undef
情况下可能不会使用更多内存,但我打赌它预计会使用更多内存,所以它无论如何都会抓住它。然而,我现在并不热衷于研究内部的内存使用

非常方便地展示这类东西:

#!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 );
起初,输出看起来有点吓人,但您可以看到
unde
值是
NULL(0x0)
而不是单个字符串值(
PV
):


你是遇到了内存问题还是只是好奇?好奇。正如我所看到的,这种改变很难节省大量的ram。5.10也给了我同样的结果。也许perl开始缓存小整数,比如python?:-)我用相同的值和每个键的不同值进行了尝试,得到了相同的结果。我认为Perl可能正在获取一大块内存,以便在以后用值填充它。5.10及以上版本更擅长将最小内存用于仅为int或仅为引用的内容。以前,sv有两个部分,一个有refcnt、flags和指向其余部分的指针;只有undef最终没有第二部分。现在,初始结构有一个额外的字段,该字段以前存储在第二个结构中(它是什么字段取决于类型)。
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 = ()