Performance¶
This page shows recorded timings. None of the numbers are typed by hand:
when the site is built, the six judge problems are read from
examples/15_algorithms/measurements.json and the collatz table from the README.
scripts/refresh.py re-measures and reports what has drifted past a tolerance,
and --write records it.
Collatz kernel compared with other compilers¶
This is the collatz kernel from the README. It was run on one machine, ten runs each in a fresh process, and the table shows the kernel's wall time (mean ± standard deviation).
Of the PPy rows, ppy build --unsafe is the wrap-semantics artifact. ppy run
keeps Python-integer semantics: overflow is guarded and falls back to arbitrary
precision.
| compiler | kernel | integer semantics |
|---|---|---|
PPy ppy build --unsafe --host-cpu |
28.8 ± 0.5 ms | 64-bit, wraps on overflow (this machine's instruction set) |
C (clang -O3 -march=native) |
30.8 ± 0.7 ms | 64-bit, wraps on overflow |
PPy ppy build --unsafe |
30.8 ± 0.4 ms | 64-bit, wraps on overflow |
Numba @njit |
32.5 ± 0.9 ms | 64-bit, wraps on overflow |
C (clang -O3) |
32.8 ± 0.5 ms | 64-bit, wraps on overflow |
PPy ppy run |
41.7 ± 1.8 ms | Python ints: guarded, falls back to arbitrary precision |
C (gcc -O3) |
41.9 ± 0.9 ms | 64-bit, wraps on overflow |
Codon -release |
42.1 ± 12.1 ms | 64-bit, wraps on overflow |
| PyPy 3.11 | 52.8 ± 0.5 ms | Python ints |
Cython (cdef long long) |
61.6 ± 0.8 ms | 64-bit, wraps on overflow |
| mypyc | 71.6 ± 1.4 ms | Python ints |
| Nuitka | 714.7 ± 12.8 ms | Python ints, no type specialization |
| CPython 3.14 | 1068.8 ± 5.5 ms | Python ints |
Six judge problems, whole process¶
These are wall times of the whole process, including input reading and interpreter startup. Nothing inside the programs is instrumented. Each problem reads its input from standard input.
| problem | CPython | ppy run |
ppy build --unsafe |
--standalone |
C (gcc -O3) |
C (clang -O3) |
|---|---|---|---|---|---|---|
N-Queens 15a_nqueens |
142.0 ± 12.5 ms | 123.6 ± 144.1 ms | 48.7 ± 14.9 ms | 5.7 ± 0.2 ms | 4.8 ± 0.1 ms | 5.4 ± 0.1 ms |
Shortest paths 15b_dijkstra |
4858.5 ± 72.8 ms | 3659.1 ± 238.0 ms | 4426.9 ± 53.7 ms | 111.7 ± 1.2 ms | 142.2 ± 2.5 ms | 134.3 ± 2.4 ms |
Substring search 15c_kmp |
292.4 ± 12.8 ms | 145.5 ± 160.1 ms | 53.3 ± 1.3 ms | — | 9.3 ± 0.1 ms | 9.0 ± 0.4 ms |
Range sums 15d_segment_tree |
1571.7 ± 26.0 ms | 1288.3 ± 157.9 ms | 1524.4 ± 24.2 ms | 30.1 ± 0.8 ms | 50.8 ± 0.7 ms | 50.9 ± 0.9 ms |
Longest increasing subsequence 15e_lis |
541.6 ± 14.0 ms | 198.6 ± 152.9 ms | 111.5 ± 1.6 ms | 41.5 ± 0.6 ms | 57.7 ± 0.4 ms | 53.9 ± 0.4 ms |
Counting inversions 15f_input |
603.7 ± 11.2 ms | 189.3 ± 166.5 ms | 98.4 ± 3.1 ms | 38.6 ± 0.5 ms | 43.5 ± 0.8 ms | 44.2 ± 0.4 ms |
Recorded on Intel(R) Core(TM) Ultra 9 386H, 16 cores, CPython 3.14.5, Linux-6.6.114.1-microsoft-standard-WSL2-x86_64-with-glibc2.39, at 2026-09-14T04:47:22.
The ppy run column includes the first run's build into the cache. That is
why its deviation is wide. From the second run on, it is the launcher alone.
--standalone is a native executable with no interpreter inside.