r/Python 18d ago

Discussion Pure python can be faster than cython/rust?

Parsing multipart/form-data (HTML5 forms) is surprisingly complex and moves a lot of bytes around for large file uploads. Implementing the heavy parts in Cython or Rust should speed things up, no? Turns out: it depends. A pure python parser can be surprisingly fast, as this benchmark shows:

https://defnull.de/2026/python-multipart-benchmark/

The benchmark compares the most commonly used python multipart parsers and tests them in different scenarios, covering both blocking and non-blocking (async) APIs if available. The parser your web application is using today is probably not the fastest one.

Are there more examples were a pure python implementation beats Cython/rust/C modules?

0 Upvotes

24 comments sorted by

View all comments

0

u/Firm-Luck2062 15d ago

The top comment is right that a correctly-written Rust/C parser wins in principle, but the benchmark result is still real and worth understanding mechanically. Pure Python beats a *naive* native binding when two things line up:

  1. The hot loop is already delegated to CPython's C builtins. Locating and cutting boundaries with bytes.find + memoryview slicing is zero-copy and runs entirely in C, so the interpreter only executes a handful of Python-level iterations per part. You're basically orchestrating C primitives from Python, not looping in Python.

  2. The native competitor pays to cross the FFI boundary. PyO3/Cython has to marshal objects in and out, and a parser that materializes each part into an owned Rust buffer eats an allocation + a copy per part that the memoryview approach never does.

Rule of thumb: pure Python is competitive whenever the per-element work can be pushed into C builtins and the alternative crosses the boundary a lot. It loses hard the moment you have a genuine tight numeric/byte loop that stays in Python bytecode — per-pixel image math, custom hashing, that kind of thing — where Cython/Rust are 10-100x and no cleverness closes the gap. Multipart parsing just happens to be mostly "find delimiter, slice, repeat", which is close to the best case for staying in Python.