From d41f8086d57481888cf08b976bb0d0eafc467e79 Mon Sep 17 00:00:00 2001 From: Todd Grunke Date: Wed, 31 Jul 2024 16:28:55 -0700 Subject: [PATCH] Reduce allocations in AbstractStructureTaggerProvider.GetMultiLineRegions (#74619) * Reduce allocations in AbstractStructureTaggerProvider.GetMultiLineRegions This is a private method, and the caller simply enumerates the results, so there is no need to allocate an intermediary array. This shows up as 0.6% of allocations in the scrolling speedomenter profile that I'm looking at (in the typing section of a particularly poorly performing run) --- .../Structure/AbstractStructureTaggerProvider.cs | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/src/EditorFeatures/Core/Structure/AbstractStructureTaggerProvider.cs b/src/EditorFeatures/Core/Structure/AbstractStructureTaggerProvider.cs index 0244ed956c537..aa3ae21b762d3 100644 --- a/src/EditorFeatures/Core/Structure/AbstractStructureTaggerProvider.cs +++ b/src/EditorFeatures/Core/Structure/AbstractStructureTaggerProvider.cs @@ -206,9 +206,13 @@ private void ProcessSpans( ImmutableArray spans) { var snapshot = snapshotSpan.Snapshot; - spans = GetMultiLineRegions(outliningService, spans, snapshot); - foreach (var span in spans) + // Use the returned enumerable directly instead of allocating into an array. The returned + // enumeration can contain a fairly large number of items for large files, so even + // using an ArrayBuilder could result in allocation issues without using a custom pool. + var multiLineSpans = GetMultiLineRegions(outliningService, spans, snapshot); + + foreach (var span in multiLineSpans) { var tag = new StructureTag(this, span, snapshot); context.AddTag(new TagSpan(span.TextSpan.ToSnapshotSpan(snapshot), tag)); @@ -226,12 +230,11 @@ protected override bool TagEquals(IContainerStructureTag tag1, IContainerStructu private static bool s_exceptionReported = false; - private static ImmutableArray GetMultiLineRegions( + private static IEnumerable GetMultiLineRegions( BlockStructureService service, ImmutableArray regions, ITextSnapshot snapshot) { // Remove any spans that aren't multiline. - var multiLineRegions = ArrayBuilder.GetInstance(); foreach (var region in regions) { if (region.TextSpan.Length > 0) @@ -262,12 +265,10 @@ private static ImmutableArray GetMultiLineRegions( var endLine = snapshot.GetLineNumberFromPosition(region.TextSpan.End); if (startLine != endLine) { - multiLineRegions.Add(region); + yield return region; } } } - - return multiLineRegions.ToImmutableAndFree(); } #region Creating Preview Buffers