From 68f6b79fd3f06ea572d5f0edd5fc8cbaee1ae449 Mon Sep 17 00:00:00 2001 From: LDj3SNuD <35856442+LDj3SNuD@users.noreply.github.com> Date: Tue, 12 Jan 2021 19:04:02 +0100 Subject: Add a simple Pools Limiter. (#1830) * Added support for offline invalidation, via PPTC, of low cq translations replaced by high cq translations; both on a single run and between runs. Added invalidation of .cache files in the event of reuse on a different user operating system. Added .info and .cache files invalidation in case of a failed stream decompression. Nits. * InternalVersion = 1712; * Nits. * Address comment. * Get rid of BinaryFormatter. Nits. * Move Ptc.LoadTranslations(). Nits. * Nits. * Fixed corner cases (in case backup copies have to be used). Added save logs. * Not core fixes. * Complement to the previous commit. Added load logs. Removed BinaryFormatter leftovers. * Add LoadTranslations log. * Nits. * Removed the search and management of LowCq overlapping functions. * Final increment of .info and .cache flags. * Nit. * Free up memory allocated by Pools during any PPTC translations at boot time. * Nit due to rebase. * Add a simple Pools Limiter. * Nits. * Fix missing JumpTable.RegisterFunction() due to rebase. Clear MemoryStreams as soon as possible, when they are no longer needed. * Code cleaning. * Nit for retrigger Checks. * Update Ptc.cs * Contextual refactoring of Translator. Ignore resetting of pools for DirectCallStubs. * Nit for retrigger Checks. --- ARMeilleure/Common/ThreadStaticPool.cs | 82 +++++++++++++++++++++------------- 1 file changed, 50 insertions(+), 32 deletions(-) (limited to 'ARMeilleure/Common/ThreadStaticPool.cs') 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 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 _instance; @@ -25,11 +25,11 @@ namespace ARMeilleure.Common } } - private static ConcurrentDictionary>> _pools = new ConcurrentDictionary>>(); + private static ConcurrentDictionary>> _pools = new(); private static Stack> GetPools(int groupId) { - return _pools.GetOrAdd(groupId, x => new Stack>()); + 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(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 _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(); } } } -- cgit v1.2.3