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

Parallel word count (Monte Cristo)

Parallel word-frequency count over ~2.7 MB of Project Gutenberg text. Each runner uses its idiomatic CPU-parallel primitive.

Runtime · median per inner-loop window

median of 7 runs

Native Gocompiled
22.9 ms0.25×
Pipitbytecode VM
90.4 msbaseline
CPython 3.14bytecode VM
190 ms2.10×
PyPy 7.3tracing JIT
298 ms3.30×
Ttengobytecode VM
n/a
Sscriggobytecode VM
n/a
Mmvmbytecode VM
256 ms2.83×
YyaegiAST walker
n/a

Full statistics

RunnerNCompileRuntimeP95StddevRSSvs pipitStatus
Native Gocompiled7113 ms22.9 ms24.2 ms800 µs1.62 GiB0.25×OK
Pipitbytecode VM73.29 ms90.4 ms93.7 ms1.50 ms592 MiB1.00×OK
CPython 3.14bytecode VM7843 µs190 ms193 ms1.45 msn/a2.10×OK
PyPy 7.3tracing JIT7602 µs298 ms299 ms1.78 msn/a3.30×OK
tengobytecode VM0n/an/an/an/an/an/ano data
scriggobytecode VM0n/an/an/an/an/an/aunsupported
mvmbytecode VM7800 µs256 ms266 ms9.14 ms1.69 GiB2.83×OK
yaegiAST walker0n/an/an/an/an/an/ano data
Workload & symmetry rules

Workload

  1. Load The Count of Monte Cristo (Project Gutenberg #1184) corpus from disk.
  2. Split into 16 word-aligned chunks.
  3. Spawn 16 workers (goroutine + WaitGroup on Go/pipit; multiprocessing.Pool on Python).
  4. Each worker tokenises via byte-walk and builds a local word → count map.
  5. Merge maps, compute top-50 by (count desc, word asc) via hand-rolled insertion-sort.

Symmetry rules

  • Each runner uses its idiomatic CPU-parallel primitive. Python's multiprocessing.Pool (not threading, because of the GIL).
  • No str.split, no regexp, no sort.*/sorted(key=...): tokenisation and ranking are hand-rolled.

Why this benchmark exists

Directly measures the GIL-free advantage. Pipit inherits Go's goroutine scheduler; CPython has to fork.

Source code