UserCache vs FrankenPHP zval.h Reference

Compares UserCache\Cache with a benchmark reference cache built on the official FrankenPHP zval.h helpers, both running in the same persistent FrankenPHP worker threads. The reference is not a public native FrankenPHP cache API. Measured at 2026-09-30T07:54:36.579770+00:00.

How to read this report

Measured run — all selected samples validated · mode worker · micro 15 pairs × 2 sessions · A/A 15 pairs · HTTP 5 rounds × 5 s · CPUs 0-3 · FrankenPHP 51e6246e71f3

Related report: UserCache\Cache performance report (APCu and Yac)

PHP fetch batchesUserCache faster in 30/33Counts use paired 95% intervals
Geomean
1.18x faster
Reference faster
0
Within interval
3
Read fetchesUserCache faster in 20/21Counts use paired 95% intervals
Geomean
1.21x faster
Reference faster
0
Within interval
1
Fetch and mutateUserCache faster in 10/12Counts use paired 95% intervals
Geomean
1.13x faster
Reference faster
0
Within interval
2
HTTP, 100 ops/requestUserCache faster in 7/12Counts use paired 95% intervals
Geomean throughput
1.03x higher
Reference faster
1
Within interval
4
PHP batch time, median
1.21x faster
HTTP, 1 op/requestUserCache faster in 1/12Counts use paired 95% intervals
Geomean throughput
1.01x lower
Reference faster
3
Within interval
8
PHP batch time, median
1.16x slower
Cached data sizeUserCache smaller in 15/16Shared memory vs reference persistent bytes
Median
2.09x smaller
UserCache empty segment
3.73 MiB
Extra PHP heap in UserCache
456 B to 2.25 MiB

Summary

PHP fetch batch rows compare time inside one PHP execution as a speedup; HTTP rows compare end-to-end throughput. Above 1.00x UserCache is faster in both. Counts use the paired bootstrap 95% interval of each case; the geometric mean weighs every case equally.pairing and statistics note

CasesCountUserCache fasterWithin intervalReference fasterGeomean speedup
PHP fetch batches3330301.177x
Read fetches2120101.206x
Fetch and mutate1210201.128x
HTTP, 100 ops/request (throughput)127411.029x
HTTP, 1 op/request (throughput)121830.986x

A/A runs (the reference measured against itself) show the noise floor: their medians range from 0.943x to 1.132x. Cases marked † have A/A noise above ±2%, so differences of that size are not meaningful there.

PHP fetch batches, speedup (reference time ÷ UserCache time)

Payload1 key, warm, read1 key, warm, read, TTL 36001 key, warm, mutate32,768 keys, warm, read32,768 keys, warm, mutate32,768 keys, cold, read
null1.155x1.124–1.180-----
bool1.176x1.164–1.195-----
int1.163x1.145–1.178--1.198x1.189–1.2011.192x1.185–1.1971.420x †1.410–1.446
double1.157x1.141–1.170-----
string321.221x †1.198–1.240-1.165x1.142–1.190---
string3001.208x1.187–1.224-1.192x †1.172–1.1961.296x1.274–1.3101.256x1.234–1.2691.024x1.000–1.057
string4k1.229x †1.213–1.238-1.078x1.071–1.098---
string64k1.218x †1.200–1.225-1.023x0.998–1.045---
packed81.271x1.259–1.2771.201x1.191–1.2211.162x1.157–1.1721.305x1.288–1.3351.208x1.194–1.2171.126x1.114–1.150
packed5121.270x †1.263–1.286-1.052x1.049–1.062---
hash321.224x1.208–1.234-1.083x1.069–1.0931.301x †1.225–1.3511.087x †0.991–1.4011.082x †1.047–1.108
nested1.139x1.122–1.147-1.069x1.051–1.081---

HTTP worker scaling, throughput ratio (UserCache ÷ reference)

Fixture / mix1 worker, 100 ops/request2 workers, 100 ops/request4 workers, 100 ops/request1 worker, 1 op/request2 workers, 1 op/request4 workers, 1 op/request
array / read0.998x0.976–1.0220.970x0.870–1.2291.028x1.009–1.0360.976x0.942–0.9901.077x1.032–2.0410.987x0.979–1.014
array / 99% read + 1% store0.907x0.767–0.9851.033x0.733–1.2611.141x1.139–1.1530.989x0.932–1.0140.874x0.811–1.2670.993x0.976–1.092
scalar / read1.037x1.025–1.0891.025x1.001–1.0961.052x1.041–1.0630.986x0.955–1.0150.996x0.990–0.9970.998x0.985–1.044
scalar / 99% read + 1% store1.031x1.021–1.0511.048x0.995–1.1731.100x1.093–1.1090.981x0.946–0.9950.993x0.992–1.0090.998x0.984–1.009

PHP fetch batches — worker mode

Median time per fetch in a timed batch, including the common PHP fetch loop and observation or mutation. Seed, setup and warmup stay outside the batch. The speedup cell shows its 95% interval and the speedup of each session; A/A noise is how far the same case measured reference against reference moved from 1.00x.workload note

CaseUserCachezval.h referenceSpeedupFasterA/A noisePairs
null1 key · warm · read62.3 nsCPU 62.3 ns72.7 nsCPU 72.7 ns1.155x1.124–1.180s1 1.109x · s2 1.170xUserCache 1.00xzval.h reference 1.16x±1.2%30
bool1 key · warm · read58.6 nsCPU 58.4 ns68.3 nsCPU 68.3 ns1.176x1.164–1.195s1 1.195x · s2 1.173xUserCache 1.00xzval.h reference 1.18x±1.0%30
int1 key · warm · read59.3 nsCPU 59.2 ns69.0 nsCPU 69.0 ns1.163x1.145–1.178s1 1.160x · s2 1.172xUserCache 1.00xzval.h reference 1.16x±0.1%30
int32,768 keys · warm · read61.4 nsCPU 61.4 ns73.8 nsCPU 73.7 ns1.198x1.189–1.201s1 1.198x · s2 1.199xUserCache 1.00xzval.h reference 1.20x±1.3%30
int32,768 keys · warm · mutate flag (scalar no-op)61.5 nsCPU 61.5 ns73.6 nsCPU 73.6 ns1.192x1.185–1.197s1 1.195x · s2 1.190xUserCache 1.00xzval.h reference 1.19x±1.5%30
int32,768 keys · cold · read69.4 nsCPU 69.4 ns98.6 nsCPU 98.6 ns1.420x †1.410–1.446s1 1.410x · s2 1.444xUserCache 1.00xzval.h reference 1.42x±2.3%30
double1 key · warm · read65.7 nsCPU 65.7 ns76.5 nsCPU 76.1 ns1.157x1.141–1.170s1 1.155x · s2 1.159xUserCache 1.00xzval.h reference 1.16x±1.7%30
string321 key · warm · read72.9 nsCPU 72.9 ns88.1 nsCPU 88.1 ns1.221x †1.198–1.240s1 1.230x · s2 1.213xUserCache 1.00xzval.h reference 1.22x±2.9%30
string321 key · warm · mutate83.7 nsCPU 83.6 ns97.0 nsCPU 97.0 ns1.165x1.142–1.190s1 1.154x · s2 1.191xUserCache 1.00xzval.h reference 1.16x±1.0%30
string3001 key · warm · read68.0 nsCPU 68.0 ns81.8 nsCPU 81.8 ns1.208x1.187–1.224s1 1.208x · s2 1.202xUserCache 1.00xzval.h reference 1.21x±0.0%30
string3001 key · warm · mutate79.4 nsCPU 79.4 ns93.9 nsCPU 93.9 ns1.192x †1.172–1.196s1 1.189x · s2 1.193xUserCache 1.00xzval.h reference 1.19x±5.7%30
string30032,768 keys · warm · read69.3 nsCPU 69.2 ns89.5 nsCPU 89.4 ns1.296x1.274–1.310s1 1.296x · s2 1.301xUserCache 1.00xzval.h reference 1.30x±0.9%30
string30032,768 keys · warm · mutate81.7 nsCPU 81.7 ns101.4 nsCPU 101.4 ns1.256x1.234–1.269s1 1.245x · s2 1.259xUserCache 1.00xzval.h reference 1.26x±0.7%30
string30032,768 keys · cold · read93.9 nsCPU 93.9 ns95.7 nsCPU 95.5 ns1.024x1.000–1.057s1 1.061x · s2 1.002xUserCache 1.00xzval.h reference 1.02xinterval includes 1.00x±1.9%30
string4k1 key · warm · read65.6 nsCPU 65.6 ns80.6 nsCPU 80.6 ns1.229x †1.213–1.238s1 1.227x · s2 1.230xUserCache 1.00xzval.h reference 1.23x±2.5%30
string4k1 key · warm · mutate132.3 nsCPU 132.3 ns143.2 nsCPU 143.1 ns1.078x1.071–1.098s1 1.072x · s2 1.096xUserCache 1.00xzval.h reference 1.08x±0.4%30
string64k1 key · warm · read65.5 nsCPU 65.5 ns80.1 nsCPU 80.1 ns1.218x †1.200–1.225s1 1.222x · s2 1.209xUserCache 1.00xzval.h reference 1.22x±2.8%30
string64k1 key · warm · mutate971.7 nsCPU 969.8 ns983.5 nsCPU 982.9 ns1.023x0.998–1.045s1 1.017x · s2 1.027xUserCache 1.00xzval.h reference 1.02xinterval includes 1.00x±0.1%30
packed81 key · warm · read66.6 nsCPU 66.5 ns85.3 nsCPU 85.1 ns1.271x1.259–1.277s1 1.279x · s2 1.265xUserCache 1.00xzval.h reference 1.27x±0.5%30
packed81 key · warm · read · TTL 360072.2 nsCPU 72.2 ns86.9 nsCPU 86.9 ns1.201x1.191–1.221s1 1.181x · s2 1.220xUserCache 1.00xzval.h reference 1.20x±0.3%30
packed81 key · warm · mutate94.7 nsCPU 94.7 ns110.2 nsCPU 110.2 ns1.162x1.157–1.172s1 1.160x · s2 1.164xUserCache 1.00xzval.h reference 1.16x±1.7%30
packed832,768 keys · warm · read73.1 nsCPU 73.0 ns95.5 nsCPU 95.5 ns1.305x1.288–1.335s1 1.325x · s2 1.291xUserCache 1.00xzval.h reference 1.30x±1.3%30
packed832,768 keys · warm · mutate101.8 nsCPU 101.7 ns121.5 nsCPU 121.4 ns1.208x1.194–1.217s1 1.210x · s2 1.202xUserCache 1.00xzval.h reference 1.21x±0.3%30
packed832,768 keys · cold · read171.4 nsCPU 171.3 ns192.7 nsCPU 192.7 ns1.126x1.114–1.150s1 1.156x · s2 1.104xUserCache 1.00xzval.h reference 1.13x±0.5%30
packed5121 key · warm · read66.7 nsCPU 66.6 ns85.1 nsCPU 85.0 ns1.270x †1.263–1.286s1 1.281x · s2 1.267xUserCache 1.00xzval.h reference 1.27x±2.3%30
packed5121 key · warm · mutate380.7 nsCPU 380.5 ns400.7 nsCPU 400.7 ns1.052x1.049–1.062s1 1.051x · s2 1.062xUserCache 1.00xzval.h reference 1.05x±0.1%30
hash321 key · warm · read70.1 nsCPU 70.1 ns85.7 nsCPU 85.6 ns1.224x1.208–1.234s1 1.209x · s2 1.230xUserCache 1.00xzval.h reference 1.22x±0.2%30
hash321 key · warm · mutate149.9 nsCPU 149.8 ns162.6 nsCPU 162.5 ns1.083x1.069–1.093s1 1.089x · s2 1.076xUserCache 1.00xzval.h reference 1.08x±1.8%30
hash3232,768 keys · warm · read276.1 nsCPU 276.0 ns359.4 nsCPU 359.3 ns1.301x †1.225–1.351s1 1.280x · s2 1.301xUserCache 1.00xzval.h reference 1.30x±13.2%30
hash3232,768 keys · warm · mutate354.1 nsCPU 354.1 ns388.0 nsCPU 383.5 ns1.087x †0.991–1.401s1 1.373x · s2 1.013xUserCache 1.00xzval.h reference 1.09xinterval includes 1.00x±7.2%30
hash3232,768 keys · cold · read726.4 nsCPU 725.3 ns780.3 nsCPU 779.2 ns1.082x †1.047–1.108s1 1.062x · s2 1.085xUserCache 1.00xzval.h reference 1.08x±5.7%30
nested1 key · warm · read73.6 nsCPU 73.6 ns83.6 nsCPU 83.4 ns1.139x1.122–1.147s1 1.122x · s2 1.147xUserCache 1.00xzval.h reference 1.14x±0.4%30
nested1 key · warm · mutate128.2 nsCPU 128.2 ns136.4 nsCPU 136.2 ns1.069x1.051–1.081s1 1.075x · s2 1.058xUserCache 1.00xzval.h reference 1.07x±0.3%30

HTTP worker scaling

Real HTTP requests to FrankenPHP workers. Throughput ratio is the UserCache throughput divided by the reference throughput; above 1.00x UserCache is faster. Closed-loop clients equal twice the worker count, with all workers warmed before timing. The array fixture has TTL 3600; the scalar fixture has TTL 0. Both share 32 keys.HTTP scope note

Throughput

CaseUserCachezval.h referenceThroughput ratioFasterRounds
array / read1 worker · 100 ops/request · TTL 360017,209 req/s1,720,903 ops/sp50 106.7 µs · p99 254.4 µs17,083 req/s1,708,260 ops/sp50 107.5 µs · p99 229.2 µs0.998x0.976–1.022zval.h reference 1.00xUserCache 1.00xinterval includes 1.00x5
array / read2 workers · 100 ops/request · TTL 360029,064 req/s2,906,447 ops/sp50 113.9 µs · p99 456.0 µs29,349 req/s2,934,864 ops/sp50 114.1 µs · p99 428.2 µs0.970x0.870–1.229zval.h reference 1.00xUserCache 1.03xinterval includes 1.00x5
array / read4 workers · 100 ops/request · TTL 360046,134 req/s4,613,394 ops/sp50 157.3 µs · p99 437.2 µs44,873 req/s4,487,288 ops/sp50 162.4 µs · p99 444.9 µs1.028x1.009–1.036UserCache 1.00xzval.h reference 1.03x5
array / 99% read + 1% store1 worker · 100 ops/request · TTL 360015,071 req/s1,507,129 ops/sp50 115.0 µs · p99 462.5 µs16,612 req/s1,661,225 ops/sp50 108.9 µs · p99 276.7 µs0.907x0.767–0.985zval.h reference 1.00xUserCache 1.10x5
array / 99% read + 1% store2 workers · 100 ops/request · TTL 360032,857 req/s3,285,724 ops/sp50 102.9 µs · p99 376.7 µs31,201 req/s3,120,100 ops/sp50 108.1 µs · p99 399.3 µs1.033x0.733–1.261UserCache 1.00xzval.h reference 1.03xinterval includes 1.00x5
array / 99% read + 1% store4 workers · 100 ops/request · TTL 360042,735 req/s4,273,521 ops/sp50 170.0 µs · p99 475.0 µs37,442 req/s3,744,166 ops/sp50 194.8 µs · p99 531.4 µs1.141x1.139–1.153UserCache 1.00xzval.h reference 1.14x5
scalar / read1 worker · 100 ops/request · TTL 022,474 req/s2,247,421 ops/sp50 79.0 µs · p99 169.6 µs21,673 req/s2,167,281 ops/sp50 85.5 µs · p99 165.5 µs1.037x1.025–1.089UserCache 1.00xzval.h reference 1.04x5
scalar / read2 workers · 100 ops/request · TTL 045,020 req/s4,502,042 ops/sp50 72.3 µs · p99 300.1 µs44,595 req/s4,459,480 ops/sp50 74.2 µs · p99 289.8 µs1.025x1.001–1.096UserCache 1.00xzval.h reference 1.02x5
scalar / read4 workers · 100 ops/request · TTL 056,015 req/s5,601,461 ops/sp50 126.5 µs · p99 390.2 µs53,251 req/s5,325,103 ops/sp50 134.0 µs · p99 407.6 µs1.052x1.041–1.063UserCache 1.00xzval.h reference 1.05x5
scalar / 99% read + 1% store1 worker · 100 ops/request · TTL 021,342 req/s2,134,154 ops/sp50 85.7 µs · p99 175.2 µs20,679 req/s2,067,873 ops/sp50 88.5 µs · p99 172.0 µs1.031x1.021–1.051UserCache 1.00xzval.h reference 1.03x5
scalar / 99% read + 1% store2 workers · 100 ops/request · TTL 042,135 req/s4,213,497 ops/sp50 75.5 µs · p99 393.3 µs39,682 req/s3,968,182 ops/sp50 81.0 µs · p99 408.7 µs1.048x0.995–1.173UserCache 1.00xzval.h reference 1.05xinterval includes 1.00x5
scalar / 99% read + 1% store4 workers · 100 ops/request · TTL 054,166 req/s5,416,551 ops/sp50 131.0 µs · p99 404.4 µs49,224 req/s4,922,413 ops/sp50 145.8 µs · p99 420.5 µs1.100x1.093–1.109UserCache 1.00xzval.h reference 1.10x5
array / read1 worker · 1 op/request · TTL 360026,696 req/s26,696 ops/sp50 64.6 µs · p99 177.0 µs27,158 req/s27,158 ops/sp50 61.0 µs · p99 186.2 µs0.976x0.942–0.990zval.h reference 1.00xUserCache 1.02x5
array / read2 workers · 1 op/request · TTL 360047,976 req/s47,976 ops/sp50 65.9 µs · p99 316.5 µs41,528 req/s41,528 ops/sp50 70.7 µs · p99 448.0 µs1.077x1.032–2.041UserCache 1.00xzval.h reference 1.08x5
array / read4 workers · 1 op/request · TTL 360062,497 req/s62,497 ops/sp50 111.4 µs · p99 375.4 µs63,248 req/s63,248 ops/sp50 110.4 µs · p99 365.6 µs0.987x0.979–1.014zval.h reference 1.00xUserCache 1.01xinterval includes 1.00x5
array / 99% read + 1% store1 worker · 1 op/request · TTL 360026,383 req/s26,383 ops/sp50 66.6 µs · p99 185.3 µs27,049 req/s27,049 ops/sp50 63.5 µs · p99 172.3 µs0.989x0.932–1.014zval.h reference 1.00xUserCache 1.01xinterval includes 1.00x5
array / 99% read + 1% store2 workers · 1 op/request · TTL 360042,893 req/s42,893 ops/sp50 72.9 µs · p99 374.0 µs46,648 req/s46,648 ops/sp50 65.5 µs · p99 342.9 µs0.874x0.811–1.267zval.h reference 1.00xUserCache 1.14xinterval includes 1.00x5
array / 99% read + 1% store4 workers · 1 op/request · TTL 360062,344 req/s62,344 ops/sp50 112.2 µs · p99 366.7 µs63,193 req/s63,193 ops/sp50 110.8 µs · p99 364.1 µs0.993x0.976–1.092zval.h reference 1.00xUserCache 1.01xinterval includes 1.00x5
scalar / read1 worker · 1 op/request · TTL 027,954 req/s27,954 ops/sp50 59.5 µs · p99 143.9 µs28,342 req/s28,342 ops/sp50 57.6 µs · p99 139.8 µs0.986x0.955–1.015zval.h reference 1.00xUserCache 1.01xinterval includes 1.00x5
scalar / read2 workers · 1 op/request · TTL 052,138 req/s52,138 ops/sp50 61.5 µs · p99 258.8 µs52,311 req/s52,311 ops/sp50 60.9 µs · p99 255.0 µs0.996x0.990–0.997zval.h reference 1.00xUserCache 1.00x5
scalar / read4 workers · 1 op/request · TTL 061,113 req/s61,113 ops/sp50 113.0 µs · p99 391.4 µs61,366 req/s61,366 ops/sp50 113.4 µs · p99 382.4 µs0.998x0.985–1.044zval.h reference 1.00xUserCache 1.00xinterval includes 1.00x5
scalar / 99% read + 1% store1 worker · 1 op/request · TTL 027,318 req/s27,318 ops/sp50 58.9 µs · p99 145.6 µs28,196 req/s28,196 ops/sp50 57.8 µs · p99 143.2 µs0.981x0.946–0.995zval.h reference 1.00xUserCache 1.02x5
scalar / 99% read + 1% store2 workers · 1 op/request · TTL 051,849 req/s51,849 ops/sp50 61.9 µs · p99 263.0 µs51,856 req/s51,856 ops/sp50 61.7 µs · p99 259.3 µs0.993x0.992–1.009zval.h reference 1.00xUserCache 1.01xinterval includes 1.00x5
scalar / 99% read + 1% store4 workers · 1 op/request · TTL 062,443 req/s62,443 ops/sp50 111.6 µs · p99 370.8 µs62,594 req/s62,594 ops/sp50 110.6 µs · p99 366.7 µs0.998x0.984–1.009zval.h reference 1.00xUserCache 1.00xinterval includes 1.00x5

Time inside PHP

Median PHP batch time per cache operation within each request, with the PHP thread CPU per operation for the whole request. Speedup is the reference median divided by the UserCache median. These medians have no paired interval, so they are not colored; the lower median is in green text. With one operation per request, each batch is the first fetch of its request and includes per-request setup, and the cache call is a small part of the request (compare the thread CPU with the HTTP latency above), so throughput mostly reflects HTTP and client overhead.

CaseUserCachezval.h referenceSpeedup of medians
array / read1 worker · 100 ops/request · TTL 3600176.7 ns/opPHP thread CPU 179.1 ns/op176.0 ns/opPHP thread CPU 178.8 ns/op0.996x
array / read2 workers · 100 ops/request · TTL 3600227.0 ns/opPHP thread CPU 225.2 ns/op235.6 ns/opPHP thread CPU 232.9 ns/op1.038x
array / read4 workers · 100 ops/request · TTL 3600180.9 ns/opPHP thread CPU 184.5 ns/op203.8 ns/opPHP thread CPU 207.3 ns/op1.127x
array / 99% read + 1% store1 worker · 100 ops/request · TTL 3600215.6 ns/opPHP thread CPU 216.3 ns/op191.0 ns/opPHP thread CPU 193.7 ns/op0.886x
array / 99% read + 1% store2 workers · 100 ops/request · TTL 3600222.3 ns/opPHP thread CPU 219.1 ns/op251.6 ns/opPHP thread CPU 237.5 ns/op1.132x
array / 99% read + 1% store4 workers · 100 ops/request · TTL 3600239.0 ns/opPHP thread CPU 232.9 ns/op364.0 ns/opPHP thread CPU 269.3 ns/op1.523x
scalar / read1 worker · 100 ops/request · TTL 058.8 ns/opPHP thread CPU 62.0 ns/op74.6 ns/opPHP thread CPU 77.7 ns/op1.267x
scalar / read2 workers · 100 ops/request · TTL 061.4 ns/opPHP thread CPU 64.3 ns/op85.5 ns/opPHP thread CPU 88.0 ns/op1.393x
scalar / read4 workers · 100 ops/request · TTL 061.1 ns/opPHP thread CPU 64.9 ns/op93.8 ns/opPHP thread CPU 97.6 ns/op1.536x
scalar / 99% read + 1% store1 worker · 100 ops/request · TTL 072.3 ns/opPHP thread CPU 75.4 ns/op83.2 ns/opPHP thread CPU 86.6 ns/op1.151x
scalar / 99% read + 1% store2 workers · 100 ops/request · TTL 078.4 ns/opPHP thread CPU 80.5 ns/op109.3 ns/opPHP thread CPU 106.8 ns/op1.394x
scalar / 99% read + 1% store4 workers · 100 ops/request · TTL 077.1 ns/opPHP thread CPU 80.8 ns/op146.4 ns/opPHP thread CPU 120.2 ns/op1.899x
array / read1 worker · 1 op/request · TTL 3600477.5 ns/opPHP thread CPU 831.0 ns/op423.6 ns/opPHP thread CPU 772.8 ns/op0.887x
array / read2 workers · 1 op/request · TTL 3600524.5 ns/opPHP thread CPU 930.2 ns/op640.2 ns/opPHP thread CPU 1,087.3 ns/op1.221x
array / read4 workers · 1 op/request · TTL 3600528.7 ns/opPHP thread CPU 971.5 ns/op522.7 ns/opPHP thread CPU 962.5 ns/op0.989x
array / 99% read + 1% store1 worker · 1 op/request · TTL 3600547.2 ns/opPHP thread CPU 895.2 ns/op467.1 ns/opPHP thread CPU 803.3 ns/op0.854x
array / 99% read + 1% store2 workers · 1 op/request · TTL 3600714.4 ns/opPHP thread CPU 1,145.7 ns/op593.1 ns/opPHP thread CPU 994.6 ns/op0.830x
array / 99% read + 1% store4 workers · 1 op/request · TTL 3600635.5 ns/opPHP thread CPU 1,063.5 ns/op575.7 ns/opPHP thread CPU 1,007.7 ns/op0.906x
scalar / read1 worker · 1 op/request · TTL 0270.0 ns/opPHP thread CPU 611.1 ns/op218.3 ns/opPHP thread CPU 551.2 ns/op0.809x
scalar / read2 workers · 1 op/request · TTL 0269.2 ns/opPHP thread CPU 642.8 ns/op234.5 ns/opPHP thread CPU 604.2 ns/op0.871x
scalar / read4 workers · 1 op/request · TTL 0319.3 ns/opPHP thread CPU 749.2 ns/op282.1 ns/opPHP thread CPU 708.2 ns/op0.883x
scalar / 99% read + 1% store1 worker · 1 op/request · TTL 0302.5 ns/opPHP thread CPU 628.6 ns/op229.3 ns/opPHP thread CPU 564.2 ns/op0.758x
scalar / 99% read + 1% store2 workers · 1 op/request · TTL 0337.5 ns/opPHP thread CPU 703.7 ns/op265.0 ns/opPHP thread CPU 634.8 ns/op0.785x
scalar / 99% read + 1% store4 workers · 1 op/request · TTL 0398.6 ns/opPHP thread CPU 826.8 ns/op303.9 ns/opPHP thread CPU 731.4 ns/op0.762x

Memory usage

The supplied micro host configures UserCache SHM capacity at 256 MiB, entries_hint at 65,536 and PHP memory_limit at 768 MiB. The HTTP host configures SHM at 32 MiB and memory_limit at 256 MiB, leaving entries_hint at the extension default. These are configured capacities/limits, separate from the measured used-byte snapshots below; neither is process RSS.

cached data: for UserCache, shared memory used above the empty segment (the empty segment already holds the entry tables sized by entries_hint; the reference sample of the same host shows it), including keys and allocator overhead; for the reference, requested persistent helper allocations, excluding allocator rounding and some wrapper metadata. PHP heap: sampled worker PHP heap after the reads, above the heap after reset, including warm prototypes and bookkeeping such as UserCache per-key records. PHP peak: peak heap above the heap after reset. Fetched values are released each iteration. These categories cannot be added as if they described equal allocations. The smaller value of each category is highlighted, including ties.

PHP fetch batch data sets

Data setUserCachezval.h reference
null1 keycached data 32 BPHP heap 3.0 KiBPHP peak 3.0 KiBcached data 392 BPHP heap 2.6 KiBPHP peak 2.6 KiB
bool1 keycached data 32 BPHP heap 3.0 KiBPHP peak 3.0 KiBcached data 392 BPHP heap 2.6 KiBPHP peak 2.6 KiB
int1 keycached data 32 BPHP heap 3.0 KiBPHP peak 3.0 KiBcached data 392 BPHP heap 2.6 KiBPHP peak 2.6 KiB
int32,768 keyscached data 1.00 MiBPHP heap 6.01 MiBPHP peak 6.01 MiBcached data 3.50 MiBPHP heap 3.76 MiBPHP peak 4.00 MiB
double1 keycached data 32 BPHP heap 3.0 KiBPHP peak 3.0 KiBcached data 392 BPHP heap 2.6 KiBPHP peak 2.6 KiB
string321 keycached data 64 BPHP heap 3.1 KiBPHP peak 3.1 KiBcached data 456 BPHP heap 2.7 KiBPHP peak 2.7 KiB
string3001 keycached data 328 BPHP heap 3.4 KiBPHP peak 3.4 KiBcached data 720 BPHP heap 3.0 KiBPHP peak 3.0 KiB
string30032,768 keyscached data 10.50 MiBPHP heap 6.01 MiBPHP peak 6.01 MiBcached data 13.75 MiBPHP heap 3.76 MiBPHP peak 4.00 MiB
string4k1 keycached data 4.1 KiBPHP heap 19.0 KiBPHP peak 19.0 KiBcached data 4.4 KiBPHP heap 18.6 KiBPHP peak 18.6 KiB
string64k1 keycached data 65.0 KiBPHP heap 139.0 KiBPHP peak 139.0 KiBcached data 64.4 KiBPHP heap 138.6 KiBPHP peak 138.6 KiB
packed81 keycached data 264 BPHP heap 3.4 KiBPHP peak 3.4 KiBcached data 712 BPHP heap 3.0 KiBPHP peak 3.0 KiB
packed832,768 keyscached data 8.25 MiBPHP heap 12.76 MiBPHP peak 12.76 MiBcached data 13.50 MiBPHP heap 10.51 MiBPHP peak 10.51 MiB
packed5121 keycached data 8.2 KiBPHP heap 27.1 KiBPHP peak 27.1 KiBcached data 16.4 KiBPHP heap 26.7 KiBPHP peak 26.7 KiB
hash321 keycached data 2.6 KiBPHP heap 8.1 KiBPHP peak 8.7 KiBcached data 2.9 KiBPHP heap 7.7 KiBPHP peak 7.7 KiB
hash3232,768 keyscached data 84.00 MiBPHP heap 87.76 MiBPHP peak 87.76 MiBcached data 85.25 MiBPHP heap 85.51 MiBPHP peak 85.51 MiB
nested1 keycached data 2.3 KiBPHP heap 10.4 KiBPHP peak 10.6 KiBcached data 4.1 KiBPHP heap 9.9 KiBPHP peak 9.9 KiB

HTTP fixtures at the end of each case

HTTP end status samples one worker PHP heap; it is not total heap across all workers or process RSS. Shared/persistent stores are process-wide.

FixtureUserCachezval.h reference
array32 keys · median of 12 casescached data 28.2 KiBworker PHP heap 521.6 KiBcached data 35.5 KiBworker PHP heap 515.7 KiB
scalar32 keys · median of 12 casescached data 1.0 KiBworker PHP heap 481.7 KiBcached data 3.2 KiBworker PHP heap 478.8 KiB
All memory snapshots (bytes, medians of absolute values)

The inactive backend still exists in the host, so the UserCache shared used bytes of a reference sample show the empty segment. Peak is reset per case. In-request graph pins are recorded for each sample.

CaseBackendShared used BReference persistent BPHP reset BPHP seed BPHP warm BPHP after BPHP peak BIn-request graph pins
null / 1 key · warm · readUserCache3,914,2960495,152496,720496,720498,248498,2480
null / 1 key · warm · readzval.h reference3,914,264392495,152495,864496,264497,792497,7920
bool / 1 key · warm · readUserCache3,914,2960495,152496,720496,720498,248498,2480
bool / 1 key · warm · readzval.h reference3,914,264392495,152495,864496,264497,792497,7920
int / 1 key · warm · readUserCache3,914,2960495,152496,720496,720498,248498,2480
int / 1 key · warm · readzval.h reference3,914,264392495,152495,864496,264497,792497,7920
int / 32,768 keys · warm · readUserCache4,962,8400495,2006,792,0806,792,0806,793,6086,793,6080
int / 32,768 keys · warm · readzval.h reference3,914,2643,670,016495,2002,334,8164,432,0244,433,5524,694,1920
int / 32,768 keys · warm · mutate flag (scalar no-op)UserCache4,962,8400495,2006,792,0806,792,0806,793,6086,793,6080
int / 32,768 keys · warm · mutate flag (scalar no-op)zval.h reference3,914,2643,670,016495,2002,334,8164,432,0244,433,5524,694,1920
int / 32,768 keys · cold · readUserCache4,962,8400495,2006,792,0806,792,0806,793,6086,793,6080
int / 32,768 keys · cold · readzval.h reference3,914,2643,670,016495,1842,334,8002,334,8004,433,5364,694,1760
double / 1 key · warm · readUserCache3,914,2960495,168496,736496,736498,264498,2640
double / 1 key · warm · readzval.h reference3,914,264392495,168495,880496,280497,808497,8080
string32 / 1 key · warm · readUserCache3,914,3280495,176496,808496,872498,400498,4000
string32 / 1 key · warm · readzval.h reference3,914,264456495,176495,952496,416497,944497,9440
string32 / 1 key · warm · mutateUserCache3,914,3280495,192496,824496,888498,416498,4160
string32 / 1 key · warm · mutatezval.h reference3,914,264456495,176495,952496,416497,944497,9440
string300 / 1 key · warm · readUserCache3,914,5920495,176497,128497,128498,656498,6560
string300 / 1 key · warm · readzval.h reference3,914,264720495,176496,672496,672498,200498,2000
string300 / 1 key · warm · mutateUserCache3,914,5920495,192497,144497,144498,672498,6720
string300 / 1 key · warm · mutatezval.h reference3,914,264720495,192496,688496,688498,216498,2160
string300 / 32,768 keys · warm · readUserCache14,923,5120495,2086,792,4726,792,4726,794,0006,794,0000
string300 / 32,768 keys · warm · readzval.h reference3,914,26414,417,920495,2084,432,4164,432,4164,433,9444,694,5840
string300 / 32,768 keys · warm · mutateUserCache14,923,5120495,2566,792,5206,792,5206,794,0486,794,0480
string300 / 32,768 keys · warm · mutatezval.h reference3,914,26414,417,920495,2564,432,4644,432,4644,433,9924,694,6320
string300 / 32,768 keys · cold · readUserCache14,923,5120495,2086,792,4726,792,4726,794,0006,794,0000
string300 / 32,768 keys · cold · readzval.h reference3,914,26414,417,920495,2084,432,4164,432,4164,433,9444,694,5840
string4k / 1 key · warm · readUserCache3,918,4880495,176504,936513,128514,656514,6560
string4k / 1 key · warm · readzval.h reference3,914,2644,520495,176504,080512,672514,200514,2000
string4k / 1 key · warm · mutateUserCache3,918,4880495,192504,952513,144514,672521,3680
string4k / 1 key · warm · mutatezval.h reference3,914,2644,520495,176504,080512,672514,200520,8960
string64k / 1 key · warm · readUserCache3,980,8240495,176566,376636,008637,536637,5360
string64k / 1 key · warm · readzval.h reference3,914,26465,960495,176565,520635,552637,080637,0800
string64k / 1 key · warm · mutateUserCache3,980,8240495,192566,392636,024637,552705,6880
string64k / 1 key · warm · mutatezval.h reference3,914,26465,960495,192565,536635,568637,096705,2320
packed8 / 1 key · warm · readUserCache3,914,5280495,168496,952497,168498,696498,6960
packed8 / 1 key · warm · readzval.h reference3,914,264712495,168496,096496,712498,240498,2400
packed8 / 1 key · warm · read · TTL 3600UserCache3,914,5280495,200496,984497,200498,728498,7280
packed8 / 1 key · warm · read · TTL 3600zval.h reference3,914,264712495,200496,128496,744498,272498,2720
packed8 / 1 key · warm · mutateUserCache3,914,5280495,168496,952497,168498,696498,6960
packed8 / 1 key · warm · mutatezval.h reference3,914,264712495,168496,096496,712498,240498,2400
packed8 / 32,768 keys · warm · readUserCache12,565,0160495,2006,792,29613,870,18413,871,71213,871,7120
packed8 / 32,768 keys · warm · readzval.h reference3,914,26414,155,776495,2002,335,03211,510,12811,511,65611,511,6560
packed8 / 32,768 keys · warm · mutateUserCache12,565,0160495,2166,792,31213,870,20013,871,72813,871,7280
packed8 / 32,768 keys · warm · mutatezval.h reference3,914,26414,155,776495,2162,335,04811,510,14411,511,67211,511,6720
packed8 / 32,768 keys · cold · readUserCache12,565,0160495,2006,792,2966,792,29613,871,71213,871,7120
packed8 / 32,768 keys · cold · readzval.h reference3,914,26414,155,776495,2002,335,0322,335,03211,511,65611,511,6560
packed512 / 1 key · warm · readUserCache3,922,7120495,176509,088521,432522,960522,9600
packed512 / 1 key · warm · readzval.h reference3,914,26416,840495,176508,232520,976522,504522,5040
packed512 / 1 key · warm · mutateUserCache3,922,7120495,192509,104521,448522,976533,8240
packed512 / 1 key · warm · mutatezval.h reference3,914,26416,840495,192508,248520,992522,520533,3680
hash32 / 1 key · warm · readUserCache3,916,9520495,168499,352501,968503,496504,0880
hash32 / 1 key · warm · readzval.h reference3,914,2643,008495,168498,496501,512503,040503,0400
hash32 / 1 key · warm · mutateUserCache3,916,9520495,168499,352501,968503,496504,0880
hash32 / 1 key · warm · mutatezval.h reference3,914,2643,008495,168498,496501,512503,040503,0400
hash32 / 32,768 keys · warm · readUserCache91,994,6480495,2006,794,69692,515,78492,517,31292,517,6160
hash32 / 32,768 keys · warm · readzval.h reference3,914,26489,391,104495,2002,337,43290,155,72890,157,25690,157,2560
hash32 / 32,768 keys · warm · mutateUserCache91,994,6480495,2166,794,71292,515,80092,517,32892,517,6320
hash32 / 32,768 keys · warm · mutatezval.h reference3,914,26489,391,104495,2162,337,44890,155,74490,157,27290,157,2720
hash32 / 32,768 keys · cold · readUserCache91,994,6480495,2006,794,6966,794,69692,517,31292,517,6160
hash32 / 32,768 keys · cold · readzval.h reference3,914,26489,391,104495,2002,337,4322,337,43290,157,25690,157,2560
nested / 1 key · warm · readUserCache3,916,6000495,168500,472504,272505,800506,0000
nested / 1 key · warm · readzval.h reference3,914,2644,232495,168499,616503,752505,280505,2800
nested / 1 key · warm · mutateUserCache3,916,6000495,168500,472504,272505,800506,0000
nested / 1 key · warm · mutatezval.h reference3,914,2644,232495,168499,616503,752505,280505,2800
HTTP caseBackendShared used BReference persistent BSampled worker PHP heap B
array / read · 1 worker · 100 ops/requestUserCache2,019,9520534,104
array / read · 1 worker · 100 ops/requestzval.h reference1,991,02436,352528,104
array / read · 2 workers · 100 ops/requestUserCache2,019,9520534,104
array / read · 2 workers · 100 ops/requestzval.h reference1,991,02436,352528,104
array / read · 4 workers · 100 ops/requestUserCache2,019,9520534,104
array / read · 4 workers · 100 ops/requestzval.h reference1,991,02436,352528,104
array / 99% read + 1% store · 1 worker · 100 ops/requestUserCache2,019,9520534,120
array / 99% read + 1% store · 1 worker · 100 ops/requestzval.h reference1,991,02436,352528,120
array / 99% read + 1% store · 2 workers · 100 ops/requestUserCache2,019,9520534,120
array / 99% read + 1% store · 2 workers · 100 ops/requestzval.h reference1,991,02436,352528,120
array / 99% read + 1% store · 4 workers · 100 ops/requestUserCache2,019,9520534,120
array / 99% read + 1% store · 4 workers · 100 ops/requestzval.h reference1,991,02436,352528,120
scalar / read · 1 worker · 100 ops/requestUserCache1,992,0480493,232
scalar / read · 1 worker · 100 ops/requestzval.h reference1,991,0243,328490,304
scalar / read · 2 workers · 100 ops/requestUserCache1,992,0480493,232
scalar / read · 2 workers · 100 ops/requestzval.h reference1,991,0243,328490,304
scalar / read · 4 workers · 100 ops/requestUserCache1,992,0480493,232
scalar / read · 4 workers · 100 ops/requestzval.h reference1,991,0243,328490,304
scalar / 99% read + 1% store · 1 worker · 100 ops/requestUserCache1,992,0480493,232
scalar / 99% read + 1% store · 1 worker · 100 ops/requestzval.h reference1,991,0243,328490,304
scalar / 99% read + 1% store · 2 workers · 100 ops/requestUserCache1,992,0480493,232
scalar / 99% read + 1% store · 2 workers · 100 ops/requestzval.h reference1,991,0243,328490,304
scalar / 99% read + 1% store · 4 workers · 100 ops/requestUserCache1,992,0480493,232
scalar / 99% read + 1% store · 4 workers · 100 ops/requestzval.h reference1,991,0243,328490,304
array / read · 1 worker · 1 op/requestUserCache2,019,9520534,072
array / read · 1 worker · 1 op/requestzval.h reference1,991,02436,352528,056
array / read · 2 workers · 1 op/requestUserCache2,019,9520534,072
array / read · 2 workers · 1 op/requestzval.h reference1,991,02436,352528,056
array / read · 4 workers · 1 op/requestUserCache2,019,9520534,072
array / read · 4 workers · 1 op/requestzval.h reference1,991,02436,352528,056
array / 99% read + 1% store · 1 worker · 1 op/requestUserCache2,019,9520534,088
array / 99% read + 1% store · 1 worker · 1 op/requestzval.h reference1,991,02436,352528,088
array / 99% read + 1% store · 2 workers · 1 op/requestUserCache2,019,9520534,088
array / 99% read + 1% store · 2 workers · 1 op/requestzval.h reference1,991,02436,352528,088
array / 99% read + 1% store · 4 workers · 1 op/requestUserCache2,019,9520534,088
array / 99% read + 1% store · 4 workers · 1 op/requestzval.h reference1,991,02436,352528,088
scalar / read · 1 worker · 1 op/requestUserCache1,992,0480493,200
scalar / read · 1 worker · 1 op/requestzval.h reference1,991,0243,328490,256
scalar / read · 2 workers · 1 op/requestUserCache1,992,0480493,200
scalar / read · 2 workers · 1 op/requestzval.h reference1,991,0243,328490,256
scalar / read · 4 workers · 1 op/requestUserCache1,992,0480493,200
scalar / read · 4 workers · 1 op/requestzval.h reference1,991,0243,328490,256
scalar / 99% read + 1% store · 1 worker · 1 op/requestUserCache1,992,0480493,200
scalar / 99% read + 1% store · 1 worker · 1 op/requestzval.h reference1,991,0243,328490,272
scalar / 99% read + 1% store · 2 workers · 1 op/requestUserCache1,992,0480493,200
scalar / 99% read + 1% store · 2 workers · 1 op/requestzval.h reference1,991,0243,328490,272
scalar / 99% read + 1% store · 4 workers · 1 op/requestUserCache1,992,0480493,200
scalar / 99% read + 1% store · 4 workers · 1 op/requestzval.h reference1,991,0243,328490,272

A/A measurement noise

The same reference wrapper measured against itself with the same pairing, as second run time ÷ first run time. A UserCache speedup closer to 1.00x than this spread is not a difference; A/A medians beyond ±2% are marked †.

CaseSecond / first medianObserved pair rangePair p25–p75Median 95% intervalPairs
null1 key · warm · read1.012x0.767–1.7450.961–1.0630.950–1.06615
bool1 key · warm · read0.990x0.768–1.3530.945–1.0450.910–1.02515
int1 key · warm · read1.001x0.788–1.5470.959–1.0410.960–1.04115
int32,768 keys · warm · read1.013x0.953–1.0531.003–1.0191.004–1.02015
int32,768 keys · warm · mutate flag (scalar no-op)1.015x0.843–1.0690.985–1.0300.975–1.02815
int32,768 keys · cold · read0.977x †0.928–1.1660.949–1.0020.945–1.00315
double1 key · warm · read1.017x0.910–1.3100.978–1.0590.987–1.04615
string321 key · warm · read0.971x †0.858–1.4740.942–1.0360.932–1.04115
string321 key · warm · mutate0.990x0.895–1.3970.954–1.0630.968–1.06315
string3001 key · warm · read1.000x0.928–1.1490.971–1.0890.968–1.08515
string3001 key · warm · mutate0.943x †0.719–1.2100.917–1.0340.903–1.05115
string30032,768 keys · warm · read1.009x0.915–1.0810.978–1.0190.980–1.01615
string30032,768 keys · warm · mutate0.993x0.834–1.0610.973–1.0330.960–1.03515
string30032,768 keys · cold · read1.019x0.840–1.1080.995–1.0290.994–1.03015
string4k1 key · warm · read0.975x †0.789–1.1820.917–1.0570.915–1.07215
string4k1 key · warm · mutate1.004x0.773–1.4280.965–1.0780.969–1.07915
string64k1 key · warm · read0.972x †0.795–1.3390.957–1.0240.956–1.03715
string64k1 key · warm · mutate0.999x0.933–1.1200.967–1.0520.956–1.03215
packed81 key · warm · read1.005x0.926–1.0500.981–1.0170.983–1.02415
packed81 key · warm · read · TTL 36001.003x0.664–1.0350.996–1.0150.996–1.01815
packed81 key · warm · mutate0.983x0.932–1.0510.970–1.0250.966–1.01615
packed832,768 keys · warm · read0.987x0.906–1.0450.969–1.0110.963–1.01415
packed832,768 keys · warm · mutate0.997x0.936–1.1290.953–1.0260.954–1.02115
packed832,768 keys · cold · read0.995x0.827–1.0590.982–1.0010.984–1.00215
packed5121 key · warm · read0.977x †0.957–3.0000.973–1.0230.971–1.03215
packed5121 key · warm · mutate0.999x0.942–1.0600.985–1.0120.987–1.01715
hash321 key · warm · read1.002x0.967–1.0590.978–1.0160.980–1.01715
hash321 key · warm · mutate0.982x0.936–1.0790.966–1.0270.955–1.02415
hash3232,768 keys · warm · read1.132x †0.712–1.7361.047–1.1621.045–1.16215
hash3232,768 keys · warm · mutate1.072x †1.033–1.1091.044–1.0911.043–1.09015
hash3232,768 keys · cold · read1.057x †0.631–1.3621.038–1.0851.027–1.08315
nested1 key · warm · read1.004x0.919–1.0860.973–1.0300.966–1.03015
nested1 key · warm · mutate0.997x0.864–1.0920.976–1.0260.982–1.03915

Raw helper diagnostic — no cache speed ratio

Reads call persistent_zval_to_request from an already persisted value. They do not persist/free per iteration, perform key lookup, implement TTL or share the warm wrapper prototype cache. The 32,768-key label records the surrounding workload shape; the raw helper still has one source value. This is an allocation/copy lower-level diagnostic, not a public FrankenPHP cache comparison, and never enters the rankings above.

Raw helper timings
Case shapeRaw helper ns/opRaw helper CPU ns/opSamples
null / 1 key · warm · read47.547.42
bool / 1 key · warm · read46.446.42
int / 1 key · warm · read47.247.22
int / 32,768 keys · warm · read45.845.82
int / 32,768 keys · warm · mutate flag (scalar no-op)45.945.82
int / 32,768 keys · cold · read46.946.92
double / 1 key · warm · read49.349.32
string32 / 1 key · warm · read67.867.82
string32 / 1 key · warm · mutate71.571.42
string300 / 1 key · warm · read73.573.52
string300 / 1 key · warm · mutate73.073.02
string300 / 32,768 keys · warm · read69.769.02
string300 / 32,768 keys · warm · mutate70.770.72
string300 / 32,768 keys · cold · read67.267.22
string4k / 1 key · warm · read106.0105.92
string4k / 1 key · warm · mutate109.5109.52
string64k / 1 key · warm · read907.9907.12
string64k / 1 key · warm · mutate923.2923.02
packed8 / 1 key · warm · read132.6132.52
packed8 / 1 key · warm · read · TTL 3600131.7131.72
packed8 / 1 key · warm · mutate142.1142.02
packed8 / 32,768 keys · warm · read135.4135.32
packed8 / 32,768 keys · warm · mutate146.4146.42
packed8 / 32,768 keys · cold · read132.1132.12
packed512 / 1 key · warm · read3,594.73,589.42
packed512 / 1 key · warm · mutate3,632.73,630.12
hash32 / 1 key · warm · read729.6729.62
hash32 / 1 key · warm · mutate672.6672.62
hash32 / 32,768 keys · warm · read701.9701.52
hash32 / 32,768 keys · warm · mutate791.2791.12
hash32 / 32,768 keys · cold · read664.1663.82
nested / 1 key · warm · read466.8466.62
nested / 1 key · warm · mutate492.8492.72

Environment

Measured2026-09-30T07:54:36.579770+00:00 to 2026-09-30T08:33:50.538804+00:00
Micro and A/A modeworker
Micro pairs15 pairs × 2 sessions
HTTP rounds5 rounds × 5 s
CPU affinity0-3
PlatformLinux-7.0.14-orbstack-00380-ga7e0a2dc9535-aarch64-with-glibc2.39
CPU count10
FrankenPHP revision51e6246e71f335b96ac22d7782f5b20392555109
Gogo1.27.0
Compilercc (Ubuntu 13.3.0-6ubuntu2~24.04.1) 13.3.0
PHP configure--disable-all --enable-cli --enable-embed=shared --enable-zts --disable-zend-signals --enable-zend-max-execution-timers --enable-pcntl --without-pcre-jit --disable-opcache-jit
Verified source inputs45,316,114 bytes · SHA-256 93cbd6973cbd24241f3e8a12ed50d5436eff1a91ca45379b0fdd37f2a17822ed

The source inputs archive includes the exact PHP input tree, harness assets, built source/config files and measurement producer snapshots, and stays in the local measurement workspace. The aggregate result, including provenance and the build manifest, is embedded in this HTML; raw JSONL samples and logs are not published.

Data and provenance

The aggregate result.json is embedded in this page unchanged, in <script id="embedded-result" type="application/json"> (schema_version 1). Its ratios keep the measured direction: micro[] and aa[] rows hold paired_ratio as UserCache time ÷ reference time (this page shows its reciprocal as the speedup) with median_ratio_ci95, and http[] rows hold paired_throughput_ratio as UserCache ÷ reference. Per-backend medians are under backends.user_cache and backends.reference.

JSON.parse(document.getElementById('embedded-result').textContent)

Official helper: pinned FrankenPHP zval.h. Build manifest and binary/library/fixture SHA-256 values are stored in the aggregate JSON.

Configuration and environment
{
  "created_at": "2026-09-30T07:54:36.579770+00:00",
  "configuration": {
    "build_dir": "/workspaces/php-src/php-user_cache_benchmark_harness/runtime/frankenphp",
    "output_dir": "/workspaces/php-src/php-user_cache_benchmark_harness/results/persistence-20260930T075436.577836Z",
    "output": "/workspaces/php-src/php-user_cache_benchmark_harness/BENCH_RESULT_PERSISTENCE.html",
    "build": false,
    "php_src": "/workspaces/php-src",
    "frankenphp_src": null,
    "jobs": 2,
    "quick": false,
    "pairs": 15,
    "rounds": 5,
    "sessions": 2,
    "seconds": 5,
    "cpus": "0-3",
    "seed": 1701,
    "stage": "all",
    "mode": "worker",
    "payloads": [
      "null",
      "bool",
      "int",
      "double",
      "string32",
      "string300",
      "string4k",
      "string64k",
      "packed8",
      "packed512",
      "hash32",
      "nested"
    ],
    "workers": [
      "1",
      "2",
      "4"
    ],
    "operations": [
      "1",
      "100"
    ],
    "kinds": [
      "array",
      "scalar"
    ],
    "modes": [
      "read",
      "mixed"
    ]
  },
  "environment": {
    "platform": "Linux-7.0.14-orbstack-00380-ga7e0a2dc9535-aarch64-with-glibc2.39",
    "machine": "aarch64",
    "python": "3.12.3 (main, Aug 31 2026, 10:18:26) [GCC 13.3.0]",
    "cpu_count": 10,
    "affinity": [
      0,
      1,
      2,
      3,
      4,
      5,
      6,
      7,
      8,
      9
    ]
  },
  "binaries": {
    "bench": {
      "path": "/workspaces/php-src/php-user_cache_benchmark_harness/runtime/frankenphp/bin/frankenphp-bench",
      "sha256": "8da32f12b5fa65223d78f037b0388cfd8201ccfd7062e1a50634cf428d6d554d"
    },
    "scale": {
      "path": "/workspaces/php-src/php-user_cache_benchmark_harness/runtime/frankenphp/bin/frankenphp-scale",
      "sha256": "545e5ddebd42b75cbdddb0b99dfe84338b423a446a1c58abcdd55585775f6ca6"
    }
  },
  "php_libraries": {
    "/workspaces/php-src/php-user_cache_benchmark_harness/runtime/frankenphp/install/lib/libphp.so": "2bebc91ccd5d1086684691a6bffbcd030ab9dbab7b8f17cae2ca594042bf1106"
  }
}
243 executions, 243 validated
ExecutionSample validationExit
aa-s1validated0
micro-s1validated0
micro-s2validated0
http-array-w1-o1-read-r0-user_cachevalidated0
http-array-w1-o1-read-r0-referencevalidated0
http-array-w1-o1-read-r1-referencevalidated0
http-array-w1-o1-read-r1-user_cachevalidated0
http-array-w1-o1-read-r2-user_cachevalidated0
http-array-w1-o1-read-r2-referencevalidated0
http-array-w1-o1-read-r3-referencevalidated0
http-array-w1-o1-read-r3-user_cachevalidated0
http-array-w1-o1-read-r4-user_cachevalidated0
http-array-w1-o1-read-r4-referencevalidated0
http-array-w1-o1-mixed-r0-user_cachevalidated0
http-array-w1-o1-mixed-r0-referencevalidated0
http-array-w1-o1-mixed-r1-referencevalidated0
http-array-w1-o1-mixed-r1-user_cachevalidated0
http-array-w1-o1-mixed-r2-user_cachevalidated0
http-array-w1-o1-mixed-r2-referencevalidated0
http-array-w1-o1-mixed-r3-referencevalidated0
http-array-w1-o1-mixed-r3-user_cachevalidated0
http-array-w1-o1-mixed-r4-user_cachevalidated0
http-array-w1-o1-mixed-r4-referencevalidated0
http-array-w1-o100-read-r0-user_cachevalidated0
http-array-w1-o100-read-r0-referencevalidated0
http-array-w1-o100-read-r1-referencevalidated0
http-array-w1-o100-read-r1-user_cachevalidated0
http-array-w1-o100-read-r2-user_cachevalidated0
http-array-w1-o100-read-r2-referencevalidated0
http-array-w1-o100-read-r3-referencevalidated0
http-array-w1-o100-read-r3-user_cachevalidated0
http-array-w1-o100-read-r4-user_cachevalidated0
http-array-w1-o100-read-r4-referencevalidated0
http-array-w1-o100-mixed-r0-user_cachevalidated0
http-array-w1-o100-mixed-r0-referencevalidated0
http-array-w1-o100-mixed-r1-referencevalidated0
http-array-w1-o100-mixed-r1-user_cachevalidated0
http-array-w1-o100-mixed-r2-user_cachevalidated0
http-array-w1-o100-mixed-r2-referencevalidated0
http-array-w1-o100-mixed-r3-referencevalidated0
http-array-w1-o100-mixed-r3-user_cachevalidated0
http-array-w1-o100-mixed-r4-user_cachevalidated0
http-array-w1-o100-mixed-r4-referencevalidated0
http-array-w2-o1-read-r0-referencevalidated0
http-array-w2-o1-read-r0-user_cachevalidated0
http-array-w2-o1-read-r1-user_cachevalidated0
http-array-w2-o1-read-r1-referencevalidated0
http-array-w2-o1-read-r2-referencevalidated0
http-array-w2-o1-read-r2-user_cachevalidated0
http-array-w2-o1-read-r3-user_cachevalidated0
http-array-w2-o1-read-r3-referencevalidated0
http-array-w2-o1-read-r4-referencevalidated0
http-array-w2-o1-read-r4-user_cachevalidated0
http-array-w2-o1-mixed-r0-referencevalidated0
http-array-w2-o1-mixed-r0-user_cachevalidated0
http-array-w2-o1-mixed-r1-user_cachevalidated0
http-array-w2-o1-mixed-r1-referencevalidated0
http-array-w2-o1-mixed-r2-referencevalidated0
http-array-w2-o1-mixed-r2-user_cachevalidated0
http-array-w2-o1-mixed-r3-user_cachevalidated0
http-array-w2-o1-mixed-r3-referencevalidated0
http-array-w2-o1-mixed-r4-referencevalidated0
http-array-w2-o1-mixed-r4-user_cachevalidated0
http-array-w2-o100-read-r0-referencevalidated0
http-array-w2-o100-read-r0-user_cachevalidated0
http-array-w2-o100-read-r1-user_cachevalidated0
http-array-w2-o100-read-r1-referencevalidated0
http-array-w2-o100-read-r2-referencevalidated0
http-array-w2-o100-read-r2-user_cachevalidated0
http-array-w2-o100-read-r3-user_cachevalidated0
http-array-w2-o100-read-r3-referencevalidated0
http-array-w2-o100-read-r4-referencevalidated0
http-array-w2-o100-read-r4-user_cachevalidated0
http-array-w2-o100-mixed-r0-referencevalidated0
http-array-w2-o100-mixed-r0-user_cachevalidated0
http-array-w2-o100-mixed-r1-user_cachevalidated0
http-array-w2-o100-mixed-r1-referencevalidated0
http-array-w2-o100-mixed-r2-referencevalidated0
http-array-w2-o100-mixed-r2-user_cachevalidated0
http-array-w2-o100-mixed-r3-user_cachevalidated0
http-array-w2-o100-mixed-r3-referencevalidated0
http-array-w2-o100-mixed-r4-referencevalidated0
http-array-w2-o100-mixed-r4-user_cachevalidated0
http-array-w4-o1-read-r0-referencevalidated0
http-array-w4-o1-read-r0-user_cachevalidated0
http-array-w4-o1-read-r1-user_cachevalidated0
http-array-w4-o1-read-r1-referencevalidated0
http-array-w4-o1-read-r2-referencevalidated0
http-array-w4-o1-read-r2-user_cachevalidated0
http-array-w4-o1-read-r3-user_cachevalidated0
http-array-w4-o1-read-r3-referencevalidated0
http-array-w4-o1-read-r4-referencevalidated0
http-array-w4-o1-read-r4-user_cachevalidated0
http-array-w4-o1-mixed-r0-referencevalidated0
http-array-w4-o1-mixed-r0-user_cachevalidated0
http-array-w4-o1-mixed-r1-user_cachevalidated0
http-array-w4-o1-mixed-r1-referencevalidated0
http-array-w4-o1-mixed-r2-referencevalidated0
http-array-w4-o1-mixed-r2-user_cachevalidated0
http-array-w4-o1-mixed-r3-user_cachevalidated0
http-array-w4-o1-mixed-r3-referencevalidated0
http-array-w4-o1-mixed-r4-referencevalidated0
http-array-w4-o1-mixed-r4-user_cachevalidated0
http-array-w4-o100-read-r0-user_cachevalidated0
http-array-w4-o100-read-r0-referencevalidated0
http-array-w4-o100-read-r1-referencevalidated0
http-array-w4-o100-read-r1-user_cachevalidated0
http-array-w4-o100-read-r2-user_cachevalidated0
http-array-w4-o100-read-r2-referencevalidated0
http-array-w4-o100-read-r3-referencevalidated0
http-array-w4-o100-read-r3-user_cachevalidated0
http-array-w4-o100-read-r4-user_cachevalidated0
http-array-w4-o100-read-r4-referencevalidated0
http-array-w4-o100-mixed-r0-user_cachevalidated0
http-array-w4-o100-mixed-r0-referencevalidated0
http-array-w4-o100-mixed-r1-referencevalidated0
http-array-w4-o100-mixed-r1-user_cachevalidated0
http-array-w4-o100-mixed-r2-user_cachevalidated0
http-array-w4-o100-mixed-r2-referencevalidated0
http-array-w4-o100-mixed-r3-referencevalidated0
http-array-w4-o100-mixed-r3-user_cachevalidated0
http-array-w4-o100-mixed-r4-user_cachevalidated0
http-array-w4-o100-mixed-r4-referencevalidated0
http-scalar-w1-o1-read-r0-referencevalidated0
http-scalar-w1-o1-read-r0-user_cachevalidated0
http-scalar-w1-o1-read-r1-user_cachevalidated0
http-scalar-w1-o1-read-r1-referencevalidated0
http-scalar-w1-o1-read-r2-referencevalidated0
http-scalar-w1-o1-read-r2-user_cachevalidated0
http-scalar-w1-o1-read-r3-user_cachevalidated0
http-scalar-w1-o1-read-r3-referencevalidated0
http-scalar-w1-o1-read-r4-referencevalidated0
http-scalar-w1-o1-read-r4-user_cachevalidated0
http-scalar-w1-o1-mixed-r0-referencevalidated0
http-scalar-w1-o1-mixed-r0-user_cachevalidated0
http-scalar-w1-o1-mixed-r1-user_cachevalidated0
http-scalar-w1-o1-mixed-r1-referencevalidated0
http-scalar-w1-o1-mixed-r2-referencevalidated0
http-scalar-w1-o1-mixed-r2-user_cachevalidated0
http-scalar-w1-o1-mixed-r3-user_cachevalidated0
http-scalar-w1-o1-mixed-r3-referencevalidated0
http-scalar-w1-o1-mixed-r4-referencevalidated0
http-scalar-w1-o1-mixed-r4-user_cachevalidated0
http-scalar-w1-o100-read-r0-referencevalidated0
http-scalar-w1-o100-read-r0-user_cachevalidated0
http-scalar-w1-o100-read-r1-user_cachevalidated0
http-scalar-w1-o100-read-r1-referencevalidated0
http-scalar-w1-o100-read-r2-referencevalidated0
http-scalar-w1-o100-read-r2-user_cachevalidated0
http-scalar-w1-o100-read-r3-user_cachevalidated0
http-scalar-w1-o100-read-r3-referencevalidated0
http-scalar-w1-o100-read-r4-referencevalidated0
http-scalar-w1-o100-read-r4-user_cachevalidated0
http-scalar-w1-o100-mixed-r0-referencevalidated0
http-scalar-w1-o100-mixed-r0-user_cachevalidated0
http-scalar-w1-o100-mixed-r1-user_cachevalidated0
http-scalar-w1-o100-mixed-r1-referencevalidated0
http-scalar-w1-o100-mixed-r2-referencevalidated0
http-scalar-w1-o100-mixed-r2-user_cachevalidated0
http-scalar-w1-o100-mixed-r3-user_cachevalidated0
http-scalar-w1-o100-mixed-r3-referencevalidated0
http-scalar-w1-o100-mixed-r4-referencevalidated0
http-scalar-w1-o100-mixed-r4-user_cachevalidated0
http-scalar-w2-o1-read-r0-referencevalidated0
http-scalar-w2-o1-read-r0-user_cachevalidated0
http-scalar-w2-o1-read-r1-user_cachevalidated0
http-scalar-w2-o1-read-r1-referencevalidated0
http-scalar-w2-o1-read-r2-referencevalidated0
http-scalar-w2-o1-read-r2-user_cachevalidated0
http-scalar-w2-o1-read-r3-user_cachevalidated0
http-scalar-w2-o1-read-r3-referencevalidated0
http-scalar-w2-o1-read-r4-referencevalidated0
http-scalar-w2-o1-read-r4-user_cachevalidated0
http-scalar-w2-o1-mixed-r0-referencevalidated0
http-scalar-w2-o1-mixed-r0-user_cachevalidated0
http-scalar-w2-o1-mixed-r1-user_cachevalidated0
http-scalar-w2-o1-mixed-r1-referencevalidated0
http-scalar-w2-o1-mixed-r2-referencevalidated0
http-scalar-w2-o1-mixed-r2-user_cachevalidated0
http-scalar-w2-o1-mixed-r3-user_cachevalidated0
http-scalar-w2-o1-mixed-r3-referencevalidated0
http-scalar-w2-o1-mixed-r4-referencevalidated0
http-scalar-w2-o1-mixed-r4-user_cachevalidated0
http-scalar-w2-o100-read-r0-referencevalidated0
http-scalar-w2-o100-read-r0-user_cachevalidated0
http-scalar-w2-o100-read-r1-user_cachevalidated0
http-scalar-w2-o100-read-r1-referencevalidated0
http-scalar-w2-o100-read-r2-referencevalidated0
http-scalar-w2-o100-read-r2-user_cachevalidated0
http-scalar-w2-o100-read-r3-user_cachevalidated0
http-scalar-w2-o100-read-r3-referencevalidated0
http-scalar-w2-o100-read-r4-referencevalidated0
http-scalar-w2-o100-read-r4-user_cachevalidated0
http-scalar-w2-o100-mixed-r0-referencevalidated0
http-scalar-w2-o100-mixed-r0-user_cachevalidated0
http-scalar-w2-o100-mixed-r1-user_cachevalidated0
http-scalar-w2-o100-mixed-r1-referencevalidated0
http-scalar-w2-o100-mixed-r2-referencevalidated0
http-scalar-w2-o100-mixed-r2-user_cachevalidated0
http-scalar-w2-o100-mixed-r3-user_cachevalidated0
http-scalar-w2-o100-mixed-r3-referencevalidated0
http-scalar-w2-o100-mixed-r4-referencevalidated0
http-scalar-w2-o100-mixed-r4-user_cachevalidated0
http-scalar-w4-o1-read-r0-user_cachevalidated0
http-scalar-w4-o1-read-r0-referencevalidated0
http-scalar-w4-o1-read-r1-referencevalidated0
http-scalar-w4-o1-read-r1-user_cachevalidated0
http-scalar-w4-o1-read-r2-user_cachevalidated0
http-scalar-w4-o1-read-r2-referencevalidated0
http-scalar-w4-o1-read-r3-referencevalidated0
http-scalar-w4-o1-read-r3-user_cachevalidated0
http-scalar-w4-o1-read-r4-user_cachevalidated0
http-scalar-w4-o1-read-r4-referencevalidated0
http-scalar-w4-o1-mixed-r0-referencevalidated0
http-scalar-w4-o1-mixed-r0-user_cachevalidated0
http-scalar-w4-o1-mixed-r1-user_cachevalidated0
http-scalar-w4-o1-mixed-r1-referencevalidated0
http-scalar-w4-o1-mixed-r2-referencevalidated0
http-scalar-w4-o1-mixed-r2-user_cachevalidated0
http-scalar-w4-o1-mixed-r3-user_cachevalidated0
http-scalar-w4-o1-mixed-r3-referencevalidated0
http-scalar-w4-o1-mixed-r4-referencevalidated0
http-scalar-w4-o1-mixed-r4-user_cachevalidated0
http-scalar-w4-o100-read-r0-referencevalidated0
http-scalar-w4-o100-read-r0-user_cachevalidated0
http-scalar-w4-o100-read-r1-user_cachevalidated0
http-scalar-w4-o100-read-r1-referencevalidated0
http-scalar-w4-o100-read-r2-referencevalidated0
http-scalar-w4-o100-read-r2-user_cachevalidated0
http-scalar-w4-o100-read-r3-user_cachevalidated0
http-scalar-w4-o100-read-r3-referencevalidated0
http-scalar-w4-o100-read-r4-referencevalidated0
http-scalar-w4-o100-read-r4-user_cachevalidated0
http-scalar-w4-o100-mixed-r0-user_cachevalidated0
http-scalar-w4-o100-mixed-r0-referencevalidated0
http-scalar-w4-o100-mixed-r1-referencevalidated0
http-scalar-w4-o100-mixed-r1-user_cachevalidated0
http-scalar-w4-o100-mixed-r2-user_cachevalidated0
http-scalar-w4-o100-mixed-r2-referencevalidated0
http-scalar-w4-o100-mixed-r3-referencevalidated0
http-scalar-w4-o100-mixed-r3-user_cachevalidated0
http-scalar-w4-o100-mixed-r4-user_cachevalidated0
http-scalar-w4-o100-mixed-r4-referencevalidated0

Notes

Measurement contract

Micro/A/A execution mode: worker. Worker mode retains the PHP execution between HTTP requests; classic mode starts a fresh PHP request for each micro/A/A HTTP sample. Each sample performs its seed and warmup in that same PHP execution. HTTP scaling always uses persistent workers, independently of this option.

Worker-mode samples must have zero outstanding graph pins. Classic samples record a nonnegative pin count during the PHP request, when borrowed shared values may legitimately remain pinned; this observation does not verify their release after request shutdown.

Workloads

Dynamic payloads are created at runtime, with OPcache and JIT disabled. Seed/persist, setup and warmup are outside the timed fetch batch. Both cache wrappers include lookup, generation/TTL invalidation and warm PHP-heap COW caching; the raw helper reads an already persisted source and excludes cache lookup. Cold means the first fetch after store, including any store-time string COW seeding; there is no cold one-key row. The retained integer mutate-flag case does not mutate integers.

Common cases cover null, boolean, integer, double, strings and nested arrays; object hooks, references, aliases/cycles and UserCache-specific native object support are outside this reference comparison. Mutation checks verify the cached source remains unchanged. Fetched values are released each iteration: these memory figures do not measure retaining an unbounded list of returned values. Stores in the mixed HTTP workload are reported together with reads; this is not an isolated store benchmark.

Pairing and statistics

Independent hosts run sequentially. Micro samples use randomized paired backend order; HTTP pairs alternate order within each case. A/A runs use the same reference wrapper twice to expose local noise. Every case stays visible, including cases within the interval and cases the reference wins. Raw scalar/immutable-pointer helpers can be lower bounds that a full cache cannot beat. The supplied fixtures are dynamic; OPcache-immutable fixtures are not mixed into these results.

Timing tables use per-backend medians. Ratios are medians of matched pairs, not ratios of pooled means; intervals are a paired bootstrap 95% interval for the median when at least two pairs exist. Intervals from very few pairs are exploratory. Lower latency/CPU is better; higher HTTP throughput is better.

HTTP scope

Request and operation rates are separate; all individual response samples and status/pin checks are retained.

The loopback HTTP client and server run in the same Go process and share its CPU affinity. HTTP throughput includes client, server and networking overhead; it is not an isolated remote-client server-capacity result. Thread CPU measurements cover the PHP thread only, not total Go host/client CPU. With more workers, the client and the workers compete for the same CPUs and intervals widen.