Benchmarks and verification
Seeded sampling verification and performance
The sampling API uses local ChaCha20 state and inverse CDFs. This benchmark times full PHP batches for normal, beta and Poisson at 1,000, 100,000 and one million draws. Every call reinitializes the explicit seed and allocates the complete numeric output. Raw results retain the seed, input hashes, numerical evidence, PHP version, binary hash, all timing samples, process elapsed time and peak RSS.
Independent verification first
Before any timing phase, Python independently computes the ChaCha blocks at 17 evenly spaced indices, with the pinned PCG seed expansion/Open01 mapping. Base-R quantiles transform those exact probabilities. PHP’s sampled points must match at 1e-15 + 1e-12*abs(reference); discrete values match the integer quantiles. The full output is consumed by mean/variance calculations and checked against theoretical moments within eight standard errors (using the distribution’s fourth central moment for variance). Fixed seeds make these checks deterministic.
This complements the ordinary 25-case independent stream/quantile fixture suite. It does not compare every element to R and does not claim that R’s own RNG shares the ChaCha sequence. Each timed result undergoes the same numerical checks again.
Recorded: 2026-10-12T15:50:48.801124+00:00; macOS-27.0.1-arm64-arm-64bit-Mach-O; PHP 8.5.10. All 9 sample-point/moment comparisons passed before timings. Seed 42, 5 repetitions.
| Family | Draws | Median full call (ms) | Peak whole-process RSS (MiB) |
|---|---|---|---|
| normal | 1,000 | 0.09167 | 27.5 |
| normal | 100,000 | 9.321 | 31.1 |
| normal | 1,000,000 | 92.52 | 65.4 |
| beta | 1,000 | 0.9933 | 27.6 |
| beta | 100,000 | 98.44 | 31.2 |
| beta | 1,000,000 | 963 | 65.5 |
| poisson | 1,000 | 0.1685 | 27.6 |
| poisson | 100,000 | 19.07 | 32.7 |
| poisson | 1,000,000 | 174.2 | 65.7 |
Timing interpretation
Five measurements follow one untimed warm-up. Timing includes ChaCha setup, quantile evaluation, PHP result allocation and ordinary reclamation of previous results. JSON I/O and numerical summaries are outside the timed call. Peak RSS covers the whole worker, including summaries and inputs; it is not isolated RNG state memory. These are API-level times on the recorded machine, not universal throughput guarantees or a comparison with optimized rejection samplers.
The normal/Poisson/beta cases show differing inverse-CDF costs. The method retains one numerical quantile path for every family. A future optimized sampler should be justified by measured demand and independent distribution/reproducibility tests.
Reproduction
Configure matching PHP/headers as in development. Python’s standard library and R/jsonlite are reference tools only.
cargo build -p phit --release --locked
PHP=/path/to/matching/php python3 tests/benchmarks/run-rng.py
python3 scripts/distribution-docs.pyThe independent ChaCha equations are shared with the fixture generator; they read no native uniforms or samples. The sampling API and these benchmarks add no R/Python runtime dependency or shared application RNG state.
From phpstats/phit@76b22f0.