object pool
using System;
using System.Collections.Concurrent;
using System.Threading;
namespace test
{
/// <summary>
/// object pool
/// </summary>
/// <typeparam name="T"></typeparam>
public class ObjectPool<T>
where T : new()
{
// 초기 생성된 item 수
public int ItemCountInit { get; private set; }
// 현재 보유하고 있는 item 수
public int ItemCountIdle => _bag.Count;
// 전체 item 수 (사용중인 수 + idle 수)
private int _itemCountTotal;
public int ItemCountTotal => _itemCountTotal;
// item 생성 Func
private readonly Func<T> _createFunc;
private readonly ConcurrentBag<T> _bag = new ConcurrentBag<T>();
public ObjectPool(int initItemCount)
: this(initItemCount, null)
{
}
public ObjectPool(int initItemCount, Func<T> createFunc)
{
ItemCountInit = initItemCount;
_createFunc = createFunc;
for (int i = 0; i < ItemCountInit; i++)
{
_bag.Add(CreateItem());
}
}
// rent object
public T Rent()
{
return _bag.TryTake(out T item) ? item : CreateItem();
}
// return object
public void Return(T item)
{
_bag.Add(item);
}
private T CreateItem()
{
T item = (_createFunc is null) ? new T() : _createFunc();
Interlocked.Increment(ref _itemCountTotal);
return item;
}
public override string ToString()
{
return $"Total: {ItemCountTotal}, Idle: {ItemCountIdle}, Init: {ItemCountInit}";
}
}
}
object type pool
using System;
using System.Collections.Concurrent;
using System.Text;
namespace test
{
/// <summary>
/// type 별 object pool
/// </summary>
public class ObjectTypePool
{
// key: class type, value: object pool
private readonly ConcurrentDictionary<Type, ObjectPool<object>> _pool = new ConcurrentDictionary<Type, ObjectPool<object>>();
// type 별 미리 생성할 object 개수 설정
private readonly int _initItemCountPerType;
public ObjectTypePool() { }
public ObjectTypePool(int initItemCountPerType, params Type[] types)
{
_initItemCountPerType = initItemCountPerType;
foreach (Type type in types)
{
_pool.TryAdd(type, CreateSubPool(type));
}
}
// rent object
public T Rent<T>()
{
return (T)GetOrAdd(typeof(T)).Rent();
}
// return object
public void Return<T>(T item)
{
GetOrAdd(item.GetType()).Return(item);
}
private ObjectPool<object> GetOrAdd(Type type)
{
return _pool.GetOrAdd(type, (type) => CreateSubPool(type));
}
private ObjectPool<object> CreateSubPool(Type type)
{
lock (_pool)
{
if (_pool.TryGetValue(type, out ObjectPool<object> value))
{
return value;
}
return new ObjectPool<object>(
_initItemCountPerType,
() => Activator.CreateInstance(type)
);
}
}
public override string ToString()
{
StringBuilder sb = new StringBuilder();
foreach (var kv in _pool)
{
Type type = kv.Key;
ObjectPool<object> subPool = kv.Value;
sb.Append($"[{type.Name}: {subPool}]");
}
return sb.ToString();
}
}
}
test
using System;
namespace test_pool.Pool
{
public class Item { }
public class ItemA : Item { }
public class ItemB : Item { }
public interface IItemStruct { }
public struct ItemStructA : IItemStruct { }
public struct ItemStructB : IItemStruct { }
class TestPool
{
public void Test()
{
TestObjectPool();
TestObjectTypePool();
}
public void TestObjectPool()
{
//var pool = new ObjectPool<DataClass>(100, () => new DataClass());
var pool = new ObjectPool<DataClass>(100);
var item = pool.Rent();
Console.WriteLine(pool);
pool.Return(item);
Console.WriteLine(pool);
}
public void TestObjectTypePool()
{
var pool = new ObjectTypePool();
var r = pool.Rent<Item>();
pool.Return(r);
Console.WriteLine(pool);
var a = pool.Rent<ItemA>();
pool.Return(a);
Console.WriteLine(pool);
var b = pool.Rent<ItemB>();
pool.Return(b);
Console.WriteLine(pool);
var sa = pool.Rent<ItemStructA>();
pool.Return(sa);
Console.WriteLine(pool);
var sb = pool.Rent<ItemStructB>();
pool.Return(sb);
Console.WriteLine(pool);
}
}
}
'C#' 카테고리의 다른 글
c# DebuggerDisplay, DebuggerTypeProxy attribute (0) | 2022.03.16 |
---|---|
c# method attribute 의 값을 해당 메소드에서 가져오기 (0) | 2022.03.15 |
c# HttpClient (0) | 2022.03.15 |
c# channel (0) | 2022.03.15 |
GC TEST (0) | 2022.03.08 |
GC EventPipe 모니터링 (0) | 2022.03.08 |
C# .net core 빌드 및 powershell 전송 (0) | 2022.03.01 |
c# stack size 확인 (0) | 2022.02.24 |