Inline formatter printing hot paths#26504
Conversation
Merging this PR will improve performance by 5.99%
|
| Mode | Benchmark | BASE |
HEAD |
Efficiency | |
|---|---|---|---|---|---|
| ⚡ | Simulation | formatter[pydantic/types.py] |
3.2 ms | 2.9 ms | +7.23% |
| ⚡ | Simulation | formatter[large/dataset.py] |
7.9 ms | 7.4 ms | +7.16% |
| ⚡ | Simulation | formatter[numpy/ctypeslib.py] |
1.7 ms | 1.6 ms | +5.9% |
| ⚡ | Simulation | formatter[unicode/pypinyin.py] |
612.9 µs | 580.8 µs | +5.53% |
| ⚡ | Simulation | formatter[numpy/globals.py] |
231.6 µs | 222.3 µs | +4.17% |
Tip
Curious why this is faster? Use the CodSpeed MCP and ask your agent.
Comparing charlie/codex-inline-formatter-printing (1521be2) with main (c360a05)
Footnotes
-
93 benchmarks were skipped, so the baseline results were used instead. If they were deleted from the codebase, click here and archive them to remove them from the performance reports. ↩
|
nice 🚀 succeeding where I failed 🙂 |
| } | ||
|
|
||
| /// Prints a single element and push the following elements to queue | ||
| // LLVM considers this function too large to inline on its own, but it is called for every |
There was a problem hiding this comment.
LLVM does have a point, given that the function is called twice. But it's probably fine, we may want to reconsider if the function is ever called in three places.
|
Why is it silly |
Summary
The formatter calls
Printer::print_elementfor every rendered format element andPrinter::print_textfor every text element. LLVM leaves both private methods out of line even when they are marked#[inline]and the release profile uses fat LTO, so these hot loops retain out-of-line calls.This marks both functions as
#[inline(always)], allowing the printing loop and its common text paths to optimize together. It follows the same general source-level inlining approach as #26429 and closed #26473, but targets the printing pass rather than fitting or comment extraction. The methods have a small, fixed set of call sites, and the release binary's.textgrows by 11,264 bytes (0.36%).Performance
To test whether ordinary
#[inline]is sufficient and whether LTO changes the result, I built the exact base with no annotation,#[inline], and#[inline(always)]under both the profiling profile (LTO disabled) and the release profile (fat LTO). Plain#[inline]neither removed the out-of-line symbols nor changed.text, and CodSpeed reported 0.0% in both profiles. Forced inlining removed both symbols and preserved the improvement under fat LTO:.textdelta#[inline]#[inline(always)]#[inline]#[inline(always)]The release/fat-LTO comparison on the existing non-microbenchmark formatter suite reports:
formatter[large/dataset.py]formatter[pydantic/types.py]formatter[numpy/ctypeslib.py]formatter[unicode/pypinyin.py]formatter[numpy/globals.py]