-
Notifications
You must be signed in to change notification settings - Fork 3.6k
perf(renderer): diff code lines in O(n) via a prev-line map#706
Open
ly-wang19 wants to merge 1 commit into
Open
perf(renderer): diff code lines in O(n) via a prev-line map #706ly-wang19 wants to merge 1 commit into
ly-wang19 wants to merge 1 commit into
Conversation
BaseCodeElement diffed each render against the previous one with a linear prevLinesRef.current.find() per line, on top of a separate Set pass — O(lines x prevLines). This effect runs on every streaming update while a code block types out, and code blocks routinely run dozens to hundreds of lines, so the quadratic cost lands on a render hot path. Build a single Map<id, prevLine> and fold the insert/replace checks into one O(n) pass. Behavior is identical: a line missing from the previous render is "inserted", a line present with changed content is "replaced" (the two were already mutually exclusive). Closes THU-MAIC#705
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
BaseCodeElement's line-diffuseEffectruns on every[lines, animate]change — i.e. on each streaming update while a code block types out. It built aSetfor the insert check (O(1)), then did a second pass with a linearprevLinesRef.current.find(...)per line for the content/replace check:That second loop is O(lines ×ばつ prevLines) = O(n2). Code blocks routinely run 50-300 lines and this fires repeatedly during the typing animation, so it's an on-render hot path.
Fix
One
Map<id, prevLine>, one O(n) pass. Insert and replace were already mutually exclusive (a line either isn't in prev → inserted, or is in prev with changed content → replaced), so the mergedif/else ifis behavior-identical and also drops the redundant second iteration. Consistent with theSetthe first loop already used.Verification
prettierclean,eslintclean,tsc --noEmiterror count unchanged (the only errors are pre-existing unresolved-workspace-module noise; the edited region type-checks clean).statesmap for any (prev, current) line pair —typingon first render,insertedfor new ids,replacedfor same id + changed content, unchanged otherwise.Closes #705