A test expression like
map { exists $HASH{$_} } @rand
seems to include a lot of superfluous temporary list construction and destruction redundant overhead extraneous activity.
My approach would be simpler (please forgive a bit of slapdashery):
>perl -wMstrict -le
"use Benchmark qw(cmpthese);
my %HASH;
my $not_key = 'not_key';
$HASH{ rand() } = 1;
compare();
$HASH{ rand() } = 1 for 0 .. 30_000;
compare();
sub compare {
print '------------------';
print 'hash keys/buckets: ' . %HASH;
my ($is_key) = each %HASH;
! exists $HASH{$not_key} or die qq{$not_key should not exist};
exists $HASH{$is_key} or die qq{$is_key should exist};
print qq{test keys '$is_key' and '$not_key' seem ok};
my $HR = \%HASH;
cmpthese(-2, {
hash_hit => sub { exists $HASH{$is_key} },
hash_miss => sub { exists $HASH{$not_key} },
href_hit => sub { exists $HR->{$is_key} },
href_miss => sub { exists $HR->{$not_key} },
});
}
"
------------------
hash keys/buckets: 1/8
test keys '0.408477783203125' and 'not_key' seem ok
Rate hash_miss href_miss href_hit hash_hit
hash_miss 3305141/s -- -6% -22% -42%
href_miss 3520236/s 7% -- -16% -39%
href_hit 4215045/s 28% 20% -- -27%
hash_hit 5746274/s 74% 63% 36% --
------------------
hash keys/buckets: 14778/32768
test keys '0.091217041015625' and 'not_key' seem ok
Rate href_miss href_hit hash_miss hash_hit
href_miss 3392515/s -- -18% -21% -36%
href_hit 4126900/s 22% -- -3% -23%
hash_miss 4272362/s 26% 4% -- -20%
hash_hit 5329295/s 57% 29% 25% --
Hashes still seem faster than references, but hits seem faster than misses. Overall differences are still not compelling.
Update: The results above support the notion that hash key lookup (e.g., with exists) is O(1), so the idea of direct or indirect hash lookup being 'faster' might not have much meaning even if the timing differences were more significant.