合并2个或更多Perl哈希引用是否会消耗或多或少两倍的内存?

问题描述 投票:1回答:2

给定以下代码,$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
};

Update

哈希引用实际上指向使用tieDB_File创建的大哈希。

我想知道是否有可能只使用一个哈希值,这样我就不需要将所有内容都转储到内存中了。此外,我可能会同时使用其中两个以上。

perl
2个回答
3
投票

捆绑的哈希根本不是哈希。它们是子程序的接口。因为它们是代码而不是数据,所以谈论关联哈希的内存和性能通常是没有意义的。

我们先谈谈普通的哈希。

$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
投票

简单的答案是肯定的。

如果你想要两个散列引用的所有键而不创建一个新的hashref,并假设你没有重复的键,你可以做类似的事情。

use List::Util qw( uniq );

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

然后从任一数组中获取值

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

那么你为什么要使用哈希引用而不是哈希,为什么内存需要考虑这个问题呢?

© www.soinside.com 2019 - 2024. All rights reserved.