diff options
Diffstat (limited to 'ARMeilleure/Common/ThreadStaticPool.cs')
| -rw-r--r-- | ARMeilleure/Common/ThreadStaticPool.cs | 82 |
1 files changed, 50 insertions, 32 deletions
diff --git a/ARMeilleure/Common/ThreadStaticPool.cs b/ARMeilleure/Common/ThreadStaticPool.cs index 3fce28ec..e23bf1dc 100644 --- a/ARMeilleure/Common/ThreadStaticPool.cs +++ b/ARMeilleure/Common/ThreadStaticPool.cs @@ -1,13 +1,13 @@ using System; using System.Collections.Concurrent; using System.Collections.Generic; -using System.Threading; namespace ARMeilleure.Common { class ThreadStaticPool<T> where T : class, new() { - private const int PoolSizeIncrement = 200; + private const int ChunkSizeLimit = 1000; // even + private const int PoolSizeIncrement = 200; // > 0 [ThreadStatic] private static ThreadStaticPool<T> _instance; @@ -25,11 +25,11 @@ namespace ARMeilleure.Common } } - private static ConcurrentDictionary<int, Stack<ThreadStaticPool<T>>> _pools = new ConcurrentDictionary<int, Stack<ThreadStaticPool<T>>>(); + private static ConcurrentDictionary<int, Stack<ThreadStaticPool<T>>> _pools = new(); private static Stack<ThreadStaticPool<T>> GetPools(int groupId) { - return _pools.GetOrAdd(groupId, x => new Stack<ThreadStaticPool<T>>()); + return _pools.GetOrAdd(groupId, (groupId) => new()); } public static void PreparePool(int groupId) @@ -41,19 +41,20 @@ namespace ARMeilleure.Common var pools = GetPools(groupId); lock (pools) { - _instance = (pools.Count != 0) ? pools.Pop() : new ThreadStaticPool<T>(PoolSizeIncrement * 2); + _instance = (pools.Count != 0) ? pools.Pop() : new(); } } } public static void ReturnPool(int groupId) { - // Reset and return the pool for this thread to the specified group. + // Reset, limit if necessary, and return the pool for this thread to the specified group. var pools = GetPools(groupId); lock (pools) { _instance.Clear(); + _instance.ChunkSizeLimiter(); pools.Push(_instance); _instance = null; @@ -66,58 +67,75 @@ namespace ARMeilleure.Common foreach (var pools in _pools.Values) { + foreach (var instance in pools) + { + instance.Dispose(); + } + pools.Clear(); } _pools.Clear(); } - private T[] _pool; - private int _poolUsed = -1; - private int _poolSize; + private List<T[]> _pool; + private int _chunkIndex = -1; + private int _poolIndex = -1; - public ThreadStaticPool(int initialSize) + private ThreadStaticPool() { - _pool = new T[initialSize]; - - for (int i = 0; i < initialSize; i++) - { - _pool[i] = new T(); - } + _pool = new(ChunkSizeLimit * 2); - _poolSize = initialSize; + AddChunkIfNeeded(); } public T Allocate() { - int index = Interlocked.Increment(ref _poolUsed); - - if (index >= _poolSize) + if (++_poolIndex >= PoolSizeIncrement) { - IncreaseSize(); + AddChunkIfNeeded(); + + _poolIndex = 0; } - return _pool[index]; + return _pool[_chunkIndex][_poolIndex]; } - private void IncreaseSize() + private void AddChunkIfNeeded() { - _poolSize += PoolSizeIncrement; + if (++_chunkIndex >= _pool.Count) + { + T[] pool = new T[PoolSizeIncrement]; + + for (int i = 0; i < PoolSizeIncrement; i++) + { + pool[i] = new T(); + } - T[] newArray = new T[_poolSize]; - Array.Copy(_pool, 0, newArray, 0, _pool.Length); + _pool.Add(pool); + } + } - for (int i = _pool.Length; i < _poolSize; i++) + public void Clear() + { + _chunkIndex = 0; + _poolIndex = -1; + } + + private void ChunkSizeLimiter() + { + if (_pool.Count >= ChunkSizeLimit) { - newArray[i] = new T(); - } + int newChunkSize = ChunkSizeLimit / 2; - Interlocked.Exchange(ref _pool, newArray); + _pool.RemoveRange(newChunkSize, _pool.Count - newChunkSize); + _pool.Capacity = ChunkSizeLimit * 2; + } } - public void Clear() + private void Dispose() { - _poolUsed = -1; + _pool.Clear(); } } } |
