Goblin Core Microbenchmarks
Generated: 2026-07-02 01:05:30 UTC.
These measurements isolate in-process read-path costs. They do not include sockets, polling, Redis comparison, or process RSS accounting.
Source data:
off:benchmark-results/microbench-1m-rank-cache-off-v2.jsonexact:benchmark-results/microbench-1m-rank-cache-exact-v2.jsonblock-hint:benchmark-results/microbench-1m-rank-cache-block-hint-v2.json
Configuration
| Setting | off |
exact |
block-hint |
|---|---|---|---|
members |
1000000 |
1000000 |
1000000 |
ops |
1000000 |
1000000 |
1000000 |
range_size |
16 |
16 |
16 |
warmups |
1 |
1 |
1 |
seed |
12345 |
12345 |
12345 |
score_shape |
integer |
integer |
integer |
rank_cache_mode |
off |
exact |
block-hint |
score_string_cache |
false |
false |
false |
Rank Cache off
| Metric | Raw ZSet ns/op | RESP ns/op | Command into ns/op | Command string ns/op | Parse into ns/op |
|---|---|---|---|---|---|
ZSCORE |
75.60 | 29.16 | 155.23 | 155.34 | 191.88 |
ZRANK |
376.51 | 25.32 | 435.44 | 434.07 | 432.97 |
ZREVRANK |
372.07 | 25.32 | 439.19 | 429.88 | 431.71 |
ZRANGE |
242.44 | 275.77 | 468.14 | 500.83 | 482.04 |
ZRANGE WITHSCORES |
242.44 | 546.62 | 918.88 | 941.54 | 920.92 |
Rank Cache exact
| Metric | Raw ZSet ns/op | RESP ns/op | Command into ns/op | Command string ns/op | Parse into ns/op |
|---|---|---|---|---|---|
ZSCORE |
75.39 | 29.37 | 159.57 | 158.10 | 196.74 |
ZRANK |
200.08 | 24.14 | 274.23 | 268.63 | 271.48 |
ZREVRANK |
205.53 | 24.14 | 275.93 | 267.30 | 277.07 |
ZRANGE |
244.69 | 273.06 | 486.58 | 495.86 | 500.84 |
ZRANGE WITHSCORES |
244.69 | 572.88 | 935.96 | 953.69 | 939.20 |
Rank Cache block-hint
| Metric | Raw ZSet ns/op | RESP ns/op | Command into ns/op | Command string ns/op | Parse into ns/op |
|---|---|---|---|---|---|
ZSCORE |
103.44 | 34.95 | 177.94 | 184.77 | 238.92 |
ZRANK |
338.34 | 24.67 | 385.36 | 470.87 | 451.27 |
ZREVRANK |
465.05 | 24.67 | 404.34 | 455.06 | 490.36 |
ZRANGE |
287.70 | 410.07 | 541.31 | 714.15 | 624.93 |
ZRANGE WITHSCORES |
287.70 | 684.42 | 1,189.78 | 1,462.15 | 1,402.94 |
Rank Cache Effect
| Metric | off ns/op | exact ns/op | block-hint ns/op | exact vs off | block-hint vs off |
|---|---|---|---|---|---|
Raw ZSCORE |
75.60 | 75.39 | 103.44 | -0.3% | 36.8% |
Raw ZRANK |
376.51 | 200.08 | 338.34 | -46.9% | -10.1% |
Raw ZREVRANK |
372.07 | 205.53 | 465.05 | -44.8% | 25.0% |
Raw ZRANGE iter |
242.44 | 244.69 | 287.70 | 0.9% | 18.7% |
Command-into ZSCORE |
155.23 | 159.57 | 177.94 | 2.8% | 14.6% |
Command-into ZRANK |
435.44 | 274.23 | 385.36 | -37.0% | -11.5% |
Command-into ZREVRANK |
439.19 | 275.93 | 404.34 | -37.2% | -7.9% |
Command-into ZRANGE |
468.14 | 486.58 | 541.31 | 3.9% | 15.6% |
ZRANGE Serialization Breakdown
| Component | off ns/op | exact ns/op | block-hint ns/op |
|---|---|---|---|
Score-index traversal |
49.48 | 49.07 | 48.57 |
Member lookup |
134.46 | 137.62 | 145.54 |
Score formatting only |
71.24 | 68.84 | 67.01 |
Member RESP append only |
429.65 | 436.63 | 520.21 |
Score RESP append preformatted |
297.64 | 298.65 | 341.42 |
Score RESP append formatting |
181.14 | 181.76 | 177.52 |
Direct RESP append WITHSCORES |
737.93 | 767.69 | 878.89 |
RESP append |
247.54 | 245.71 | 252.58 |
RESP append WITHSCORES |
501.92 | 532.76 | 546.46 |
Full command into |
466.92 | 478.95 | 546.05 |
Full command into WITHSCORES |
917.07 | 930.34 | 1,351.33 |
Write Path (write_path, rank cache off)
Generated on the local macOS arm64 development machine (--members 100000, --ops 100000, integer scores, 2026-07-07). Steady-state remove metrics (store_zrem, raw_zset_remove, execute_command_into_zrem*) zrem one member and immediately zadd-restore it each op. New-member metrics reset an empty store/zset per timed run.
| Metric | ns/op | Notes |
|---|---|---|
store_zadd_update |
33.76 | Preloaded store, score change on existing member |
store_zadd_new |
269.19 | Fresh store per run |
store_zrem |
355.34 | Remove + zadd restore, inline key |
raw_zset_add_update |
24.24 | Isolated ZSet, score change |
raw_zset_add_new |
267.38 | Fresh ZSet per run |
raw_zset_remove |
339.57 | Remove + add restore |
execute_command_into_zadd_update |
69.85 | Command dispatch + integer reply |
execute_command_into_zadd_new |
309.37 | Fresh store per run |
execute_command_into_zrem |
497.56 | Remove + zadd restore |
Read path (--members 100000, range 16, rank cache off):
| Metric | ns/op |
|---|---|
resp_append_withscores |
276.20 |
execute_command_into_withscores |
271.22 |
List all write-path metrics:
./build-release/goblin_core_microbench --list-benchmarks | rg '^write_path'
Read-Path Notes
ZRANGEresponse construction is the visible in-process cost: RESP-only serialization is 275.77 ns/op versus 242.44 ns/op for raw range iteration.ZRANGEbreakdown separates score-index traversal, member lookup, and RESP append costs: 49.48 ns/op traversal, 134.46 ns/op member lookup, and 247.54 ns/op RESP append.WITHSCORESadds double formatting work in the RESP append path: 501.92 ns/op versus 247.54 ns/op without scores.- Score formatting and score bulk append are now separated: 71.24 ns/op for formatting only and 181.14 ns/op for score bulk append with formatting.
ZRANGEcommand-into versus string-wrapper cost should be read as a server-path check, not a guaranteed microbench win: command-into is 468.14 ns/op versus 500.83 ns/op for the string wrapper.ZSCOREcommand overhead over raw lookup is about 79.63 ns/op.ZRANKremains mostly data-structure work in-process: raw rank is 376.51 ns/op versus 435.44 ns/op for command execution.