This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
faster constant hash key lookups ($hash{const})
authorDavid Mitchell <davem@iabyn.com>
Mon, 7 Jul 2014 22:17:13 +0000 (23:17 +0100)
committerDavid Mitchell <davem@iabyn.com>
Tue, 8 Jul 2014 14:36:41 +0000 (15:36 +0100)
commit34dadc62d399176c3286094e10619c6300ab9243
tree02cdeaf6cc51935e6afc42560ae87c25d36e13fb
parent86f641010e0569b8d5a3f09a3011af1522b6c14a
faster constant hash key lookups ($hash{const})

On something like $hash{constantstring}, at compile-time the
PVX string on the SV attached to the OP_CONST is converted into a
HEK (with an appropriate offset shift).

At run-time on hash keying, this HEK is used to speed up the bucket
search; however it turns out that this can be improved. Currently,
the main bucket loop does:

    for (; entry; entry = HeNEXT(entry)) {
if (HeHASH(entry) != hash)
    continue;
if (HeKLEN(entry) != (I32)klen)
    continue;
if (HeKEY(entry) != key && memNE(HeKEY(entry),key,klen))
    continue;
if ((HeKFLAGS(entry) ^ masked_flags) & HVhek_UTF8)
    continue;

The 'HeKEY(entry) != key' test is the bit that allows us to skip the
memNE() when 'key' is actually part of a HEK. However, this means that in
the const HEK scenario, for a match, we do pointless hash, klen and
HVhek_UTF8 tests, when HeKEY(entry) == key is sufficient for a
match. Conversely, in the non-const-HEK scenario, the 'HeKEY(entry) !=
key' will always fail, and so it's just dead weight in the loop.

To work around this, this commit splits the code into two separate bucket
search loops; one for const-HEKs that just compare HEK pointers, and a
general loop that now doesn't have do the 'HeKEY(entry) != key' test.

Analysing this code with cachegrind shows that with this commit, lookups
of constant keys that exist (e.g. the typical perl object scenario,
$self->{somefield}) takes 15% less instruction reads in hv_common(), 14%
less data reads and 27% less writes.

A lookup with a non-existing constant key ($hash{not_exist}) is about the
same as before (0.7% improvement).

Non-constant existing lookup ($hash{$existing_key}) is about 5% less
instructions, while $hash{$non_existing_key} is about 0.7%.
hv.c