Add improved API for object pools

This commit is contained in:
Dustin Campbell 2022-11-23 17:23:11 -08:00
Родитель fe4bd081b7
Коммит 1c085fcbc3
31 изменённых файлов: 129 добавлений и 69 удалений

Просмотреть файл

@ -19,4 +19,7 @@ internal static class ArrayBuilderPool<T>
public static PooledObject<ImmutableArray<T>.Builder> GetPooledObject()
=> DefaultPool.GetPooledObject();
public static PooledObject<ImmutableArray<T>.Builder> GetPooledObject(out ImmutableArray<T>.Builder builder)
=> DefaultPool.GetPooledObject(out builder);
}

Просмотреть файл

@ -20,4 +20,7 @@ internal static class DictionaryPool<TKey, TValue>
public static PooledObject<Dictionary<TKey, TValue>> GetPooledObject()
=> DefaultPool.GetPooledObject();
public static PooledObject<Dictionary<TKey, TValue>> GetPooledObject(out Dictionary<TKey, TValue> map)
=> DefaultPool.GetPooledObject(out map);
}

Просмотреть файл

@ -19,4 +19,7 @@ internal static class HashSetPool<T>
public static PooledObject<HashSet<T>> GetPooledObject()
=> DefaultPool.GetPooledObject();
public static PooledObject<HashSet<T>> GetPooledObject(out HashSet<T> set)
=> DefaultPool.GetPooledObject(out set);
}

Просмотреть файл

@ -19,4 +19,7 @@ internal static class ListPool<T>
public static PooledObject<List<T>> GetPooledObject()
=> DefaultPool.GetPooledObject();
public static PooledObject<List<T>> GetPooledObject(out List<T> list)
=> DefaultPool.GetPooledObject(out list);
}

Просмотреть файл

@ -15,22 +15,86 @@ internal static partial class PooledObject
public static PooledObject<ImmutableArray<T>.Builder> GetPooledObject<T>(this ObjectPool<ImmutableArray<T>.Builder> pool)
=> new(pool, ArrayBuilderFuncs<T>.Allocate, ArrayBuilderFuncs<T>.Release);
public static PooledObject<ImmutableArray<T>.Builder> GetPooledObject<T>(
this ObjectPool<ImmutableArray<T>.Builder> pool,
out ImmutableArray<T>.Builder builder)
{
var pooledObject = pool.GetPooledObject();
builder = pooledObject.Object;
return pooledObject;
}
public static PooledObject<Dictionary<TKey, TValue>> GetPooledObject<TKey, TValue>(this ObjectPool<Dictionary<TKey, TValue>> pool)
where TKey : notnull
=> new(pool, DictionaryFuncs<TKey, TValue>.Allocate, DictionaryFuncs<TKey, TValue>.Release);
public static PooledObject<Dictionary<TKey, TValue>> GetPooledObject<TKey, TValue>(
this ObjectPool<Dictionary<TKey, TValue>> pool,
out Dictionary<TKey, TValue> map)
where TKey : notnull
{
var pooledObject = pool.GetPooledObject();
map = pooledObject.Object;
return pooledObject;
}
public static PooledObject<HashSet<T>> GetPooledObject<T>(this ObjectPool<HashSet<T>> pool)
=> new(pool, HashSetFuncs<T>.Allocate, HashSetFuncs<T>.Release);
public static PooledObject<HashSet<T>> GetPooledObject<T>(
this ObjectPool<HashSet<T>> pool,
out HashSet<T> set)
{
var pooledObject = pool.GetPooledObject();
set = pooledObject.Object;
return pooledObject;
}
public static PooledObject<List<T>> GetPooledObject<T>(this ObjectPool<List<T>> pool)
=> new(pool, ListFuncs<T>.Allocate, ListFuncs<T>.Release);
public static PooledObject<List<T>> GetPooledObject<T>(
this ObjectPool<List<T>> pool,
out List<T> list)
{
var pooledObject = pool.GetPooledObject();
list = pooledObject.Object;
return pooledObject;
}
public static PooledObject<Stack<T>> GetPooledObject<T>(this ObjectPool<Stack<T>> pool)
=> new(pool, StackFuncs<T>.Allocate, StackFuncs<T>.Release);
public static PooledObject<Stack<T>> GetPooledObject<T>(
this ObjectPool<Stack<T>> pool,
out Stack<T> stack)
{
var pooledObject = pool.GetPooledObject();
stack = pooledObject.Object;
return pooledObject;
}
public static PooledObject<Stopwatch> GetPooledObject(this ObjectPool<Stopwatch> pool)
=> new(pool, StopwatchFuncs.Allocate, StopwatchFuncs.Release);
public static PooledObject<Stopwatch> GetPooledObject(
this ObjectPool<Stopwatch> pool,
out Stopwatch watch)
{
var pooledObject = pool.GetPooledObject();
watch = pooledObject.Object;
return pooledObject;
}
public static PooledObject<StringBuilder> GetPooledObject(this ObjectPool<StringBuilder> pool)
=> new(pool, StringBuilderFuncs.Allocate, StringBuilderFuncs.Release);
public static PooledObject<StringBuilder> GetPooledObject(
this ObjectPool<StringBuilder> pool,
out StringBuilder builder)
{
var pooledObject = pool.GetPooledObject();
builder = pooledObject.Object;
return pooledObject;
}
}

Просмотреть файл

@ -21,4 +21,7 @@ internal static class ReferenceEqualityHashSetPool<T>
ObjectPool.Default(() => new HashSet<T>(ReferenceEqualityComparer<T>.Instance));
public static PooledObject<HashSet<T>> GetPooledObject() => DefaultPool.GetPooledObject();
public static PooledObject<HashSet<T>> GetPooledObject(out HashSet<T> set)
=> DefaultPool.GetPooledObject(out set);
}

Просмотреть файл

@ -18,4 +18,7 @@ internal static class StackPool<T>
public static readonly ObjectPool<Stack<T>> DefaultPool = ObjectPool.Default<Stack<T>>();
public static PooledObject<Stack<T>> GetPooledObject() => DefaultPool.GetPooledObject();
public static PooledObject<Stack<T>> GetPooledObject(out Stack<T> stack)
=> DefaultPool.GetPooledObject(out stack);
}

Просмотреть файл

@ -19,4 +19,7 @@ internal static class StopwatchPool
public static PooledObject<Stopwatch> GetPooledObject()
=> DefaultPool.GetPooledObject();
public static PooledObject<Stopwatch> GetPooledObject(out Stopwatch watch)
=> DefaultPool.GetPooledObject(out watch);
}

Просмотреть файл

@ -19,4 +19,7 @@ internal static class StringBuilderPool
public static PooledObject<StringBuilder> GetPooledObject()
=> DefaultPool.GetPooledObject();
public static PooledObject<StringBuilder> GetPooledObject(out StringBuilder builder)
=> DefaultPool.GetPooledObject(out builder);
}

Просмотреть файл

@ -23,6 +23,10 @@ internal static class StringDictionaryPool<TValue>
public static PooledObject<Dictionary<string, TValue>> GetPooledObject()
=> DefaultPool.GetPooledObject();
public static PooledObject<Dictionary<string, TValue>> GetPooledObject(out Dictionary<string, TValue> map)
=> DefaultPool.GetPooledObject(out map);
}
public static class OrdinalIgnoreCase
@ -32,5 +36,8 @@ internal static class StringDictionaryPool<TValue>
public static PooledObject<Dictionary<string, TValue>> GetPooledObject()
=> DefaultPool.GetPooledObject();
public static PooledObject<Dictionary<string, TValue>> GetPooledObject(out Dictionary<string, TValue> map)
=> DefaultPool.GetPooledObject(out map);
}
}

Просмотреть файл

@ -165,8 +165,7 @@ internal class TextDocumentUriPresentationEndpoint : AbstractTextDocumentPresent
// TODO: Add @using statements if required, or fully qualify (GetTypeName())
using var pooledBuilder = StringBuilderPool.GetPooledObject();
var sb = pooledBuilder.Object;
using var _ = StringBuilderPool.GetPooledObject(out var sb);
sb.Append('<');
sb.Append(typeName);

Просмотреть файл

@ -401,8 +401,7 @@ internal class CSharpOnTypeFormattingPass : CSharpFormattingPassBase
private static string PrependLines(string text, string newLine, int count)
{
using var pooledBuilder = StringBuilderPool.GetPooledObject();
var builder = pooledBuilder.Object;
using var _ = StringBuilderPool.GetPooledObject(out var builder);
var capacity = (newLine.Length * count) + text.Length;

Просмотреть файл

@ -85,8 +85,7 @@ internal class SourceTextDiffer : TextDiffer
var start = 0;
var end = 0;
using var pooledBuilder = StringBuilderPool.GetPooledObject();
var builder = pooledBuilder.Object;
using var _ = StringBuilderPool.GetPooledObject(out var builder);
foreach (var edit in edits)
{

Просмотреть файл

@ -37,8 +37,7 @@ internal class DefaultLSPTagHelperTooltipFactory : LSPTagHelperTooltipFactory
//
// Additional description infos result in a triple `---` to separate the markdown entries.
using var pooledBuilder = StringBuilderPool.GetPooledObject();
var descriptionBuilder = pooledBuilder.Object;
using var _ = StringBuilderPool.GetPooledObject(out var descriptionBuilder);
for (var i = 0; i < associatedTagHelperInfos.Count; i++)
{
@ -101,8 +100,7 @@ internal class DefaultLSPTagHelperTooltipFactory : LSPTagHelperTooltipFactory
//
// Additional description infos result in a triple `---` to separate the markdown entries.
using var pooledBuilder = StringBuilderPool.GetPooledObject();
var descriptionBuilder = pooledBuilder.Object;
using var _ = StringBuilderPool.GetPooledObject(out var descriptionBuilder);
for (var i = 0; i < associatedAttributeInfos.Count; i++)
{
@ -163,8 +161,7 @@ internal class DefaultLSPTagHelperTooltipFactory : LSPTagHelperTooltipFactory
summaryContent = summaryContent.Trim();
var crefMatches = ExtractCrefMatches(summaryContent);
using var pooledBuilder = StringBuilderPool.GetPooledObject();
var summaryBuilder = pooledBuilder.Object;
using var _ = StringBuilderPool.GetPooledObject(out var summaryBuilder);
summaryBuilder.Append(summaryContent);

Просмотреть файл

@ -244,8 +244,7 @@ internal class DefaultVSLSPTagHelperTooltipFactory : VSLSPTagHelperTooltipFactor
private static void ClassifyReducedTypeName(List<ClassifiedTextRun> runs, string reducedTypeName)
{
using var pooledBuilder = StringBuilderPool.GetPooledObject();
var currentTextRun = pooledBuilder.Object;
using var _ = StringBuilderPool.GetPooledObject(out var currentTextRun);
for (var i = 0; i < reducedTypeName.Length; i++)
{
@ -355,8 +354,7 @@ internal class DefaultVSLSPTagHelperTooltipFactory : VSLSPTagHelperTooltipFactor
return;
}
using var pooledBuilder = StringBuilderPool.GetPooledObject();
var currentTextRun = pooledBuilder.Object;
using var _ = StringBuilderPool.GetPooledObject(out var currentTextRun);
var currentCrefMatchIndex = 0;
var currentCodeMatchIndex = 0;

Просмотреть файл

@ -27,8 +27,7 @@ public class ObjectPoolTests : TestBase
Assert.Equal(0, accessor.UsedSlotCount);
// Acquire a StringBuilder.
var pooledBuilder = StringBuilderPool.GetPooledObject();
var builder = pooledBuilder.Object;
var pooledBuilder = StringBuilderPool.GetPooledObject(out var builder);
// Verify that the pool is still empty.
Assert.Equal(0, accessor.UsedSlotCount);
@ -52,8 +51,7 @@ public class ObjectPoolTests : TestBase
Assert.Same(builder, accessor[0]);
// Acquire another StringBuilder.
var pooledBuilder2 = StringBuilderPool.GetPooledObject();
var builder2 = pooledBuilder2.Object;
var pooledBuilder2 = StringBuilderPool.GetPooledObject(out var builder2);
Assert.Equal(0, accessor.UsedSlotCount);
@ -84,12 +82,9 @@ public class ObjectPoolTests : TestBase
StringBuilder builder1, builder2;
using (var pooledBuilder1 = StringBuilderPool.GetPooledObject())
using (StringBuilderPool.GetPooledObject(out builder1))
using (StringBuilderPool.GetPooledObject(out builder2))
{
builder1 = pooledBuilder1.Object;
using var pooledBuilder2 = StringBuilderPool.GetPooledObject();
builder2 = pooledBuilder2.Object;
}
Assert.Equal(2, accessor.UsedSlotCount);

Просмотреть файл

@ -160,8 +160,7 @@ public abstract class SemanticTokenTestBase : TagHelperServiceTestBase
private static void GenerateSemanticBaseline(IEnumerable<int>? actual, string baselineFileName)
{
using var pooledBuilder = StringBuilderPool.GetPooledObject();
var builder = pooledBuilder.Object;
using var _ = StringBuilderPool.GetPooledObject(out var builder);
if (actual != null)
{

Просмотреть файл

@ -28,8 +28,7 @@ public class CompilationFailedException : XunitException
{
get
{
using var pooledBuilder = StringBuilderPool.GetPooledObject();
var builder = pooledBuilder.Object;
using var _ = StringBuilderPool.GetPooledObject(out var builder);
builder.AppendLine("Compilation failed: ");

Просмотреть файл

@ -242,8 +242,7 @@ public static class IntermediateNodeVerifier
private static string Format(IntermediateNode[] ancestors, string expected, string actual, string userMessage)
{
using var pooledBuilder = StringBuilderPool.GetPooledObject();
var builder = pooledBuilder.Object;
using var _ = StringBuilderPool.GetPooledObject(out var builder);
builder.AppendLine(userMessage);
builder.AppendLine();

Просмотреть файл

@ -398,8 +398,7 @@ public class RazorIntegrationTestBase : TestBase
{
get
{
using var pooledBuilder = StringBuilderPool.GetPooledObject();
var builder = pooledBuilder.Object;
using var _ = StringBuilderPool.GetPooledObject(out var builder);
builder.AppendLine("Compilation failed: ");

Просмотреть файл

@ -12,8 +12,7 @@ public static class SourceMappingsSerializer
{
public static string Serialize(RazorCSharpDocument csharpDocument, RazorSourceDocument sourceDocument)
{
using var pooledBuilder = StringBuilderPool.GetPooledObject();
var builder = pooledBuilder.Object;
using var _ = StringBuilderPool.GetPooledObject(out var builder);
var charBuffer = new char[sourceDocument.Length];
sourceDocument.CopyTo(0, charBuffer, 0, sourceDocument.Length);

Просмотреть файл

@ -100,8 +100,7 @@ public static class IntermediateNodeAssert
{
var html = Assert.IsType<HtmlContentIntermediateNode>(node);
using var pooledBuilder = StringBuilderPool.GetPooledObject();
var content = pooledBuilder.Object;
using var _ = StringBuilderPool.GetPooledObject(out var content);
for (var i = 0; i < html.Children.Count; i++)
{
@ -124,8 +123,7 @@ public static class IntermediateNodeAssert
{
var statement = Assert.IsType<CSharpCodeIntermediateNode>(node);
using var pooledBuilder = StringBuilderPool.GetPooledObject();
var content = pooledBuilder.Object;
using var _ = StringBuilderPool.GetPooledObject(out var content);
for (var i = 0; i < statement.Children.Count; i++)
{
@ -213,8 +211,7 @@ public static class IntermediateNodeAssert
try
{
using var pooledBuilder = StringBuilderPool.GetPooledObject();
var content = pooledBuilder.Object;
using var _ = StringBuilderPool.GetPooledObject(out var content);
for (var i = 0; i < attributeValue.Children.Count; i++)
{
@ -238,8 +235,7 @@ public static class IntermediateNodeAssert
try
{
using var pooledBuilder = StringBuilderPool.GetPooledObject();
var content = pooledBuilder.Object;
using var _ = StringBuilderPool.GetPooledObject(out var content);
for (var i = 0; i < attributeValue.Children.Count; i++)
{
@ -263,8 +259,7 @@ public static class IntermediateNodeAssert
{
var cSharp = Assert.IsType<CSharpExpressionIntermediateNode>(node);
using var pooledBuilder = StringBuilderPool.GetPooledObject();
var content = pooledBuilder.Object;
using var _ = StringBuilderPool.GetPooledObject(out var content);
for (var i = 0; i < cSharp.Children.Count; i++)
{
@ -287,8 +282,7 @@ public static class IntermediateNodeAssert
{
var beginNode = Assert.IsType<CSharpCodeIntermediateNode>(node);
using var pooledBuilder = StringBuilderPool.GetPooledObject();
var content = pooledBuilder.Object;
using var _ = StringBuilderPool.GetPooledObject(out var content);
for (var i = 0; i < beginNode.Children.Count; i++)
{
@ -311,8 +305,7 @@ public static class IntermediateNodeAssert
{
var endNode = Assert.IsType<CSharpCodeIntermediateNode>(node);
using var pooledBuilder = StringBuilderPool.GetPooledObject();
var content = pooledBuilder.Object;
using var _ = StringBuilderPool.GetPooledObject(out var content);
for (var i = 0; i < endNode.Children.Count; i++)
{
@ -476,8 +469,7 @@ public static class IntermediateNodeAssert
private static string Format(IntermediateNode[] ancestors, IEnumerable<IntermediateNode> nodes, string userMessage)
{
using var pooledBuilder = StringBuilderPool.GetPooledObject();
var builder = pooledBuilder.Object;
using var _ = StringBuilderPool.GetPooledObject(out var builder);
builder.AppendLine(userMessage);
builder.AppendLine();

Просмотреть файл

@ -90,8 +90,7 @@ internal class ClassifiedSpanVerifier
private static string Format(string expected, string actual, string userMessage)
{
using var pooledBuilder = StringBuilderPool.GetPooledObject();
var builder = pooledBuilder.Object;
using var _ = StringBuilderPool.GetPooledObject(out var builder);
builder.AppendLine(userMessage);
builder.AppendLine();

Просмотреть файл

@ -263,8 +263,7 @@ public static class SyntaxNodeVerifier
private static string Format(SyntaxNode[] ancestors, string expected, string actual, string userMessage)
{
using var pooledBuilder = StringBuilderPool.GetPooledObject();
var builder = pooledBuilder.Object;
using var _ = StringBuilderPool.GetPooledObject(out var builder);
builder.AppendLine(userMessage);
builder.AppendLine();

Просмотреть файл

@ -114,8 +114,7 @@ internal class SyntaxNodeWriter : SyntaxRewriter
return;
}
using var pooledBuilder = StringBuilderPool.GetPooledObject();
var builder = pooledBuilder.Object;
using var _ = StringBuilderPool.GetPooledObject(out var builder);
builder.Append("Directive:{");
builder.Append(node.DirectiveDescriptor.Directive);

Просмотреть файл

@ -90,8 +90,7 @@ internal class TagHelperSpanVerifier
private static string Format(string expected, string actual, string userMessage)
{
using var pooledBuilder = StringBuilderPool.GetPooledObject();
var builder = pooledBuilder.Object;
using var _ = StringBuilderPool.GetPooledObject(out var builder);
builder.AppendLine(userMessage);
builder.AppendLine();

Просмотреть файл

@ -225,8 +225,7 @@ public HostServices GetHostServices()
{
var configuration = CompositionConfiguration.Create(GetCatalog());
using var pooledBuilder = StringBuilderPool.GetPooledObject();
var sb = pooledBuilder.Object;
using var _ = StringBuilderPool.GetPooledObject(out var sb);
foreach (var errorGroup in configuration.CompositionErrors)
{

Просмотреть файл

@ -93,8 +93,7 @@ public class CodeFoldingTests : AbstractRazorEditorTest
static string PrintLines(ImmutableArray<CollapsibleBlock> lines, ITextView textView)
{
using var pooledBuilder = StringBuilderPool.GetPooledObject();
var sb = pooledBuilder.Object;
using var _ = StringBuilderPool.GetPooledObject(out var sb);
foreach (var line in lines)
{

Просмотреть файл

@ -69,8 +69,7 @@ internal partial class EditorInProcess
{
var hoverContent = await HoverAsync(position, cancellationToken);
using var pooledBuilder = StringBuilderPool.GetPooledObject();
var sb = pooledBuilder.Object;
using var _ = StringBuilderPool.GetPooledObject(out var sb);
TraverseContent(hoverContent, sb);
return sb.ToString();

Просмотреть файл

@ -143,8 +143,7 @@ public class RazorSemanticTokensTests : AbstractRazorEditorTest
private static void GenerateSemanticBaseline(IEnumerable<ClassificationSpan> actual, string baselineFileName)
{
using var pooledBuilder = StringBuilderPool.GetPooledObject();
var builder = pooledBuilder.Object;
using var _ = StringBuilderPool.GetPooledObject(out var builder);
foreach (var baseline in actual)
{

Просмотреть файл

@ -99,8 +99,7 @@ internal static class VisualStudioLogging
{
var hiveDirectory = GetHiveDirectory();
using var pooledBuilder = StringBuilderPool.GetPooledObject();
var fileBuilder = pooledBuilder.Object;
using var _ = StringBuilderPool.GetPooledObject(out var fileBuilder);
var extensionsDir = Path.Combine(hiveDirectory, "Extensions");
var compatListFile = Path.Combine(extensionsDir, "CompatibilityList.xml");