Python 3.15’s JIT Compiler: How Much Faster Is It Really?

What actually changed in Python 3.15’s experimental JIT, the real speedup numbers, and whether it’s worth enabling yet

The Python 3.15 overview mentions the JIT speedup in passing. This is the longer version: what actually changed under the hood, and whether “experimental” still means “not for you.”

A quick recap: what the JIT does

Python’s JIT, introduced experimentally in 3.13, compiles frequently-executed bytecode into machine code at runtime instead of interpreting it every time — the same general idea as JIT compilers in JavaScript engines or the JVM, adapted to CPython’s specific execution model. It’s opt-in, built via a separate compile flag, and off by default.

What’s new in 3.15’s JIT specifically

3.15 adds a new tracing frontend and basic register allocation to the JIT pipeline. In plain terms: the tracing frontend now records the paths code actually takes at runtime instead of estimating them, which lets the JIT understand far more bytecode and control flow than in 3.14 (simple object creation is now supported; generators and overloaded operations partially), and register allocation — deciding which values live in CPU registers versus memory — is one of the most impactful optimizations any compiler can make, because register access is dramatically faster than memory access. Earlier JIT versions did less of this work, leaving performance on the table even for code that did get compiled.

The actual numbers

The official What’s New reports a 7-8% geometric-mean speedup over the standard interpreter on x86-64 Linux, and 11-12% on AArch64 macOS over the tail-calling interpreter — a tougher baseline than the plain interpreter — measured across the pyperformance benchmark suite. Per-benchmark results are much wider, from roughly a 15% slowdown to over 100% faster than a no-JIT build. Geometric mean matters here — it’s not “your specific script gets 8% faster,” it’s the aggregate across a benchmark suite with wildly different workload shapes. Tight numerical loops and hot function calls benefit more; I/O-bound code (the majority of real-world web apps and scripts) sees close to nothing, because the bottleneck was never CPU-bound interpretation in the first place.

Should you enable it

For most applications, no — not yet, and not because it’s unstable so much as because it doesn’t help. If your workload is I/O-bound (most web backends, most scripts that spend their time waiting on a network or database), the JIT has nothing to compile that matters. It’s worth testing specifically if you have CPU-bound Python code — numerical processing, tight loops, algorithmic work that isn’t already handled by NumPy or a compiled extension — where interpreter overhead is a measurable part of your runtime.

How to test it

Building CPython with --enable-experimental-jit (or using a pre-built distribution that ships it enabled) lets you compare against a standard build directly on your own workload (LLVM 21 is only needed at build time; anyone running a JIT-enabled Python doesn’t need it installed) — the pyperformance numbers above are a general signal, not a guarantee for your specific code. If you do test it, benchmark your actual bottleneck, not a synthetic loop; the JIT’s gains are real but workload-dependent enough that generic numbers won’t tell you what you’ll actually see.

Real Python’s JIT compiler preview goes deeper into the implementation details if you want the full technical picture beyond this summary.

Frequently Asked Questions

How much faster is Python 3.15’s JIT?

The official What’s New reports a 7-8% geometric-mean speedup over the standard interpreter on x86-64 Linux, and 11-12% on AArch64 macOS over the tail-calling interpreter, measured on the pyperformance suite. Individual results range from roughly a 15% slowdown to over 100% faster than a no-JIT build, so it is not a per-workload guarantee.

What’s new in Python 3.15’s JIT specifically?

A rebuilt tracing frontend that records the paths code actually takes at runtime instead of estimating them, so the JIT understands far more bytecode and control flow, plus basic register allocation — deciding which values live in CPU registers versus memory.

Should you enable Python 3.15’s JIT?

For most applications, not yet — if your workload is I/O-bound, which most web backends are, the JIT has nothing to compile that matters. It’s worth testing specifically for CPU-bound work like numerical processing or tight loops.

Is Python’s JIT enabled by default?

No, it’s opt-in and experimental, built via a separate compile flag (—enable-experimental-jit). It’s been experimental since its introduction in Python 3.13.