Repository navigation
Knuth-Plass: keep only the best active node per line and fitness class - #57
Conversation
FindBreaks added every candidate node at every legal breakpoint, so while lines were too loose the active set doubled per breakpoint. One 25-breakpoint paragraph reached about 26 million nodes, and a 13-page DOCX took about 190 s to render to SVG (MS-23775, MS-27476 on Magic Suite test2). Keep the lowest-demerit node per (line, fitness class); on a tie the later candidate wins, which keeps the rendered output byte-identical for that document. Adds a regression test that times out without the fix. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Up to standards ✅🟢 Issues
|
| Metric | Results |
|---|---|
| Complexity | 4 |
| Duplication | 0 |
AI Reviewer: run a review on demand. To trigger the first review automatically, go to your organization or repository integration settings. AI can make mistakes. Always validate suggestions.
TIP This summary will be updated as you push new changes.
Since its target moved from net10.0-windows to net10.0 (e4358eb, 2026-10-04), the Word COM interop calls fail CA1416 on the Linux CI runner, and the build job has failed on main ever since, which also blocks publishing. Declaring SupportedOSPlatform("windows") keeps the net10.0 target. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Added a second commit so CI can build: Not fixed here: the coverage job also fails on 🤖 Generated with Claude Code |
Problem
KnuthPlassAlgorithm.FindBreaksadded every candidate break node at every legal breakpoint. The comment said "keep only the best per fitness class", but nothing did. While lines were too loose (accepted with +10000 demerits), the active set roughly doubled at each breakpoint.Seen in Magic Suite's ReportMagic Files viewer (
/files/pageSvg, MS-23775) on test2, 4.7.526: a 746 KB DOCX (32 paragraphs, 59 images) took 122–189 s to render, and the user got an nginx 504.Measured on Windows against 1.0.289 (indicative only; production runs on Linux):
ToSvgPagestook 188–197 s on every render, nearly all of it page 2 (six short paragraphs, no images).KnuthPlassAlgorithm.FindBreaks←RenderCommandEmitter.BuildWrappedLines.Fix
Keep only the lowest-demerit node per
(line, fitness class)at each breakpoint. On equal demerits the later candidate wins (<=). With<, one line on page 1 broke after a different word, so<=is what keeps the output unchanged.Results (same document)
ToSvgPagesAll 13 SVG pages are byte-identical before and after (SHA-256 per page). Peak active nodes after the fix: 133–232.
Tests
FindBreaks_LongWordWrappedParagraph_CompletesQuickly: a 40-word paragraph shaped likeBuildWrapItemsoutput, which must finish within 10 s.System.TimeoutException, 10 s) on the unfixed algorithm and passes in about 1 s with the fix.Not in this PR (possible follow-ups)
RenderCommandEmitterbreaks every paragraph again at SVG time instead of reusing the layout's line breaks.SKTypeface.FromFamilyNameis called once per token, with no cache.DocxRenderer.RenderAsyncandToSvgPagescan't be cancelled.🤖 Generated with Claude Code