You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Summarize only the callables an analyzed Scene can reach, instead of every callable in the project. This is the one remaining change that could move the cold path from seconds to under a second.
Measurements
On a 393-file / 161,869-line project (the Manim Community fork), release build, 16 logical cores:
Inside that phase, instrumentation showed the scheduling is not the problem, which is worth recording so nobody re-investigates it:
5,629 components, 17 rounds; the dependency scan costs 3 ms total
round sizes [2445, 938, 544, 428, 234, 326, 184, 143, 104, 97, 65, 58, 24, 3, 3, 1, 1] — the tail rounds that parallelize worst cost 22 ms of 4,067 ms
the sequential recursive-component pass costs 448 ms (~11%), the only other candidate
The cost is simply 5,629 callables at ~9 ms of CPU each. Thread scaling is 39.1 → 20.3 → 10.5 → 6.6 → 5.5 s at 1/2/4/8/16 threads; the knee at 8→16 is this machine's P-core/E-core split, so parallelism is close to exhausted.
Hypothesis
Summaries exist so the lifecycle interpreter can inline a call it meets while executing a Scene. A callable that no analyzed Scene reaches, transitively, therefore has a summary that is never read. In a library project most definitions are exactly that: the fork's manim/ package defines thousands of callables and contains almost no Scene subclasses.
If the reachable set is, say, 800 of 5,629, the dominant phase drops by roughly the same ratio and the cold run lands in the 1-second range.
Why this is not a quick patch
It can change results, which makes it a correctness change wearing a performance costume:
some rules may read summaries for callables outside any Scene's reach — that has to be established from the code, not assumed
the coverage report and static-facts may need the full table even when check does not
roots are not just Scene.construct: setup/teardown hooks, MRO-composed base methods, and callbacks registered from a Scene all count
a first attempt at computing the reachable set during this investigation returned 0, i.e. the root detection was wrong — evidence that the root set is the hard part, not the traversal
Suggested order
Compute the reachable set and log its size only, changing no behavior. Land that, and get the real ratio for several projects. If the ratio is not large, close this issue.
Establish which consumers need summaries for unreachable callables, from the code.
Only then make the table demand-driven, gated so the full table is still built for the consumers that need it.
Goal
Summarize only the callables an analyzed Scene can reach, instead of every callable in the project. This is the one remaining change that could move the cold path from seconds to under a second.
Measurements
On a 393-file / 161,869-line project (the Manim Community fork), release build, 16 logical cores:
Inside that phase, instrumentation showed the scheduling is not the problem, which is worth recording so nobody re-investigates it:
[2445, 938, 544, 428, 234, 326, 184, 143, 104, 97, 65, 58, 24, 3, 3, 1, 1]— the tail rounds that parallelize worst cost 22 ms of 4,067 msThe cost is simply 5,629 callables at ~9 ms of CPU each. Thread scaling is 39.1 → 20.3 → 10.5 → 6.6 → 5.5 s at 1/2/4/8/16 threads; the knee at 8→16 is this machine's P-core/E-core split, so parallelism is close to exhausted.
Hypothesis
Summaries exist so the lifecycle interpreter can inline a call it meets while executing a Scene. A callable that no analyzed Scene reaches, transitively, therefore has a summary that is never read. In a library project most definitions are exactly that: the fork's
manim/package defines thousands of callables and contains almost no Scene subclasses.If the reachable set is, say, 800 of 5,629, the dominant phase drops by roughly the same ratio and the cold run lands in the 1-second range.
Why this is not a quick patch
It can change results, which makes it a correctness change wearing a performance costume:
static-factsmay need the full table even whencheckdoes notScene.construct: setup/teardown hooks, MRO-composed base methods, and callbacks registered from a Scene all countSuggested order
Acceptance
docs/research/Related