Skip to content

perf(editor): dedupe alignment snap-lines in O(n) instead of O(n²)#692

Open
ly-wang19 wants to merge 1 commit into
THU-MAIC:mainfrom
ly-wang19:perf/uniq-align-lines-map
Open

perf(editor): dedupe alignment snap-lines in O(n) instead of O(n²)#692
ly-wang19 wants to merge 1 commit into
THU-MAIC:mainfrom
ly-wang19:perf/uniq-align-lines-map

Conversation

@ly-wang19

Copy link
Copy Markdown
Contributor

What & why

uniqAlignLines (lib/utils/element.ts) merges alignment snap-lines with Array.findIndex inside a forEachO(n²):

lines.forEach((line) => {
  const index = uniqLines.findIndex((_line) => _line.value === line.value); // O(n)
  ...
});

It runs on every drag/scale mousemove (useDragElement / useScaleElement), and the snap-line count grows with the number of nearby element edges. On element-dense canvases that’s ~n² comparisons per pointer move at ~60 Hz → drag jank.

Closes #691.

Fix

Dedupe in O(n) via a Map keyed on value. A Map preserves first-occurrence insertion order (re-set-ting an existing key keeps its slot), so the output order and the range-merge semantics are unchanged — behavior-preserving, just linear.

Test plan

New tests/utils/uniq-align-lines.test.ts (5 cases): dedupe + outer-bound range merge, first-occurrence order preserved, single line, empty input, and many-duplicates collapse. tsc/prettier/eslint clean.

No user-facing strings (no i18n impact). (Separate test file from element.test.ts to avoid overlap with #675, which also touches element.ts.)

uniqAlignLines used Array.findIndex inside a forEach (O(n^2)) to merge
alignment snap-lines. It runs on every drag/scale mousemove and the line
count scales with nearby element edges, so it janks on element-dense
canvases. Dedupe via a Map keyed on value (O(n)); a Map preserves
first-occurrence order, so output order and range-merge semantics are
unchanged.

Closes THU-MAIC#691
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

uniqAlignLines is O(n²) (findIndex in a loop) on the drag/scale hot path

1 participant