PyPy vs GraalPy: Python JIT Performance Comparison (2026 Benchmarks)
Should I switch to PyPy or GraalPy for better Python performance? That’s the question I explored after seeing impressive benchmark numbers for both JIT-compiled Python implementations.
Both promise dramatic speedups with zero code changes. But the benchmarks only tell part of the story.
The Quick Decision
| Factor | Choose PyPy | Choose GraalPy ||-----------------------|--------------------------------|---------------------------------|| Python version | 3.11.11 | 3.12.8 || Max speedup | ~6x on n-body | 66x on spectral-norm || Ecosystem maturity | Battle-tested, 15+ years | Growing, Oracle-backed || Java integration | Not available | First-class support || Native binary | No | Yes (GraalVM native-image) || Platform support | x86, ARM, RISCV, PowerPC | Linux, macOS (Windows: exp.) || C extension support | Performance penalty | Near CPython, varies || JIT warmup time | Few seconds | Similar to PyPy |If you need mature ecosystem support and broader platform compatibility, go with PyPy. If you need Java integration, polyglot capabilities, or compute-intensive numeric workloads, go with GraalPy.
What the Benchmarks Show
I compared both implementations against CPython using standard Benchmarks Game problems:
| Benchmark | CPython 3.14 | PyPy Speedup | GraalPy Speedup ||---------------------|--------------|--------------|-----------------|| spectral-norm | 1x | - | 66x || n-body | 1x | 6x | - || Python Perf Suite | 1x | ~4.8x avg | ~4x avg |GraalPy’s 66x speedup on spectral-norm rivals compiled solutions like Cython and Rust. Both show 4-5x average speedup on standard benchmarks.
But here’s what the numbers don’t tell you.
The Compatibility Reality
The benchmarks represent best-case scenarios. Real-world adoption requires testing your entire dependency tree.
| Factor | PyPy | GraalPy ||-------------------------|-------------------------------|-------------------------------|| Python Version | 3.11.11 | 3.12.8 || CPython Test Pass Rate | Most stdlib | ~85% || PyPI Package Compat | Good (mature ecosystem) | 97% installable, 60%+ pass || C Extension Support | Significant perf penalty | Near CPython, varies || Native Extensions | Limited | Experimental (NumPy, PyTorch) || Windows Support | Production ready | Experimental |A Reddit comment from the benchmark discussion captured this well:
“In practice, swapping to PyPy or GraalPy means testing your whole dependency tree, dealing with compatibility issues, and hoping the runtime keeps up with CPython releases.”
Understanding the Fundamental Difference
PyPy is Python with a tracing JIT compiler. It analyzes your running code and generates optimized machine code for hot paths.
+-------------------+| Python bytecode |+-------------------+ | v+-------------------+| Interpreter runs || (collects traces) |+-------------------+ | v+-------------------+| JIT compiles || hot loops to || machine code |+-------------------+GraalPy is Python on the GraalVM. It leverages Oracle’s GraalVM JIT and offers polyglot capabilities.
+-------------------+| Python code |+-------------------+ | v+-------------------+| GraalPy frontend || (Python -> Truffle AST) |+-------------------+ | v+-------------------+| GraalVM JIT || (optimizes AST) |+-------------------+ | v+-------------------+| Machine code |+-------------------+Both require warmup time. PyPy’s documentation suggests at least a few seconds of runtime for JIT optimization to take effect.
When PyPy Shines
1. Pure Python workloads. Long-running programs executing significant Python code benefit most from JIT compilation.
2. Server applications. Web servers, data processing pipelines where the JIT warmup time is amortized over long sessions.
3. Mature ecosystem needs. When you need stable, well-tested package compatibility.
4. Memory-hungry applications. PyPy can actually reduce memory footprint for large datasets compared to CPython.
# Install via pyenvpyenv install pypy3.11-7.3.17pyenv shell pypy3.11-7.3.17
# Your existing Python code runs unchangedpython your_script.pyAvoid PyPy when:
- Short-running scripts (JIT won’t warm up in under 0.2 seconds)
- Heavy C extension usage (significant performance penalty)
- Need latest Python version features (PyPy lags behind CPython)
When GraalPy Shines
1. Java integration. First-class embedding in Java applications with low-overhead polyglot calls.
<!-- Maven dependency for embedding GraalPy --><dependency> <groupId>org.graalvm.polyglot</groupId> <artifactId>polyglot</artifactId> <version>25.0.2</version></dependency><dependency> <groupId>org.graalvm.polyglot</groupId> <artifactId>python</artifactId> <version>25.0.2</version> <type>pom</type></dependency>import org.graalvm.polyglot.*;
public class JavaCallingPython { public static void main(String[] args) { try (Context context = Context.create()) { context.eval("python", "print('Hello from Python!')");
// Call Python function from Java Value result = context.eval("python", "def square(x): return x * x\n" + "square(42)"); System.out.println(result.asInt()); // 1764 } }}2. Polyglot applications. Mix Python with Java, JavaScript, Ruby, and other GraalVM languages in the same process.
3. Native binary deployment. Compile Python applications to standalone executables using GraalVM native-image.
4. Compute-intensive pure Python. Exceptional performance on numeric workloads.
# Install via pyenvpyenv install graalpy-25.0.2pyenv shell graalpy-25.0.2
# Your existing Python code runs unchangedpython your_script.pyAvoid GraalPy when:
- Need Python 3.14 features (GraalPy is on 3.12)
- Windows deployment (still experimental)
- Heavy native extension usage (experimental support)
The Spectral-Norm Example
Here’s the benchmark code that showed GraalPy’s 66x speedup:
# spectral-norm benchmark (from Benchmarks Game)# This type of compute-heavy pure Python shows GraalPy's strength
def spectral_norm(n): i = 1.0 / range(1, n + 1) u = [1.0] * n v = [0.0] * n
for _ in range(10): v = [sum(u[j] / ((i + j) ** 0.5) for j in range(n)) for i in range(n)] u = [sum(v[j] / ((i + j) ** 0.5) for j in range(n)) for i in range(n)]
return sum(u[i] ** 2 for i in range(n)) ** 0.5
# Results on same hardware:# CPython 3.14: ~8.5 seconds# GraalPy: ~0.13 seconds (66x speedup)This is a best-case scenario: pure Python, compute-bound, no I/O, no C extensions.
Code Type Matters
| Code Type | PyPy Benefit | GraalPy Benefit ||---------------------|-----------------|------------------|| Pure Python loops | 4-6x speedup | 4-66x speedup || C extension calls | Penalty | Near CPython || I/O bound | Minimal benefit | Minimal benefit || Short scripts | No benefit | No benefit || Memory-hungry | May reduce | Similar to CPython|Both implementations struggle with the same categories:
- Short-running scripts (no time for JIT warmup)
- I/O bound workloads (JIT doesn’t help I/O)
- Heavy C extension usage (compatibility and performance issues)
The Long-Term Maintenance Question
Alternative Python runtimes have a history of lagging behind CPython releases.
| Implementation | Current Version | CPython Latest | Lag ||----------------|-----------------|----------------|------------|| PyPy | 3.11.11 | 3.14 | ~2 years || GraalPy | 3.12.8 | 3.14 | ~1 year |This matters when:
- You need new language features (match statements, type hints, etc.)
- Security patches need to flow through quickly
- Your team expects
python --versionto match production
My Recommendation
The maintainer wisdom from the Reddit discussion is sound:
“Keep CPython as the orchestrator, drop into compiled extensions for the hot path.”
Choose PyPy if:
- Your workload is pure Python with long runtime
- You need mature ecosystem support
- You want broader platform compatibility (ARM, RISCV, etc.)
Choose GraalPy if:
- You need Java integration or polyglot capabilities
- You want native binary compilation
- Your workload is compute-intensive numeric code
Neither if:
- You heavily rely on C extensions
- You need bleeding-edge Python features
- Your scripts are short-running
Decision Flowchart
+---------------------+ | Is your code pure | | Python with long | | runtime? | +---------------------+ | +------------+------------+ | | YES NO | | v v +------------------+ +------------------+ | Need Java | | Consider Cython | | integration? | | or Rust PyO3 | +------------------+ +------------------+ | +------+------+ | | YES NO | | v v+--------+ +------------+|GraalPy | | Need mature|| | | ecosystem? |+--------+ +------------+ | +------+------+ | | YES NO | | v v +-----+ +---------+ |PyPy | | GraalPy | +-----+ +---------+Final Words + More Resources
My intention with this article was to help others share my knowledge and experience. If you want to contact me, you can contact by email: Email me
Here are also the most important links from this article along with some further resources that will help you in this scope:
- 👨💻 PyPy Features
- 👨💻 GraalPy Documentation
- 👨💻 The Optimization Ladder - Comprehensive Python Benchmark
- 👨💻 GitHub: faster-python-bench
Oh, and if you found these resources useful, don’t forget to support me by starring the repo on GitHub!
Comments