diff options
Diffstat (limited to 'ARMeilleure/Common')
| -rw-r--r-- | ARMeilleure/Common/BitMap.cs | 4 | ||||
| -rw-r--r-- | ARMeilleure/Common/BitMapPool.cs | 24 | ||||
| -rw-r--r-- | ARMeilleure/Common/ThreadStaticPool.cs | 124 | ||||
| -rw-r--r-- | ARMeilleure/Common/ThreadStaticPoolEnums.cs | 14 |
4 files changed, 137 insertions, 29 deletions
diff --git a/ARMeilleure/Common/BitMap.cs b/ARMeilleure/Common/BitMap.cs index b1c9a673..f782ac8b 100644 --- a/ARMeilleure/Common/BitMap.cs +++ b/ARMeilleure/Common/BitMap.cs @@ -35,7 +35,7 @@ namespace ARMeilleure.Common } } - public void Reset(int initialCapacity) + public BitMap Reset(int initialCapacity) { int count = (initialCapacity + IntMask) / IntSize; @@ -50,6 +50,8 @@ namespace ARMeilleure.Common { _masks.Add(0); } + + return this; } public bool Set(int bit) diff --git a/ARMeilleure/Common/BitMapPool.cs b/ARMeilleure/Common/BitMapPool.cs index aac32d55..d8d297fa 100644 --- a/ARMeilleure/Common/BitMapPool.cs +++ b/ARMeilleure/Common/BitMapPool.cs @@ -4,15 +4,29 @@ { public static BitMap Allocate(int initialCapacity) { - BitMap result = ThreadStaticPool<BitMap>.Instance.Allocate(); - result.Reset(initialCapacity); + return BitMap().Reset(initialCapacity); + } + + #region "ThreadStaticPool" + public static void PrepareBitMapPool(int groupId = 0) + { + ThreadStaticPool<BitMap>.PreparePool(groupId, ChunkSizeLimit.Small); + } - return result; + private static BitMap BitMap() + { + return ThreadStaticPool<BitMap>.Instance.Allocate(); + } + + public static void ResetBitMapPool(int groupId = 0) + { + ThreadStaticPool<BitMap>.ResetPool(groupId); } - public static void Release() + public static void DisposeBitMapPools() { - ThreadStaticPool<BitMap>.Instance.Clear(); + ThreadStaticPool<BitMap>.DisposePools(); } + #endregion } } diff --git a/ARMeilleure/Common/ThreadStaticPool.cs b/ARMeilleure/Common/ThreadStaticPool.cs index e23bf1dc..bbe662f8 100644 --- a/ARMeilleure/Common/ThreadStaticPool.cs +++ b/ARMeilleure/Common/ThreadStaticPool.cs @@ -1,4 +1,5 @@ -using System; +using ARMeilleure.Translation.PTC; +using System; using System.Collections.Concurrent; using System.Collections.Generic; @@ -6,9 +7,6 @@ namespace ARMeilleure.Common { class ThreadStaticPool<T> where T : class, new() { - private const int ChunkSizeLimit = 1000; // even - private const int PoolSizeIncrement = 200; // > 0 - [ThreadStatic] private static ThreadStaticPool<T> _instance; @@ -18,21 +16,36 @@ namespace ARMeilleure.Common { if (_instance == null) { - PreparePool(0); // So that we can still use a pool when blindly initializing one. + PreparePool(); // So that we can still use a pool when blindly initializing one. } return _instance; } } - private static ConcurrentDictionary<int, Stack<ThreadStaticPool<T>>> _pools = new(); + private static readonly ConcurrentDictionary<int, Stack<ThreadStaticPool<T>>> _pools = new(); private static Stack<ThreadStaticPool<T>> GetPools(int groupId) { return _pools.GetOrAdd(groupId, (groupId) => new()); } - public static void PreparePool(int groupId) + public static void PreparePool( + int groupId = 0, + ChunkSizeLimit chunkSizeLimit = ChunkSizeLimit.Large, + PoolSizeIncrement poolSizeIncrement = PoolSizeIncrement.Default) + { + if (Ptc.State == PtcState.Disabled) + { + PreparePoolDefault(groupId, (int)chunkSizeLimit, (int)poolSizeIncrement); + } + else + { + PreparePoolSlim((int)chunkSizeLimit, (int)poolSizeIncrement); + } + } + + private static void PreparePoolDefault(int groupId, int chunkSizeLimit, int poolSizeIncrement) { // Prepare the pool for this thread, ideally using an existing one from the specified group. @@ -41,27 +54,75 @@ namespace ARMeilleure.Common var pools = GetPools(groupId); lock (pools) { - _instance = (pools.Count != 0) ? pools.Pop() : new(); + _instance = (pools.Count != 0) ? pools.Pop() : new(chunkSizeLimit, poolSizeIncrement); } } } - public static void ReturnPool(int groupId) + private static void PreparePoolSlim(int chunkSizeLimit, int poolSizeIncrement) + { + // Prepare the pool for this thread. + + if (_instance == null) + { + _instance = new(chunkSizeLimit, poolSizeIncrement); + } + } + + public static void ResetPool(int groupId = 0) + { + if (Ptc.State == PtcState.Disabled) + { + ResetPoolDefault(groupId); + } + else + { + ResetPoolSlim(); + } + } + + private static void ResetPoolDefault(int groupId) { // Reset, limit if necessary, and return the pool for this thread to the specified group. - var pools = GetPools(groupId); - lock (pools) + if (_instance != null) + { + var pools = GetPools(groupId); + lock (pools) + { + _instance.Clear(); + _instance.ChunkSizeLimiter(); + pools.Push(_instance); + + _instance = null; + } + } + } + + private static void ResetPoolSlim() + { + // Reset, limit if necessary, the pool for this thread. + + if (_instance != null) { _instance.Clear(); _instance.ChunkSizeLimiter(); - pools.Push(_instance); + } + } - _instance = null; + public static void DisposePools() + { + if (Ptc.State == PtcState.Disabled) + { + DisposePoolsDefault(); + } + else + { + DisposePoolSlim(); } } - public static void ResetPools() + private static void DisposePoolsDefault() { // Resets any static references to the pools used by threads for each group, allowing them to be garbage collected. @@ -78,20 +139,37 @@ namespace ARMeilleure.Common _pools.Clear(); } + private static void DisposePoolSlim() + { + // Dispose the pool for this thread. + + if (_instance != null) + { + _instance.Dispose(); + + _instance = null; + } + } + private List<T[]> _pool; private int _chunkIndex = -1; private int _poolIndex = -1; + private int _chunkSizeLimit; + private int _poolSizeIncrement; - private ThreadStaticPool() + private ThreadStaticPool(int chunkSizeLimit, int poolSizeIncrement) { - _pool = new(ChunkSizeLimit * 2); + _chunkSizeLimit = chunkSizeLimit; + _poolSizeIncrement = poolSizeIncrement; + + _pool = new(chunkSizeLimit * 2); AddChunkIfNeeded(); } public T Allocate() { - if (++_poolIndex >= PoolSizeIncrement) + if (++_poolIndex >= _poolSizeIncrement) { AddChunkIfNeeded(); @@ -105,9 +183,9 @@ namespace ARMeilleure.Common { if (++_chunkIndex >= _pool.Count) { - T[] pool = new T[PoolSizeIncrement]; + T[] pool = new T[_poolSizeIncrement]; - for (int i = 0; i < PoolSizeIncrement; i++) + for (int i = 0; i < _poolSizeIncrement; i++) { pool[i] = new T(); } @@ -124,18 +202,18 @@ namespace ARMeilleure.Common private void ChunkSizeLimiter() { - if (_pool.Count >= ChunkSizeLimit) + if (_pool.Count >= _chunkSizeLimit) { - int newChunkSize = ChunkSizeLimit / 2; + int newChunkSize = _chunkSizeLimit / 2; _pool.RemoveRange(newChunkSize, _pool.Count - newChunkSize); - _pool.Capacity = ChunkSizeLimit * 2; + _pool.Capacity = _chunkSizeLimit * 2; } } private void Dispose() { - _pool.Clear(); + _pool = null; } } } diff --git a/ARMeilleure/Common/ThreadStaticPoolEnums.cs b/ARMeilleure/Common/ThreadStaticPoolEnums.cs new file mode 100644 index 00000000..0d1d98d3 --- /dev/null +++ b/ARMeilleure/Common/ThreadStaticPoolEnums.cs @@ -0,0 +1,14 @@ +namespace ARMeilleure.Common +{ + public enum PoolSizeIncrement + { + Default = 200 + } + + public enum ChunkSizeLimit + { + Large = 200000 / PoolSizeIncrement.Default, + Medium = 100000 / PoolSizeIncrement.Default, + Small = 50000 / PoolSizeIncrement.Default + } +}
\ No newline at end of file |
