Repository navigation
Preserve measured wraps for appearance-only highlighting - #463
Merged
Merged
Conversation
simonbs
force-pushed
the
codex/preserve-highlight-wraps
branch
from
October 27, 2026 12:39
4f76cb5 to
853ffc5
Compare
simonbs
force-pushed
the
codex/preserve-highlight-wraps
branch
from
October 27, 2026 12:51
853ffc5 to
56cf114
Compare
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.
Asynchronous highlighting previously repeated line-break searches for every measured character even when only colors changed. Compare final font runs after applying captures; when they match, retain wrap boundaries and geometry while rebuilding CoreText drawing lines and updating fragment-tree/cached renderers. Font changes still fully reflow. Complete styles, backgrounds, shadows, hidden whitespace, and partial-line continuation remain supported.
Based on
mainafter #462 was squash-merged as2f08c831270c505ef42b2e8371d41fd86cfae7d9; this PR contains stage 2 only. Only the stage 2 commit was replayed across the squash ancestry. The resulting files are identical to the previously verified head853ffc5c96e406e06c5667cbc02ef015c5a7603c, so existing local validation remains applicable. Measurements used predecessor23cd5eb4e24d68098f046cdf4a13f0e19b863aed; its later test-helper extraction changed no production behavior.Measurements
On the same Release iPhone 17 Pro / iOS 27.2 simulator, eight measured trials on the local fixture's 58,901-byte longest line reduced median isolated completion redisplay from 40.135 ms to 3.996 ms for all 2,027 wrapped fragments, 1.248 ms to 0.575 ms for the visible prefix, and 1.855 ms to 0.672 ms unwrapped. This controlled benchmark excludes font classification and query/token costs.
Ordinary-scroll smoothness is not demonstrated. The equivalent real-highlighter scroll pair had mixed CPU results and worse callback-stall counts. Requests, offsets, and content dimensions matched. Load and unchanged initial typesetting also varied materially. Full phase, memory, methodology, and limitation details are in AppearanceHighlightingPerformance.md. Fixtures, instrumentation, logs, and recordings remain local.
Follow-up ordinary-scroll comparison
A serialized A–B–B–A Release comparison against #462 passed eight benchmark test executions. Median scroll-process CPU was 11.781 → 11.889 s unwrapped and 3.501 → 3.312 s wrapped. Callback intervals over 25 ms remained mixed (unwrapped A: 130/132, B: 153/131; wrapped A: 5/6, B: 17/6). All phase offsets/content dimensions and request counts matched. Two samples per revision establish neither general smoothness gains nor a systematic regression; the isolated long-line completion reduction remains this PR’s demonstrated benefit. These are instrumented Simulator run-loop measurements, not physical-device compositor hitches.
Validation
Physical-device performance and compositor hitch traces remain unverified. The composition oracle synchronously settles final state; its main-queue barrier does not prove all background requests completed. Primary checkout and phone app were untouched. No range chunking or cache eviction.