I have an application that I believe is otherwise deterministic, but had
a heisenbug caused by an unintentional dependency on hash ordering.
Before managing to find the bug by other means, I tried unsuccessully
to create a reproducible testcase by experimentally setting PERL_HASH_SEED
to $h > 0, and PERL_PERTURB_KEYS to $k in (0, 1 (default), 2).
I found that with $k=1 the application failed randomly for each $h;
with $k=0 it consistently succeeded for each $h; and with $k=2 it
again failed randomly for each $h. That last ("DETERMINISTIC") feels
like a bug.
I tried unsuccessfully to reproduce the issue with a simple test:
$ENV{PERL_PERTURB_KEYS} = 2;
for my $h (1 .. 10) {
for (1 .. 3) {
local $ENV{PERL_HASH_SEED} = $h;
print "$h: ";
system(q{perl}, q{-e}, q{
%x = map +($_ => 1), ("a".."z");
print join("", keys %x), "\n";
})
}
}
.. but saw no non-deterministic behaviour there (and in fact $h does
not seem to cause any variation in results either).
Before I dig further to try and cut down the larger application to a
test case, does anyone have suggestions as to:
- what other (non-obvious) non-deterministic behaviour I might have?
- circumstances in which PERL_PERTURB_KEYS=2 might fail to give consistent
behaviour between runs of a program that is deterministic other than
for reliance on hash order?
- how to dump perl internals of a hash at runtime? Devel::Peek does not
appear to show the structure of buckets and chains explicitly, unless
I'm misreading it.
Thanks in advance for any clues,
Hugo
a heisenbug caused by an unintentional dependency on hash ordering.
Before managing to find the bug by other means, I tried unsuccessully
to create a reproducible testcase by experimentally setting PERL_HASH_SEED
to $h > 0, and PERL_PERTURB_KEYS to $k in (0, 1 (default), 2).
I found that with $k=1 the application failed randomly for each $h;
with $k=0 it consistently succeeded for each $h; and with $k=2 it
again failed randomly for each $h. That last ("DETERMINISTIC") feels
like a bug.
I tried unsuccessfully to reproduce the issue with a simple test:
$ENV{PERL_PERTURB_KEYS} = 2;
for my $h (1 .. 10) {
for (1 .. 3) {
local $ENV{PERL_HASH_SEED} = $h;
print "$h: ";
system(q{perl}, q{-e}, q{
%x = map +($_ => 1), ("a".."z");
print join("", keys %x), "\n";
})
}
}
.. but saw no non-deterministic behaviour there (and in fact $h does
not seem to cause any variation in results either).
Before I dig further to try and cut down the larger application to a
test case, does anyone have suggestions as to:
- what other (non-obvious) non-deterministic behaviour I might have?
- circumstances in which PERL_PERTURB_KEYS=2 might fail to give consistent
behaviour between runs of a program that is deterministic other than
for reliance on hash order?
- how to dump perl internals of a hash at runtime? Devel::Peek does not
appear to show the structure of buckets and chains explicitly, unless
I'm misreading it.
Thanks in advance for any clues,
Hugo