Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use Spans and ReadOnlyCollection.Empty in TextBlock/Line, reduce allocs #9993

Open
wants to merge 14 commits into
base: main
Choose a base branch
from

Conversation

h3xds1nz
Copy link
Contributor

@h3xds1nz h3xds1nz commented Oct 24, 2024

Description

Bringing some optimizations to TextBlock control and related components (Line; ComplexLine).

  • Empty Initialize method in TextBlock's ctor has been removed.
  • Unused private methods GetLineIndexFromDcp and ClearComplexContent have been removed (EnsureComplexContent handles the detach if its needed)
  • Instead of using new ReadOnlyCollection<T>(new List<T>(0)) numerous times, we swap to the non-allocating, generic singleton variant of ReadOnlyCollection<T>.Empty, removing all possible overhead.
  • Replaced ArrayList for InlineObjects in ComplexContent with List<InlineObject>.
  • Unused calculated variable removed in ComplexLine - double adjustedXOffset (method doesn't modify state either)
  • Unused calculated variable removed in AlignContent - Vector contentOffset (method doesn't modify state either)
  • GetRangeBounds in Line instead of using a List<Rect> now uses pre-allocated Rect[] that's wrapped in ReadOnlySpan<Rect> to its callers on return.
  • Instead of creating List<TextSegment>(1) and using Insert (that's a great combination), we use TextSegment[].
  • I've adjusted the weird loop GetTightBoundingGeometryFromTextPositions with more thoughtful impl.

new ReadOnlyCollection<T>(new List<T>(0)) vs Empty

Method Mean [ns] Error [ns] StdDev [ns] Gen0 Code Size [B] Allocated [B]
Original 6.0508 ns 0.1542 ns 0.2577 ns 0.0033 78 B 56 B
PR_EDIT 0.6467 ns 0.0061 ns 0.0051 ns - 14 B -

GetRangeBounds call old vs. new and the loop itself; without combining geometries

GetTightBoundingGeometryFromTextPositions inner loop (1 rect)

Method Mean [ns] Error [ns] StdDev [ns] Gen0 Code Size [B] Allocated [B]
Original_string 131.0 ns 1.93 ns 1.71 ns 0.0210 1,682 B 352 B
APR_EDIT_int 112.3 ns 1.14 ns 1.07 ns 0.0134 975 B 224 B

Customer Impact

Increased performance, decreased allocations.

Regression

No.

Testing

Local build, sample apps run.

Risk

Should be low, the changes are pretty much mechanical.

Microsoft Reviewers: Open in CodeFlow

@h3xds1nz h3xds1nz requested review from a team as code owners October 24, 2024 21:43
@dotnet-policy-service dotnet-policy-service bot added PR metadata: Label to tag PRs, to facilitate with triage Community Contribution A label for all community Contributions labels Oct 24, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Community Contribution A label for all community Contributions PR metadata: Label to tag PRs, to facilitate with triage
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant