Skip to content

Commit

Permalink
Reduce allocations in VirtualCharService.CreateVirtualCharSequence (#…
Browse files Browse the repository at this point in the history
…75654)

This method shows up in OOP allocations in the scrolling speedometer test. This method is invoked to create runes for text sequences for strings. The standard case is that there aren't any multi-char runes in a string, in which case AbstractVirtualCharService.CreateVirtualCharSequence doesn't end up using the ImmutableSegmentedList in the result it creates. This means that we can reuse this builder and it's underlying array after it's been cleared out.

This shows up as around 2.0% of allocations in out OOP in the scrolling speedometer test.
  • Loading branch information
ToddGrun authored Oct 30, 2024
1 parent 5ab7f5b commit 308cda3
Showing 1 changed file with 14 additions and 3 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ internal class CSharpVirtualCharService : AbstractVirtualCharService
{
public static readonly IVirtualCharService Instance = new CSharpVirtualCharService();

private static readonly ObjectPool<ImmutableSegmentedList<VirtualChar>.Builder> s_pooledBuilders = new(() => ImmutableSegmentedList.CreateBuilder<VirtualChar>());

protected CSharpVirtualCharService()
{
}
Expand Down Expand Up @@ -285,11 +287,20 @@ private static VirtualCharSequence CreateVirtualCharSequence(
string tokenText, int offset, int startIndexInclusive, int endIndexExclusive, ArrayBuilder<(char ch, TextSpan span)> charResults)
{
// Second pass. Convert those characters to Runes.
var runeResults = ImmutableSegmentedList.CreateBuilder<VirtualChar>();
using var pooledRuneResults = s_pooledBuilders.GetPooledObject();
var runeResults = pooledRuneResults.Object;

ConvertCharactersToRunes(charResults, runeResults);
try
{
ConvertCharactersToRunes(charResults, runeResults);

return CreateVirtualCharSequence(tokenText, offset, startIndexInclusive, endIndexExclusive, runeResults);
return CreateVirtualCharSequence(tokenText, offset, startIndexInclusive, endIndexExclusive, runeResults);
}
finally
{
// Ensure the builder is cleared out before releasing back to the pool.
runeResults.Clear();
}
}

private static void ConvertCharactersToRunes(ArrayBuilder<(char ch, TextSpan span)> charResults, ImmutableSegmentedList<VirtualChar>.Builder runeResults)
Expand Down

0 comments on commit 308cda3

Please sign in to comment.