Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 10 additions & 11 deletions docs/introduction/performance.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,13 +37,13 @@ modern-di variant against the rivals whose API matches it, because a single colu
flatter modern-di against half the set. By-type resolution used to add a fixed lookup cost on
top of `resolve_provider`: 54-65 ns through 3.2.0, then 21/17/23 ns on C1/C2/C3 once 3.3.0 inlined
`resolve_provider`'s body into `resolve`. With the template resolver, `Container.resolve` memoizes
type → resolver directly, and the two columns differ by a few nanoseconds in either direction (242
vs 239 ns on C1, 146 vs 142 on C2, 760 vs 764 on C3 in the cells below).
type → resolver directly, and the two columns differ by 3-16 ns in either direction (242 vs
239 ns on C1, 143 vs 140 on C2, 756 vs 772 on C3 in the cells below).

C4 does not split this way: modern-di's C4 body resolves by reference throughout, while
dishka and wireup can only be measured by type. That asymmetry cuts against modern-di's
C4 ratios, though with the by-type surcharge now inside noise, levelling it would not
move the dishka ratio (1.12) below 1.0. The C1-C3 leveling does not apply to C4.
dishka and wireup can only be measured by type. The asymmetry is small: the by-type and
by-reference cells differ by at most 16 ns, under 1% of modern-di's 1.85 µs C4 cell, so levelling
it would not change which side of 1.0 any C4 ratio sits on. The C1-C3 leveling does not apply to C4.

C6 does not split either, for the same reason: modern-di's C6 body resolves by reference and there
is no by-type C6 variant to pair against dishka and wireup, so a split would leave that half of the
Expand All @@ -59,11 +59,10 @@ for why that matters and which cells it moved.

## Results

Measured 2026-10-06 with modern-di at the end of the #605 perf series (the 4.0 code, unreleased when measured)
on an Apple M2 (macOS 26.6.2), CPython 3.14.7 with the GIL, median over 5 runs (ratios paired
within each run); the footnote under each table bounds the across-run dispersion of each side's
own median. Rival versions: dishka 1.10.1, dependency-injector 4.49.1, that-depends 4.1.0,
wireup 2.12.0. Generated by `just bench-report`.
Measured 2026-10-06 with modern-di 4.0.0 on an Apple M2 (macOS 26.6.2), CPython 3.14.7 with the
GIL, median over 5 runs (ratios paired within each run); the footnote under each table bounds the
across-run dispersion of each side's own median. Rival versions: dishka 1.10.1,
dependency-injector 4.49.1, that-depends 4.1.0, wireup 2.12.0. Generated by `just bench-report`.

The previous publication (3.x, at `630de77`) used the same machine, CPython build and rival
versions, so the absolute cells are comparable with it as well as the ratios. The
Expand Down Expand Up @@ -168,7 +167,7 @@ an async finalizer and closes the child, so it gets the cheaper child build and
and #605 and pays for #597's lock allocation. The middle column is the previous 4.0 publication,
before #605.

| | 3.x (`630de77`) | 4.0 before #605 (`f300c2e`) | 4.0 with #605 |
| | 3.x (`630de77`) | 4.0 before #605 (`f300c2e`) | 4.0.0 |
|---|---|---|---|
| C1 / C2 / C3 by reference, modern-di | 253 / 151 / 789 ns | 242 / 146 / 760 ns | 242 / 143 / 756 ns |
| C4 request lifecycle, modern-di | 2.29 µs | 2.28 µs | 1.85 µs |
Expand Down
Loading