object pool, object type pool

C# 2022. 3. 11. 12:25

 

 

 

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