Host
Intel Core Ultra 9 285K · 24 cores
Platform
linux/amd64
Go
go1.27.0
CPython
python:3.14-slim
PyPy
pypy:3.11-slim
Runs / combo
7 + 2 warmup

Invert binary tree

65k-node balanced binary tree: allocator pressure, recursive descent, and pointer mutation in one inner loop. The only workload in the suite that stresses all three at once.

Compile time · median (cold)

median of 7 runs

Native Gocompiled
108 ms92.1×
Pipitbytecode VM
1.17 msbaseline
CPython 3.14bytecode VM
354 µs0.30×
PyPy 7.3tracing JIT
285 µs0.24×
Ttengobytecode VM
230 µs0.20×
Sscriggobytecode VM
n/a
Mmvmbytecode VM
358 µs0.31×
YyaegiAST walker
359 µs0.31×

Full statistics

RunnerNCompileRuntimeP95StddevRSSvs pipitStatus
Native Gocompiled7108 ms5.96 ms6.03 ms299 µs1.62 GiB92.1×OK
Pipitbytecode VM71.17 ms61.2 ms78.7 ms6.05 ms592 MiB1.00×OK
CPython 3.14bytecode VM7354 µs80.4 ms81.9 ms977 µsn/a0.30×OK
PyPy 7.3tracing JIT7285 µs42.9 ms45.3 ms1.82 msn/a0.24×OK
tengobytecode VM7230 µs180 ms205 ms14.6 ms1.69 GiB0.20×OK
scriggobytecode VM0n/an/an/an/an/an/ano data
mvmbytecode VM7358 µs165 ms167 ms2.06 ms1.69 GiB0.31×OK
yaegiAST walker7359 µs574 ms606 ms14.0 ms1.69 GiB0.31×OK
Workload & symmetry rules

Workload

  1. Recursively construct a balanced binary tree of depth 15 (2¹⁶ − 1 = 65535 nodes). Each node's value is derived deterministically from its parent (value*2 for left, value*2+1 for right, 32-bit masked).
  2. Count nodes via recursive traversal (sanity check).
  3. Compute an in-order hash fold: state = state*31 + value mod 2³².
  4. Invert the tree: at every node, swap left and right pointers recursively.
  5. Re-count and re-hash. Emit the four observables pre_count,pre_fold,post_count,post_fold.

Symmetry rules

  • Real recursive *Node struct (Go) / Node class with __slots__ (Python).
  • No conversion to arrays for the inversion step, just a pointer swap at every node.

What makes this workload unique

Every other benchmark in the suite isolates one performance dimension. Bench 14 stresses pure float arithmetic in a tight loop. Bench 15 stresses interpreter throughput with no allocation. Bench 13 stresses interface dispatch with no mutation. This one combines three pressures into a single inner loop: 65k heap allocations during construction, four full recursive walks across the tree, and in-place pointer-field mutation during the inversion. The runner that wins this benchmark is the runner whose allocator, call-frame management, and pointer-write path are all simultaneously fast. The runner that loses it has a bottleneck in at least one of the three.

Source code