Skip to content

0.9.0

Choose a tag to compare

@kurok kurok released this 28 Aug 08:31
306a9f8

Highlights

The default parse is ~4–5x faster, metadata mode ~12x. Two byte-at-a-time loops in mailparse — the MIME boundary search and the base64 whitespace strip — were most of a parse and the source of the codegen cliff #120/#204 chased (their speed depended on where the linker placed them). Both are replaced in a patched copy of mailparse 0.16.1 in vendor/mailparse (memchr for the search, a dependency-free word-at-a-time strip; PATCH.md explains).

0.8.0 0.9.0
parse_email (full), Apple M4 vs the published 0.8.0 wheel 1.079 ms 0.225 ms 4.8x
parse_email(mode="metadata"), same 0.365 ms 0.030 ms 12x
parse_many, 8 × 767 KiB, same 8.852 ms 1.835 ms 4.8x
parse_email (full), CI runner (EPYC 7763), across the two fixes 1.432 ms 0.575 ms 2.5x
vs mail-parser / stdlib email, CI runner 6.4x / 8.6x 25x / 34x

mode= on parse_many and parse_email_tree (#202): the same "full" / "lazy" / "metadata" values parse_email honours, with PyLazyMimePart and PyMimePartMetadata node types for the tree. Batch and mode compose: parse_many(mode="metadata") on 8 × 767 KiB is 0.41 ms against 4.48 ms.

Rust toolchain pin moved to 1.98.0 (#120). The "1.98.0 is 26% slower" finding was the layout effect above, not codegen: the loops' instructions were byte-identical under both compilers.

README: badges refreshed; the Benchmark section now covers every mode and batch shape from a single CI run.

Measured at release time

Per #204, a version string alone moves code layout. This commit against the previous master (nothing else changed): ±0.4% on the decoding paths on the CI runner (EPYC 9V74); +3–7% on an Apple M4. Recorded here so nobody has to rediscover it.

Wheels

13 abi3 wheels (manylinux/musllinux × x86_64, i686, aarch64, armv7, s390x, ppc64le; Windows x64/x86; macOS arm64) plus an sdist that carries the vendored crate, published via PyPI Trusted Publishing with PEP 740 attestations. Python ≥ 3.11.

Full details: CHANGELOG.