ObjectPool - это тип, используемый в компиляторе Roslyn С# для повторного использования часто используемых объектов, которые обычно получают новые и мусорные собранных очень часто. Это уменьшает количество и размер операций по сбору мусора, которые должны произойти.
У компилятора Roslyn, похоже, есть несколько отдельных пулов объектов, и каждый пул имеет другой размер. Я хочу знать, почему существует так много реализаций, какая предпочтительная реализация и почему они выбрали размер пула 20, 100 или 128.
1 - SharedPools - Сохраняет пул из 20 объектов или 100, если используется BigDefault. Это также странно, потому что он создает новый экземпляр PooledObject, который не имеет смысла, когда мы пытаемся объединить объекты, а не создавать и уничтожать новые.
// Example 1 - In a using statement, so the object gets freed at the end.
using (PooledObject<Foo> pooledObject = SharedPools.Default<List<Foo>>().GetPooledObject())
{
// Do something with pooledObject.Object
}
// Example 2 - No using statement so you need to be sure no exceptions are not thrown.
List<Foo> list = SharedPools.Default<List<Foo>>().AllocateAndClear();
// Do something with list
SharedPools.Default<List<Foo>>().Free(list);
// Example 3 - I have also seen this variation of the above pattern, which ends up the same as Example 1, except Example 1 seems to create a new instance of the IDisposable [PooledObject<T>][3] object. This is probably the preferred option if you want fewer GC's.
List<Foo> list = SharedPools.Default<List<Foo>>().AllocateAndClear();
try
{
// Do something with list
}
finally
{
SharedPools.Default<List<Foo>>().Free(list);
}
2 - ListPool и StringBuilderPool - Не строго отдельные реализации, а оболочки вокруг реализации SharedPools, показанные выше, специально для List и StringBuilder. Таким образом, это повторно использует пул объектов, хранящихся в SharedPools.
// Example 1 - No using statement so you need to be sure no exceptions are thrown.
StringBuilder stringBuilder= StringBuilderPool.Allocate();
// Do something with stringBuilder
StringBuilderPool.Free(stringBuilder);
// Example 2 - Safer version of Example 1.
StringBuilder stringBuilder= StringBuilderPool.Allocate();
try
{
// Do something with stringBuilder
}
finally
{
StringBuilderPool.Free(stringBuilder);
}
3 - PooledDictionary и PooledHashSet - Они используют ObjectPool напрямую и имеют совершенно отдельный пул объектов. Сохраняет пул из 128 объектов.
// Example 1
PooledHashSet<Foo> hashSet = PooledHashSet<Foo>.GetInstance()
// Do something with hashSet.
hashSet.Free();
// Example 2 - Safer version of Example 1.
PooledHashSet<Foo> hashSet = PooledHashSet<Foo>.GetInstance()
try
{
// Do something with hashSet.
}
finally
{
hashSet.Free();
}
Update
В .NET Core реализованы новые реализации пула объектов. См. Мой ответ для вопроса С# Object Pooling Pattern.