Repository navigation
Avoid unnecessary AttributedString copies on iOS - #59018
Open
dheerajkoppu wants to merge 1 commit into
Open
dheerajkoppu wants to merge 1 commit into
dheerajkoppu wants to merge 1 commit into
Conversation
iOS text measurement deep-copied the AttributedString several times per measure, even on a cache hit. Bind references where the code only reads, move dying locals into the box, add an AttributedString&& box constructor, build the empty-string placeholder only when needed, and take const AttributedString& in the RCTTextLayoutManager methods.
dheerajkoppu
marked this pull request as ready for review
October 13, 2026 04:07
This branch has not been deployed
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.
Summary:
Measuring
<Text>on iOS makes a bunch of unnecessary copies ofAttributedString.There are a few places where this happens:
ParagraphShadowNodecopies a local string intoAttributedStringBoxeven though the local is about to be destroyed.TextLayoutManager::measureusesautoinstead of a reference, which makes another copy.ensurePlaceholderIfEmpty_DO_NOT_USEcopies the string even when it's not empty.RCTTextLayoutManagermethods take the string by value, which also copies it.This PR avoids those extra copies by using
std::move, passing references where possible, and only creating a placeholder when the string is actually empty. Nothing changes in how text is rendered.With these changes, a cache hit goes from 5 copies to 2, and a cache miss goes from 11 to 6. Draw, hit-testing, and frame updates go from 2 copies to 0. The remaining copies mostly come from cache keys, which I left alone.
It's a pretty small cleanup, but it removes some unnecessary work.
I also ran a quick benchmark on an M4 Pro using clang
-O2, taking the median of 7 runs:Benchmark code
Changelog:
[IOS] [CHANGED] - Pass
AttributedStringby const reference inRCTTextLayoutManagerand add a move constructor forAttributedStringBox.Test Plan:
testValueMoveConstructortoAttributedStringBoxTest.yarn fantom Text: all 223 tests pass.RNTesterUnitTestspass.yarn format-check-cpppasses.