chore(metrics): replace vendored JSF PRNG with inline SplitMix64 (#700)#786
Conversation
LCOV of commit
|
|
@codex review |
…700) Removes the vendored 3rd/rng/jsf.h (178 lines, Bob Jenkins Small Fast) in favor of a ~6-line inline SplitMix64 in AbstractMetricsManager.h. This is the deep- sampling gate's PRNG (roll 0-99, deep-sample when the roll is under deep_sample_rate), used in exactly one place; sampling RATE is unchanged (only which events get deep-sampled differs, and nothing depends on the specific set). Why SplitMix64 over the issue's suggested pcg-cpp conan package: it removes the maintained code (the whole 3rd/rng dir) without ADDING a third-party dependency, keeps an 8-byte state (vs jsf's 16, vs std::mt19937's ~2.5KB), and has BigCrush-grade quality. CRITICAL invariant preserved (issue #109 "RDRAND failure on Arista switch"): the generator is seeded from a fixed constant and never from std::random_device / hardware entropy. The pre-JSF randutils-based RNG auto-seeded via random_device -> RDRAND, which faulted and threw on startup on some hardware; PR #110 fixed that by switching to a fixed-seeded PRNG. A prominent comment documents this so nobody "improves" it into entropy seeding (a particular footgun with pcg-cpp's idiomatic seed_seq_from<random_device>). Build wiring: - Delete 3rd/rng/ and its add_subdirectory + the `rng` link in visor-core. - Fix a latent copy-paste bug in 3rd/timer/CMakeLists.txt: it called target_include_directories(rng ...) instead of (timer ...), so timer.hpp's include dir was being attached to the rng target and only reached visor-core transitively through it. Removing rng would have broken <timer.hpp>; pointing it at timer makes the timer target self-contained. - Update the NOMINMAX comment in CMakeLists.txt (it cited jsf.h's static min()/max()); keep the define for general Windows hygiene. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
0a3c868 to
6531af3
Compare
There was a problem hiding this comment.
Pull request overview
This PR removes the vendored JSF PRNG implementation and replaces its sole usage (deep-sampling gate in metrics) with a small inline SplitMix64 PRNG seeded from a fixed constant, while also cleaning up the CMake wiring to drop the removed rng interface target and ensure the timer interface target is self-contained.
Changes:
- Replace
#include <jsf.h>+jsf32usage with an inline fixed-seed SplitMix64 generator for deep-sampling decisions. - Remove the
3rd/rng/directory and unlink/unsubdir it from the build. - Fix
3rd/timerCMake to attach include dirs to thetimertarget (not the deletedrngtarget) and update WIN32NOMINMAXcomment to be general-purpose.
Reviewed changes
Copilot reviewed 7 out of 7 changed files in this pull request and generated no comments.
Show a summary per file
| File | Description |
|---|---|
| src/CMakeLists.txt | Stops linking visor-core against the removed rng interface target. |
| src/AbstractMetricsManager.h | Introduces inline fixed-seed SplitMix64 PRNG and removes dependency on jsf.h. |
| CMakeLists.txt | Updates WIN32 NOMINMAX comment to reflect broader rationale (not JSF-specific). |
| 3rd/timer/CMakeLists.txt | Fixes include-directory attachment to the correct timer target (prevents breakage after rng removal). |
| 3rd/rng/jsf.h | Deletes vendored JSF PRNG header. |
| 3rd/rng/CMakeLists.txt | Deletes the rng interface target definition. |
| 3rd/CMakeLists.txt | Removes add_subdirectory(rng) from third-party build wiring. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
|
Codex Review: Didn't find any major issues. Hooray! Reviewed commit: ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍. Codex can also answer questions or update the PR. Try commenting "@codex address that feedback". |
Closes #700.
What
Replaces the vendored
3rd/rng/jsf.h(178-line Bob Jenkins "Small Fast" PRNG) with a ~6-line inline SplitMix64 inAbstractMetricsManager.h, and deletes the3rd/rng/directory.JSF was used in exactly one spot — the deep-sampling gate:
_deep_sampling_now.store((_rng() % 100U < _deep_sample_rate), ...);i.e. "roll 0–99, deep-sample this event if the roll is under
deep_sample_rate." The sampling rate is unchanged; only which events get deep-sampled differs, and nothing depends on the specific set (defaultdeep_sample_rate=100means the RNG is never even called).Why SplitMix64 instead of the proposed pcg-cpp
The issue suggested the
pcg-cppconan package. I went a different way after weighing the options:seed_seq_from<std::random_device>is exactly the footgun that caused RDRAND failure on Arista switch #109 (below).std::mt19937works but carries ~2.5 KB of state per handler instance for a 1-in-100 coin flip.3rd/rng/dir with no new dependency, 8-byte state, and BigCrush-grade quality. We "own" ~6 auditable lines instead of 178.Invariant preserved (#109)
#109 ("RDRAND failure on Arista switch") was a startup crash: the pre-JSF
randutilsRNG auto-seeded fromstd::random_device→RDRAND, which faults and throws on some hardware. PR #110 fixed it by switching to a fixed-seeded PRNG. SplitMix64 here is seeded from a fixed constant and never from hardware entropy, preserving that fix. A prominent comment documents the constraint so it isn't "improved" into entropy seeding later.Build wiring
3rd/rng/+ itsadd_subdirectory+ thernglink invisor-core.3rd/timer/CMakeLists.txt: it calledtarget_include_directories(rng ...)instead of(timer ...), sotimer.hpp's include dir was being attached to therngtarget and only reachedvisor-coretransitively through it. Removingrngwould have broken<timer.hpp>; pointing it attimermakes the timer target self-contained.NOMINMAXcomment (it cited jsf.h'sstatic min()/max()); the define stays for general Windows hygiene.Testing
unit-tests-visor-core(which includes the sampling/metrics tests) passes — 1153 assertions, 21 test cases.🤖 Generated with Claude Code