Host
Intel Core Ultra 9 285K · 24 cores
Platform
linux/amd64
Go
go1.26.0
CPython
python:3.13-slim
PyPy
pypy:3.10-slim
Runs / combo
10 + 2 warmup

Polymorphic AST eval

Interface / virtual-method dispatch through nine AST node types under heavy traversal load.

Runtime · median per inner-loop window

median of 10 runs

Native Gocompiled
2.11 ms0.04×
Piko interpbytecode VM
54.9 msbaseline
CPython 3.13bytecode VM
55.7 ms1.01×
PyPy 7.3tracing JIT
80.1 ms1.46×
Ttengobytecode VM
120 ms2.18×
Sscriggobytecode VM
n/a
Mmvmbytecode VM
246 ms4.49×
YyaegiAST walker
1.40 s25.5×

Full statistics

RunnerNCompileRuntimeP95StddevRSSvs pikoStatus
Native Gocompiled10181 ms2.11 ms2.13 ms12.0 µs69 MiB0.04×OK
Piko interpbytecode VM102.03 ms54.9 ms55.4 ms309 µs131 MiB1.00×OK
CPython 3.13bytecode VM10620 µs55.7 ms57.5 ms1.25 msn/a1.01×OK
PyPy 7.3tracing JIT10482 µs80.1 ms83.5 ms1.19 msn/a1.46×OK
tengobytecode VM10373 µs120 ms123 ms1.19 ms200 MiB2.18×OK
scriggobytecode VM0n/an/an/an/an/an/aunsupported
mvmbytecode VM10687 µs246 ms275 ms20.0 ms67 MiB4.49×OK
yaegiAST walker10702 µs1.40 s1.53 s49.4 ms71 MiB25.5×OK
Workload & symmetry rules

Workload

Build an expression tree from a deterministic LCG that mixes nine node kinds (Add, Sub, Mul, Mod, Const, Var, IfPos, Min, Max), each as a distinct struct/class satisfying a single-method contract: Node.Eval(env) uint32. Walk the tree repeatedly and accumulate the fold.

Symmetry rules

  • Real interface dispatch in Go (Eval(env) method on a Node interface) and class-based duck typing in Python.
  • No tagged-union switch shortcut; every Eval call must go through dynamic dispatch.

Why this benchmark exists

A direct measurement of the interpreter's interface / virtual-method dispatch path. Bench 05 is similar but uses a tagged-int switch; this one forces real virtual dispatch.

Source code