For years, PyPy has been the go-to choice for developers chasing raw Python speed. But that long-standing advantage is now under pressure. With CPython introducing a native JIT compiler and experimental no-GIL builds, Python’s default runtime is finally fighting back and the results are more surprising than expected.
We ran real-world benchmarks comparing PyPy with the latest JIT-enabled and free-threaded versions of CPython. What we found shows that Python performance is no longer a one-size-fits-all story.
Why PyPy Has Traditionally Been Faster Than CPython
PyPy was designed around a powerful Just-In-Time compiler built specifically for Python. This allows it to aggressively optimize loops, reduce overhead, and execute math-heavy workloads at impressive speeds.
In contrast, CPython has historically struggled with numerical workloads due to its high-level abstractions. Even simple arithmetic operations carry significant overhead, which is why PyPy often delivers massive speedups without any code changes.
Can CPython’s New JIT Close the Performance Gap?
Recent CPython releases introduced the first versions of a native JIT compiler. While still early, it already delivers measurable improvements in some workloads — especially in Python 3.15 previews.
For single-threaded, CPU-heavy tasks, the JIT alone offers modest gains. However, the real shift happens when CPython’s no-GIL build enters the picture.
How Free Threading Changes Everything for CPython
Removing the Global Interpreter Lock allows CPython to finally execute threads in true parallel fashion. When multi-threaded workloads are used, performance improves dramatically.
In benchmarks that distribute work across threads, no-GIL CPython reduces execution time by several multiples compared to traditional builds. While it still doesn’t always beat PyPy’s single-threaded speed, the gap is narrowing fast and in some cases, CPython pulls ahead.
Why PyPy Struggles With Threading and Multiprocessing
Ironically, PyPy’s biggest strength becomes a limitation in parallel workloads. PyPy still relies on a GIL-like mechanism, preventing true thread-level parallelism.
When multi-threading is introduced, PyPy often slows down instead of speeding up. Multiprocessing helps slightly, but PyPy’s inter-process communication is far less efficient than CPython’s, limiting its scalability.
What Happens in Pure Math-Heavy Workloads?
In classic math-focused benchmarks such as physics simulations and numerical loops PyPy still dominates. Tasks that are difficult or impossible to parallelize consistently run much faster on PyPy than on CPython, even with the JIT enabled.
This makes PyPy an excellent choice for tightly looped, single-threaded numerical code where raw execution speed matters most.
Why CPython Wins in I/O and Real-World Workloads
Not all programs are math-bound. In I/O-heavy scenarios like processing large files, parsing data, or aggregating results, CPython’s no-GIL multithreaded builds shine.
In these tests, CPython not only beats its own traditional builds but also outperforms PyPy sometimes by a wide margin. This highlights a key shift: CPython is becoming the better all-around runtime for modern, parallel workloads.
Is PyPy Still the Faster Python Runtime?
It depends and that’s the real answer.
PyPy remains incredibly fast for certain workloads, especially:
-
Single-threaded math-heavy tasks
-
Long-running loops with predictable execution patterns
But CPython now excels when:
-
True parallelism is possible
-
Threading or multiprocessing matters
-
Compatibility with the Python ecosystem is critical
Which Python Runtime Should You Choose?
There’s no universal winner anymore. PyPy’s performance gains are real but inconsistent across workloads. CPython, meanwhile, is rapidly improving and gaining advantages PyPy can’t yet match — especially with free threading.
The safest approach is simple: benchmark your application. Python performance today depends heavily on how your code behaves, not just which runtime you choose.
Final Thoughts: The Python Performance Landscape Is Shifting
PyPy is still blazing fast but CPython is no longer standing still. With JIT compilation and no-GIL threading evolving quickly, CPython is becoming competitive in areas where it once lagged far behind.
For developers, this is good news. Faster Python, more choices, and better performance across real-world workloads mean the future of Python looks stronger than ever.

