Conversation
There was a problem hiding this comment.
Benchmark
Details
| Benchmark suite | Current: baa1de0 | Previous: d653e35 | Ratio |
|---|---|---|---|
benchmarks/test_guard_by_type.py::test_g16_resolve_by_type |
6494550.682298163 iter/sec (stddev: 5.851735687942965e-9) |
3047679.6993326377 iter/sec (stddev: 7.68398095030079e-9) |
0.47 |
benchmarks/test_guard_by_type.py::test_g17_resolve_by_type_large_registry |
6598767.1127743665 iter/sec (stddev: 4.293556413666038e-9) |
2865716.75416891 iter/sec (stddev: 1.0895383143788401e-8) |
0.43 |
benchmarks/test_guard_cold.py::test_g8_cold_first_resolve |
37184.40656966034 iter/sec (stddev: 0.00004473324922685243) |
20141.29411413181 iter/sec (stddev: 0.000060512136922370814) |
0.54 |
benchmarks/test_guard_cold.py::test_g8b_cold_first_resolve_cached |
30381.475639833036 iter/sec (stddev: 0.00012256014172113596) |
16227.953564347019 iter/sec (stddev: 0.00012174055036984476) |
0.53 |
benchmarks/test_guard_concurrency.py::test_g14_concurrent_cached_hit[1] |
873.3331984560833 iter/sec (stddev: 0.00004723603845158256) |
394.7618303242616 iter/sec (stddev: 0.00007930621161047323) |
0.45 |
benchmarks/test_guard_concurrency.py::test_g14_concurrent_cached_hit[2] |
808.8569543873873 iter/sec (stddev: 0.0000419013861282321) |
370.305000465928 iter/sec (stddev: 0.00005600518613977446) |
0.46 |
benchmarks/test_guard_concurrency.py::test_g14_concurrent_cached_hit[4] |
750.8059377924143 iter/sec (stddev: 0.00002616986229979413) |
343.96319541635654 iter/sec (stddev: 0.00005469358116412396) |
0.46 |
benchmarks/test_guard_concurrency.py::test_g15_concurrent_first_resolve[1] |
3679.4575547426684 iter/sec (stddev: 0.00010551241219228818) |
1910.842569787941 iter/sec (stddev: 0.000162661718918218) |
0.52 |
benchmarks/test_guard_concurrency.py::test_g15_concurrent_first_resolve[2] |
2829.1033444572854 iter/sec (stddev: 0.00012990435949108989) |
1470.0730071324613 iter/sec (stddev: 0.00019458681356333786) |
0.52 |
benchmarks/test_guard_concurrency.py::test_g15_concurrent_first_resolve[4] |
1951.5797769946635 iter/sec (stddev: 0.00012682315560502754) |
1024.2656207545813 iter/sec (stddev: 0.00022810651173013014) |
0.52 |
benchmarks/test_guard_concurrency.py::test_g15b_concurrent_first_resolve_sibling_children[1] |
3661.522400603589 iter/sec (stddev: 0.00012312199572803097) |
1862.3647861059314 iter/sec (stddev: 0.00018649465933071155) |
0.51 |
benchmarks/test_guard_concurrency.py::test_g15b_concurrent_first_resolve_sibling_children[2] |
1746.6143481918753 iter/sec (stddev: 0.001982887164665335) |
1296.7650208188347 iter/sec (stddev: 0.00019925902064693113) |
0.74 |
benchmarks/test_guard_concurrency.py::test_g15b_concurrent_first_resolve_sibling_children[4] |
1601.192375939192 iter/sec (stddev: 0.00013268703447170884) |
756.3003458505401 iter/sec (stddev: 0.0012513716793371842) |
0.47 |
benchmarks/test_guard_lifecycle.py::test_g6_build_child_container |
1772948.6596151898 iter/sec (stddev: 1.363381581178034e-7) |
931547.817002775 iter/sec (stddev: 1.3562406349897537e-7) |
0.53 |
benchmarks/test_guard_lifecycle.py::test_g6b_build_child_container_auto_scope |
1629118.2735386593 iter/sec (stddev: 1.659587571492171e-8) |
862077.9393011483 iter/sec (stddev: 4.603612433079451e-8) |
0.53 |
benchmarks/test_guard_lifecycle.py::test_g7_request_lifecycle_batch |
4871.44759639082 iter/sec (stddev: 0.000007747005260560703) |
2434.0141014239816 iter/sec (stddev: 0.000010514100178307428) |
0.50 |
benchmarks/test_guard_lifecycle.py::test_g7c_event_loop_floor_control |
115056.85223269826 iter/sec (stddev: 0.0000015689318403539552) |
57790.66542745276 iter/sec (stddev: 0.000002017861486579691) |
0.50 |
benchmarks/test_guard_lifecycle.py::test_g13_teardown_at_scale |
84665.72055428299 iter/sec (stddev: 7.710670161675587e-7) |
42337.38482583684 iter/sec (stddev: 0.00000195560890905176) |
0.50 |
benchmarks/test_guard_lifecycle.py::test_g13b_teardown_at_scale_async_no_finalizers |
1099.7571501121174 iter/sec (stddev: 0.00001224649302786763) |
527.9760349185017 iter/sec (stddev: 0.00005864358048386608) |
0.48 |
benchmarks/test_guard_resolve.py::test_g1_transient_resolve |
4456031.611958201 iter/sec (stddev: 1.9063046161860242e-8) |
2056805.8935774143 iter/sec (stddev: 2.984496256464475e-8) |
0.46 |
benchmarks/test_guard_resolve.py::test_g2_cached_resolve |
7372067.89824232 iter/sec (stddev: 4.564719075047762e-9) |
2997882.9250505473 iter/sec (stddev: 9.425210929455026e-9) |
0.41 |
benchmarks/test_guard_resolve.py::test_g3_deep_chain |
1548691.0598629222 iter/sec (stddev: 2.487485711928981e-8) |
693179.6082788195 iter/sec (stddev: 5.861598282461815e-8) |
0.45 |
benchmarks/test_guard_resolve.py::test_g4_wide_resolve |
879820.2492005874 iter/sec (stddev: 3.150982717261068e-7) |
367969.91183531785 iter/sec (stddev: 4.2236427939196184e-7) |
0.42 |
benchmarks/test_guard_resolve.py::test_g5_cross_scope |
4063591.550518981 iter/sec (stddev: 1.8174168272849375e-8) |
1819533.731741305 iter/sec (stddev: 2.5719724263261836e-8) |
0.45 |
benchmarks/test_guard_resolve.py::test_g9_context_resolve |
3056283.9911284638 iter/sec (stddev: 1.3644593654572645e-7) |
1293317.0685799515 iter/sec (stddev: 1.5552437513477855e-7) |
0.42 |
benchmarks/test_guard_resolve.py::test_g12_override_active_resolve |
1544801.6420670622 iter/sec (stddev: 2.352957490628623e-8) |
659745.3442362943 iter/sec (stddev: 5.5669749410889215e-8) |
0.43 |
benchmarks/test_guard_resolve.py::test_g18_alias_hop |
7203067.065933864 iter/sec (stddev: 5.889923100113078e-9) |
3089956.8954028534 iter/sec (stddev: 1.4619977910560272e-8) |
0.43 |
benchmarks/test_guard_validate.py::test_g10_validate_deep_chain |
54398.70661629766 iter/sec (stddev: 0.000012601078788198747) |
26681.65084469777 iter/sec (stddev: 0.000039429132466512916) |
0.49 |
benchmarks/test_guard_validate.py::test_g11_validate_wide |
31951.128235850723 iter/sec (stddev: 0.000015521816857705598) |
15769.247632211958 iter/sec (stddev: 0.00002931769417972418) |
0.49 |
This comment was automatically generated by workflow using github-action-benchmark.
Merged
7 tasks done
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #576.
Summary
The issue was written against 9cd88e7. Ten PRs landed since, so I re-checked every bullet against current main (634b5d5).
pyproject.tomlsetsfilterwarnings = ["error"]. The twotest_parse_creatorcases with unresolvable annotations moved to their own parametrized test that wraps the call inpytest.warns(UserWarning).test_container.py, two intest_context_provider.py. With the guard gone,test_set_context_provider_direct_resolve_does_not_warnwas a copy oftest_context_provider, so I deleted it.TypeErrorasserts for removed constructor arguments now havematch=.test_container.py:test_explicit_open_after_close_does_not_warnandtest_construct_then_close_then_reuse_raises_until_reopened(both covered bytest_open_reopens_closed_container), andtest_build_child_off_closed_parent_is_allowed(a subset oftest_child_built_off_closed_parent_raises_only_when_the_parent_resolves).test_warm_cached_resolve_does_not_wait_for_the_lock. The main thread holds the container lock while a worker resolves a warm cached value through a child container, and the worker must finish within a 5 second join timeout.test_suggest_skips_bound_type_without_a_name(aForwardRefbound type,suggester.py53->40) andtest_sync_finalizer_returning_a_future_raises_in_sync_close_then_recovers(a non-coroutine awaitable from a sync finalizer,cache_registry.py72->74).open()calls on containers that had just been built and never closed.open()only clears the closed flag, so those calls did nothing. I used an AST pass that dropsx.open()only whenxwas assigned from a call earlier in the same block and nothing in between could close it.test_open_never_validateskeeps its call becauseopen()is what it tests.OMIT, not UNWIRABLEdocstring intest_factory.py.tests/providers/test_singleton.pytotest_cached_factory.py. Its two close/reopen tests moved totest_container.py. The concurrency test no longer sleeps to widen the race (see below) and dropped@pytest.mark.repeat(10), since it is deterministic now.Branch coverage (
pytest --cov=modern_di --cov-branch): 5 partial branches before, 3 after. Test count went from 615 to 604. Most of the drop is the removedrepeat(10). The 100% line coverage gate is unchanged and passes.Design decisions
test_concurrent_cache_misses_create_onceputs athreading.Barrier(4, timeout=5)inside a transient dependency of the cached factory. Dependencies resolve outside the lock, so all four threads are past the unlocked cache check before any of them can create, and the test asserts the creator ran once. If dependency resolution ever moved under the lock, the barrier times out and the test fails withBrokenBarrierErrorafter 5 seconds instead of hanging. I checked this by movingresolve()under the lock locally.target._lockturns it red after the 5 second join timeout.test_reopen_rebuilds_a_value_that_close_cleared, which uses a local group. Theirclear_cache=Falsehalf was already covered bytest_app_cached_factory, so it was dropped. Test names and provider attributes intest_cached_factory.pynow say "cached" instead of "singleton".catch_warningsblocks that guard warnings the library still emits (test_factory.pyskip_creator_parsing with a bound type,test_types_parser.pyunion return type with a bound type) stay as they are. They state what the test checks and still hold under the global filter.Skipped bullets
test_override_survives_root_close_sync_and_reopenand_async_already cover that, so there is no test to add.Open questions
Three partial branches remain, all outside this issue's list:
dependency_graph.py204->188: thematchover walk events has no fallthrough case. Every event type is matched, so the branch looks unreachable. Refactor: resolver compiler templates and resolution-step building #574 refactors this file, so I left it.cache_registry.py50->60:CacheItem.close_asyncwhen the item has nothing to finalize. I did not look for a public path that reaches it because Refactor: registries, wiring, container and exception internals #575 touches this file.providers_registry.py129->131: the generation changed between lookup and memo store, which needs a concurrent registry change mid-resolve. It is only reachable through a race.Test plan
just lintandjust lint-cijust test-ci(100% line coverage)pytest --cov=modern_di --cov-branch: 3 partial branches, down from 5mkdocs build --strict