PPTC & Pool Enhancements. (#1968)
* PPTC & Pool Enhancements. * Avoid buffer allocations in CodeGenContext.GetCode(). Avoid stream allocations in PTC.PtcInfo. Refactoring/nits. * Use XXHash128, for Ptc.Load & Ptc.Save, x10 faster than Md5. * Why not a nice Span. * Added a simple PtcFormatter library for deserialization/serialization, which does not require reflection, in use at PtcJumpTable and PtcProfiler; improves maintainability and simplicity/readability of affected code. * Nits. * Revert #1987. * Revert "Revert #1987." This reverts commit 998be765cf7f7da5ff0c1c08de704c9012b0f49c.
This commit is contained in:
parent
1586880114
commit
dc0adb533d
20 changed files with 777 additions and 603 deletions
|
@ -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)
|
||||
{
|
||||
// Reset, limit if necessary, and return the pool for this thread to the specified group.
|
||||
// Prepare the pool for this thread.
|
||||
|
||||
var pools = GetPools(groupId);
|
||||
lock (pools)
|
||||
if (_instance == null)
|
||||
{
|
||||
_instance.Clear();
|
||||
_instance.ChunkSizeLimiter();
|
||||
pools.Push(_instance);
|
||||
|
||||
_instance = null;
|
||||
_instance = new(chunkSizeLimit, poolSizeIncrement);
|
||||
}
|
||||
}
|
||||
|
||||
public static void ResetPools()
|
||||
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.
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
public static void DisposePools()
|
||||
{
|
||||
if (Ptc.State == PtcState.Disabled)
|
||||
{
|
||||
DisposePoolsDefault();
|
||||
}
|
||||
else
|
||||
{
|
||||
DisposePoolSlim();
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue