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
{{ message }}
Repository navigation
render: graph and chapter pages still resolve every target page, keeping render quadratic #93
#88 links each target page once per map instead of once per node, but four call sites still build the full node-id to href map for every page they write:
write_graph_pages: the chapter, scope and focus loops, each through the node_links callback that render_site passes in
_render_chapter
Each full map costs about three Path.resolve calls per distinct target page: one in _anchored_links, two in mermaid.relative_link. When the number of target pages grows with the blueprint, as it does in sectioned layouts, flat layouts with many chapters, and real textbooks, render stays quadratic.
Path.resolve calls per render with #88, on generated roadmaps of 4 chapters with 5, 10, 20 or 40 sections each, 2 theorems per section, chained across the chapter:
nodes
target pages
Path.resolve calls
65
25
8,241
125
45
25,801
245
85
89,721
485
165
332,761
Each doubling multiplies the count by 3.1, 3.5, then 3.7.
On a 1,791-node textbook blueprint with 199 distinct target pages, #88 takes render from 1,540 s to 73 s CPU with identical output. 87% of the remaining CPU is in _anchored_links, almost all of it under node_links and _render_chapter.
Removing the repeated resolves doesn't need the node_links signature change that #87 and #88 set aside. Memoizing resolve() results and hrefs per (target page, page directory) inside the node_links closure took the same blueprint from 73 s to 20 s CPU, with byte-identical output. The closure alone leaves the 485-node roadmap at 92,356 resolves, 79,040 of them in _render_chapter; sharing the memo with every _anchored_links caller brings it to 12,326 and makes growth linear.
Acceptance criteria
Make Path.resolve calls grow linearly with blueprint size: on the roadmaps above, doubling the sections should at most double the calls.
Keep rendered output byte-identical.
Add a scale regression that counts Path.resolve calls at two sizes of a sectioned blueprint and fails before the fix.
Draft #90 removes the same cost another way: it drops the focus pages, passes node_links only the article ids each view shows, and resolves links lazily. That brings the 485-node roadmap to 16,186 resolves, with different output by design. If #90 lands first, only the scale regression is left here.
Repeated Graph.children scans and whole-graph index rebuilds are tracked in #60.
Draft #90 removes the quadratic link resolution another way: links resolve lazily, each view resolves only its own articles, and the focus pages are gone. It does not add the two-size Path.resolve scale regression asked for here, and its output is intentionally not byte-identical.
Activity
Deicyde commentedon Oct 13, 2026
Draft #90 removes the quadratic link resolution another way: links resolve lazily, each view resolves only its own articles, and the focus pages are gone. It does not add the two-size
Path.resolvescale regression asked for here, and its output is intentionally not byte-identical.Posted by issue triage