Skip to content

Commit 7bf608f

Browse files
committed
perf(engine): share one summary index among the members of a cycle that read alike
With an index of its own for each member, built and compared at every round of the fixpoint, Django 5.1.4, whose largest cycle holds 144 modules, took 185 s to analyse instead of 176 s. In a regular package every member reads every module under the same names: the members that do now share one index, and the analysis takes 175 s again, with the same findings.
1 parent 1ce0a4d commit 7bf608f

1 file changed

Lines changed: 15 additions & 10 deletions

File tree

‎src/coretrace_python/engine.py‎

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -909,28 +909,33 @@ def _analyse_managers(
909909
"""Analyse one component: iterate its summaries to a fixpoint (§21), then extract
910910
what the rest of the run needs from each module. Each member reads, in an index of
911911
its own, the modules ``names`` gives it under the names given (``_imported_names``):
912-
the members' summaries as they grow, the others' as ``imported`` holds them, final."""
912+
the members' summaries as they grow, the others' as ``imported`` holds them, final.
913+
Members that read every module under the same names, as in a regular package, share
914+
one index."""
913915

916+
views = {member: tuple(sorted(names[member].items())) for member in managers}
914917
final = {
915-
member: _index(imported, {name: module_names for name, module_names in names[member].items() if name not in managers})
916-
for member in managers
918+
view: _index(imported, {name: module_names for name, module_names in view if name not in managers})
919+
for view in dict.fromkeys(views.values())
917920
}
918921

919-
def indexes(summaries: Mapping[str, Mapping[str, FunctionSummary]]) -> dict[str, SummaryIndex]:
922+
def indexes(
923+
summaries: Mapping[str, Mapping[str, FunctionSummary]],
924+
) -> dict[tuple[tuple[str, tuple[str, ...]], ...], SummaryIndex]:
920925
return {
921-
member: SummaryIndex(
926+
view: SummaryIndex(
922927
{
923-
**final[member].summaries,
928+
**seed.summaries,
924929
**{
925930
project_symbol(module, function): summary
926-
for name, module_names in names[member].items()
931+
for name, module_names in view
927932
if name in managers
928933
for module in module_names
929934
for function, summary in summaries[name].items()
930935
},
931936
}
932937
)
933-
for member in managers
938+
for view, seed in final.items()
934939
}
935940

936941
# The members' functions start from the summaries ``SummaryAnalysis`` starts from.
@@ -939,7 +944,7 @@ def indexes(summaries: Mapping[str, Mapping[str, FunctionSummary]]) -> dict[str,
939944
# iteration then shifts by one module each time and never settles (#261).
940945
index = indexes({name: starting_summaries(manager.get(CallGraphAnalysis)) for name, manager in managers.items()})
941946
for name, manager in managers.items():
942-
manager.provide(ProjectSummaries, index[name])
947+
manager.provide(ProjectSummaries, index[views[name]])
943948
# Iterated until every member's index settles, with no bound: stopped earlier,
944949
# summaries that started empty would miss what later iterations add, a dependency
945950
# still on its way reading as no taint. It settles because each iteration can only
@@ -958,7 +963,7 @@ def indexes(summaries: Mapping[str, Mapping[str, FunctionSummary]]) -> dict[str,
958963
index = updated
959964
for name, manager in managers.items():
960965
manager.run(ProjectSummariesUpdated)
961-
manager.provide(ProjectSummaries, index[name])
966+
manager.provide(ProjectSummaries, index[views[name]])
962967
return {name: _analyse_module(manager, plugins, affected, suffixes, root) for name, manager in managers.items()}
963968

964969

0 commit comments

Comments
 (0)