Сохраняет ли использование undef в качестве хеш-значений память в Perl? - PullRequest
6 голосов
/ 25 января 2010

Идиома 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 $$"'

1 Ответ

8 голосов
/ 25 января 2010

Ну, undef предполагается, что значение мухи означает, что все ссылки на него указывают на один и тот же элемент данных. Вы не получите это для других литералов. Вам все еще нужны накладные расходы слота, который ссылается на него, хотя. Тем не менее, я не вижу, чтобы это сэкономило мне память на Perl 5.10 или 5.11 на Mac OS X. Хотя perl может не использовать больше памяти в случае undef, я держу пари, что он ожидает использовать больше памяти, чтобы захватить это все равно. Однако сейчас я не заинтересован в изучении использования памяти во внутренних органах.

Devel :: Peek очень удобно для показа таких вещей:

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

Вначале вывод выглядит немного страшно, но вы видите, что значения undef равны NULL(0x0) вместо отдельных строковых значений (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 = ()
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...