Объединяет ли 2 или более хеш-ссылок Perl более или менее в два раза больше памяти? - PullRequest
0 голосов
/ 03 сентября 2018

Учитывая следующий код, использует ли хеш, на который ссылается $z, ту же память, что и ( %$x, %$y), более или менее?

Если это так, есть ли способ использовать одну ссылку для вызова данных из хэшей, на которые ссылаются либо $x, либо $y, например $z->{$somekeytoXorY}, без ущерба для производительности и памяти?

use strict;
use warnings;

my $x = {
    1 => 'a',
    2 => 'b',
};

my $y = {
    3 => 'c',
    4 => 'd',
};

my $z = {
    %$x, %$y
};

Обновление

Ссылки хеша фактически указывают на большие хеши, созданные с использованием tie и DB_File.

Мне было интересно, есть ли шанс, что я смогу использовать для них всего один хеш, чтобы мне не нужно было выгружать все в память. Также я могу использовать более двух из них одновременно.

Ответы [ 2 ]

0 голосов
/ 04 сентября 2018

Связанные хеши вовсе не являются хешами. Это интерфейсы для подпрограмм. Поскольку они представляют собой код, а не данные, говорить о памяти и производительности связанных хешей вообще не имеет смысла.

Давайте сначала поговорим об обычных хешах.

$z = { %$x, %$y }; скопирует скаляры %$x и %$y в %$z, поэтому да, это займет вдвое больше памяти (при условии, что дублирующихся ключей нет).

Вы можете поделиться скалярами:

use Data::Alias qw( alias );
my $z = {};
alias $z->{$_} = $x->{$_} for keys(%$x);
alias $z->{$_} = $y->{$_} for keys(%$y);

Вы бы все равно использовали память, пропорциональную количеству элементов в обоих хешах, но это было бы намного меньше, чем раньше, если бы %$x и %$y действительно были хешами. Это может не сэкономить память для связанных хэшей.

Альтернатива - вообще не объединять данные. Вы можете использовать связанный хеш самостоятельно ...

package Tie::MergedHashes;
use Carp qw( croak );
sub new     { my $pkg = shift; $pkg->TIEHASH(@_); }
sub TIEHASH { bless [ @_ ], $_[0] }
sub STORE   { croak("Not allowed"); }
sub FETCH   { for (@{$_[0]}) { return $_->{$_[1]} if exists($_->{$_[1]}); } return undef; }
...

my $z = {};
tie %$z, MergedHashes => ($y, $x);
$z->{$key}

... но нет причин делать код похожим на хеш. Вы можете просто использовать объект.

package MergedHashes;
use Carp qw( croak );
sub new   { bless [ @_ ], $_[0] }
sub fetch { for (@{$_[0]}) { return $_->{$_[1]} if exists($_->{$_[1]}); } return undef; }
...

my $z = MergedHashes->new($y, $x);
$z->fetch($key)
0 голосов
/ 03 сентября 2018

Простой ответ - да.

Если вы хотите получить все ключи из обеих ссылок, не создавая новый, и предполагая, что у вас нет дублированных ключей, вы могли бы сделать что-то вроде.

use List::Util qw( uniq );

my @keys = uniq( keys( %$x ), keys( %$y ) );

Затем, чтобы получить значения из любого массива, например,

my $value = exists $y->{$key} ? $y->{$key} : $x->{$key};

Кстати, почему вы используете хэш-ссылки, а не хэши, и почему память так важна, что вам нужно было задать этот вопрос?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...