Big optimizations for Buffer::set_rich_text #303
Merged
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
Currently when
Buffer::set_rich_text
is called, all existing allocations in the buffer are simply discarded. This amounts to a lot of allocations for complex text.Solution
Reuse existing allocations as much as possible when rebuilding a buffer.
Note that the changes here try to line up buffer reuse so it all maps back into the same positions in the buffer if possible. This way if, for example, you are just animating text color, the buffer won't actually require any extra allocations after the first time it's constructed (and won't over-allocate).
I did not originally intend for this PR to get so big, but diving into the code was a rabbit hole of allocations to squash.
Closes #301
Testing
I did not do any perf testing.
Follow-up
Additional areas for improvement:
Buffer::set_text
can also be optimized in a similar fashion.SmallVec
instead ofVec
where it makes sense. This should somewhat reduce the cost to make new buffers.set_rich_text
that I didn't try to solve yet.ShapeLine
is essentially aVec<Vec<Vec<ShapeGlyph>>>
. This can be flattened into two vecs: a vec of indices + metadata and a vec of ShapeGlyphs. Or even one vec with the metadata in-line.BufferLine
caches aVec<LayoutLine>
, which is essentiallyVec<Vec<LayoutGlyph>>
. This could also be flattened.Buffer
caches aShapeBuffer
but it would be better to have this inFontSystem
or elsewhere for global reuse.