---
title: "Python 3.15 JIT: Is the Corolla Finally a Rocket?"
description: "Explore Python 3.15's new JIT compiler and its performance improvements. Learn how this game-changing feature transforms Python's speed, benchmark results, and what it means for developers upgrading their applications."
image: "https://cdn.sethserver.com/blog-images/python-315-jit-is-the-corolla-finally-a-rocket-social-1772156515.webp"
---

# Python 3.15 JIT: Is the Corolla Finally a Rocket?

Remember the Corolla? I talked about it last time - how Python is the Toyota Corolla of programming languages, and how the Microsoft team basically bolted a turbo onto it. From Python 3.10 to 3.14, we got somewhere between 20-40% faster depending on what you're running and who you're asking. The Corolla didn't become a rocket, but it stopped being embarrassing at stoplights.

Python 3.15 is continuing that trend. We're seeing 8% improvements on macOS, 4% on Linux. Not the 25% headline grab that 3.11 delivered, but incremental improvements are still freaking solid. Technology doesn't usually leap - it compounds. Four percent here, eight percent there, and eventually you look back and realize the thing runs twice as fast as it did five years ago.

Here's what I want to talk about, and it's not the speed numbers.

---

## You're Optimizing Blind

Let me tell you a story you've probably lived.

You profile your code. You find a function taking 2 seconds. You spend an afternoon optimizing it - rewriting the logic, maybe swapping a library, feeling genuinely clever - and you get it down to 0.5 seconds. Big win. You ship it, you feel good, and then you notice the application is still slow.

Because that function runs once. And somewhere else in your codebase there's something running 10,000 times that takes 0.1 seconds each. That's 1,000 seconds of runtime that you completely ignored because you were optimizing what you *assumed* was slow instead of what *was* slow.

This problem has gotten weirder with AI coding assistants in the picture. LLMs are excellent at optimizing whatever you point them at. They'll happily rewrite your function to be more efficient, swap algorithms, suggest better data structures. What they can't do is tell you that the function you handed them only runs once while the real problem is three files over and six call-stack levels deep. AI sees your source code. It doesn't see your runtime behavior. That's a fundamental limitation of only being able to look at the code.

Which brings us to what Python 3.15 actually does that matters.

---

## PEP 799 and, Hopefully, the End of the Profiling Mess

Python has always had profiling tools. The problem is finding them and understanding which one to use.

Here's the old landscape: there's `profile`, a pure Python profiler that is so slow it will meaningfully distort your measurements and make your code look slower than it is. There's `cProfile`, the C implementation that's definitely usable, but the name implies `profile` is the main thing and `cProfile` is some kind of variant. And then there's `profile.sample` - the new hotness, a statistical sampling profiler that's genuinely excellent - buried under the module name of the slow thing everyone was told to avoid.

It's like if your toolbox had "hammer" and "better\_hammer" and then hidden in a drawer inside the toolbox, "actually\_use\_this\_hammer." Good luck onboarding someone new.

PEP 799 cleans this up. Python 3.15 introduces a new top-level `profiling` module with two clear children:

- `profiling.tracing` - the deterministic function-call tracer (what `cProfile` was)
- `profiling.sampling` - the statistical sampling profiler (what you should probably be using)

`profile` is getting deprecated in 3.15 with a `DeprecationWarning` and is scheduled for removal in 3.17. I'm totally cool with that. No complaints from me. Dump it.

---

## Tracing vs. Sampling: Actually Understanding the Difference

This distinction matters enough to spend some time on.

**Tracing profilers** instrument every single function call. Every time your code enters or exits a function, the profiler records it. This gives you complete, deterministic data - you know exactly how many times each function was called and exactly how long each call took. The cost is that this instrumentation adds significant overhead, sometimes 10x or more. It also disables some of the interpreter optimizations that make Python 3.11+ fast in the first place. And it only watches the main thread. We'll save the threading argument for later.

**Sampling profilers** take periodic snapshots of what your code is doing. Every few milliseconds, they look at the call stack and say "okay, right now the program is here." Over thousands of snapshots, a statistical picture emerges of where your program spends its time. The overhead is near-zero. They work across multiple threads, across async code, and can even attach to processes that are already running. You lose a little precision - if a function runs very fast and very rarely, it might never get caught in a snapshot - but for finding the actual bottlenecks that are eating your runtime, it works pretty well.

Here's why the sampling profiler matters right now specifically: remember free-threading from Python 3.14? Multiple threads running in genuine parallel? `cProfile` - the tracing approach - only watches the main thread. If you have eight CPU cores running eight threads, your tracing profiler is showing you one-eighth of the story. `profiling.sampling` sees all of them.

---

## What the Workflow Actually Looks Like

Here's the practical version. Say you're running a Flask API endpoint that takes two seconds to respond. You have a hunch it's the JSON serialization - that part of the code looks complex, there's a lot going on, it seems like a candidate.

Without profiling, you go optimize the JSON serialization. Maybe you shave it from 400ms to 100ms. You ship it. The endpoint still takes 1.7 seconds.

With `profiling.sampling`, you run the endpoint under the profiler and look at where time is actually spent. And you discover that 1.8 seconds of your 2-second request is a database query hitting a table with 2 million rows and no index on the column you're filtering by. The JSON serialization was taking 100ms all along. You were optimizing the wrong thing. Whoopsie. You scoff, but this is one of the more common things I run into.

```python
import profiling.sampling as sampler

with sampler.profile():
    result = my_slow_function()

sampler.print_stats()
```

That's the basic shape of it. Run your code under the profiler, look at the output, find the functions at the top of the list sorted by cumulative time. Those are your bottlenecks. Then - and only then - go optimize. Use AI to help you write the better query, the smarter algorithm, the cleaner implementation. Use the profiler to tell you what to point the AI at.

The tools complement each other. They don't replace each other.

---

## A Better Dashboard

Here's where we land. Python 3.10 to 3.14 was about making the engine faster. Python 3.15 is, in part, about building a better dashboard. You can see the RPMs. You can see the boost pressure. You can actually observe what's happening instead of guessing.

The Corolla is not a rocket. That was never the point. The point is that it's reliable, it's practical, it's getting meaningfully faster, and now you can actually tell which parts are slow and why.

Speed without measurement is just guessing. The best optimization is optimizing the right thing. Python 3.15 makes it a lot easier to find the right thing.

A quick note: Python 3.15 isn't out yet - it's currently in alpha with a scheduled release of October 2026. You can test the alpha builds if you want to kick the tires early. The API may shift before final release.

Profile before you optimize. Let AI help with the optimization. Read the profiler output so your readers don't have to guess.

-Sethers


```json
{"@context": "https://schema.org", "@type": "NewsArticle", "mainEntityOfPage": {"@type": "WebPage", "@id": "https://www.sethserver.com/python/python-315-jit-is-the-corolla-finally-a-rocket.html"}, "headline": "Python 3.15 JIT: Is the Corolla Finally a Rocket?", "datePublished": "2026-02-27T03:14:25", "dateModified": "2026-09-17T19:48:22", "image": {"@type": "ImageObject", "url": "https://cdn.sethserver.com/blog-images/python-315-jit-is-the-corolla-finally-a-rocket-social-1772156515.webp", "width": 1200, "height": 630}, "url": "https://www.sethserver.com/python/python-315-jit-is-the-corolla-finally-a-rocket.html", "author": {"@type": "Person", "name": "Seth Black", "url": "https://www.linkedin.com/in/seth-black-tx"}, "publisher": {"@type": "Organization", "name": "Sethserver", "logo": {"@type": "ImageObject", "url": "https://www.sethserver.com/static/images/PaperAirplane512.png"}}, "description": "Explore Python 3.15's new JIT compiler and its performance improvements. Learn how this game-changing feature transforms Python's speed, benchmark results, and what it means for developers upgrading their applications.", "articleSection": "Technology"}
{"@context": "https://schema.org", "@type": "BreadcrumbList", "itemListElement": [{"@type": "ListItem", "position": 1, "name": "sethserver", "item": "https://www.sethserver.com/"}, {"@type": "ListItem", "position": 2, "name": "Python", "item": "https://www.sethserver.com/python/"}, {"@type": "ListItem", "position": 3, "name": "Python 3.15 JIT: Is the Corolla Finally a Rocket?", "item": "https://www.sethserver.com/python/python-315-jit-is-the-corolla-finally-a-rocket.html"}]}
```
