perf(applications): memoise the payload a render re-enters for

get_merged_applications writes its cache in the last line of the function,
and the re-entrancy guard returns above it. Every lookup('applications') a
template makes while the payload is being rendered therefore rebuilt it:
get_application_defaults deep-copies roughly two hundred roles, then the
merge runs again.

Profiled over one render of tests/integration/roles/test-e2e-cli: 382 calls,
18.765s of 29s, 13.7 million deepcopy calls. That test spent 208s in setUp
for twenty renders and now spends about half.

The guarded payload cannot go into _MERGED_APPLICATIONS_CACHE, because it
carries no users and still holds its volumes. It is memoised on the render
guard instead, which is thread-local, and the finally that releases the guard
drops it, so it lives exactly one render.

Three probes established the preconditions before the change: one cache key
across all 381 nested calls, re-entrancy depth never above 2, and not one of
the 381 payloads mutated after it was handed out. That last one was then
re-measured across the whole suite with the memo made self-checking: 6861
tests and 5133 subtests, no caller wrote to what it was given.

113113e553 removed the same cost between tasks through the carrier fact.
This removes what remains inside a single render.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
kevinveenbirkenbachandClaude Opus 5 committed 2026-09-26 00:52:32 +02:00
1 parent d1d4108e62
commit dc772d6dc7
2 files changed
+71 -1

No files matched your search

+51
View File
@@ -652,5 +652,56 @@ class TestDeriveMcpPresence(unittest.TestCase):
self.assertIs(variants[1]["mcp"]["enabled"], False)
class TestGetMergedApplicationsMemoisesTheGuardedPath(unittest.TestCase):
"""A re-entrant call returns before the main cache is written, because its
payload carries no users and keeps its volumes. It is memoised on the
render guard instead, or one template render rebuilds the payload for
every ``lookup('applications')`` it makes.
"""
def setUp(self) -> None:
_reset_cache_for_tests()
cache_apps._RENDER_GUARD.applications = False
cache_apps._RENDER_GUARD.nested_payloads = {}
self.addCleanup(setattr, cache_apps._RENDER_GUARD, "applications", False)
self.addCleanup(setattr, cache_apps._RENDER_GUARD, "nested_payloads", {})
def _merged(self, roles):
return cache_apps.get_merged_applications(
variables={}, roles_dir=roles, templar=None
)
def test_a_re_entrant_call_serves_the_payload_it_already_built(self):
with tempfile.TemporaryDirectory() as tmp:
roles = _seed_minimal_roles(Path(tmp))
cache_apps._RENDER_GUARD.applications = True
first = self._merged(roles)
second = self._merged(roles)
self.assertIs(first, second)
def test_the_memo_does_not_outlive_the_guard(self):
with tempfile.TemporaryDirectory() as tmp:
roles = _seed_minimal_roles(Path(tmp))
cache_apps._RENDER_GUARD.applications = True
guarded = self._merged(roles)
cache_apps._RENDER_GUARD.applications = False
cache_apps._RENDER_GUARD.nested_payloads = {}
_reset_cache_for_tests()
after = self._merged(roles)
self.assertIsNot(guarded, after)
def test_the_guarded_payload_never_reaches_the_main_cache(self):
with tempfile.TemporaryDirectory() as tmp:
roles = _seed_minimal_roles(Path(tmp))
cache_apps._RENDER_GUARD.applications = True
self._merged(roles)
self.assertEqual(cache_apps._MERGED_APPLICATIONS_CACHE, {})
if __name__ == "__main__":
unittest.main()