diff options
author | LDj3SNuD <35856442+LDj3SNuD@users.noreply.github.com> | 2021-01-12 19:04:02 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-01-12 19:04:02 +0100 |
commit | 68f6b79fd3f06ea572d5f0edd5fc8cbaee1ae449 (patch) | |
tree | a4cf471c7979f85c3bf894f65129f2cb85931dc3 /ARMeilleure | |
parent | e57b14042910eac2f876549b4a1e6fd5ba027368 (diff) |
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.
Diffstat (limited to 'ARMeilleure')
-rw-r--r-- | ARMeilleure/Common/ThreadStaticPool.cs | 82 | ||||
-rw-r--r-- | ARMeilleure/Translation/DirectCallStubs.cs | 2 | ||||
-rw-r--r-- | ARMeilleure/Translation/PTC/Ptc.cs | 16 | ||||
-rw-r--r-- | ARMeilleure/Translation/Translator.cs | 31 |
4 files changed, 81 insertions, 50 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(); } } } diff --git a/ARMeilleure/Translation/DirectCallStubs.cs b/ARMeilleure/Translation/DirectCallStubs.cs index 57397d14..df7ca16e 100644 --- a/ARMeilleure/Translation/DirectCallStubs.cs +++ b/ARMeilleure/Translation/DirectCallStubs.cs @@ -34,8 +34,6 @@ namespace ARMeilleure.Translation _indirectCallStubPtr = Marshal.GetFunctionPointerForDelegate<GuestFunction>(GenerateIndirectCallStub(false)); _indirectTailCallStubPtr = Marshal.GetFunctionPointerForDelegate<GuestFunction>(GenerateIndirectCallStub(true)); - Translator.ResetPools(); - _initialized = true; } } diff --git a/ARMeilleure/Translation/PTC/Ptc.cs b/ARMeilleure/Translation/PTC/Ptc.cs index f382cc63..8f250a55 100644 --- a/ARMeilleure/Translation/PTC/Ptc.cs +++ b/ARMeilleure/Translation/PTC/Ptc.cs @@ -98,7 +98,6 @@ namespace ARMeilleure.Translation.PTC ClearMemoryStreams(); PtcJumpTable.Clear(); - PtcProfiler.Stop(); PtcProfiler.Wait(); PtcProfiler.ClearEntries(); @@ -345,6 +344,8 @@ namespace ARMeilleure.Translation.PTC private static void Save(string fileName) { + int translatedFuncsCount; + using (MemoryStream stream = new MemoryStream()) using (MD5 md5 = MD5.Create()) { @@ -361,6 +362,11 @@ namespace ARMeilleure.Translation.PTC PtcJumpTable.Serialize(stream, PtcJumpTable); + translatedFuncsCount = GetInfosEntriesCount(); + + ClearMemoryStreams(); + PtcJumpTable.Clear(); + stream.Seek((long)hashSize, SeekOrigin.Begin); byte[] hash = md5.ComputeHash(stream); @@ -388,7 +394,7 @@ namespace ARMeilleure.Translation.PTC long fileSize = new FileInfo(fileName).Length; - Logger.Info?.Print(LogClass.Ptc, $"Saved Translation Cache (size: {fileSize} bytes, translated functions: {GetInfosEntriesCount()})."); + Logger.Info?.Print(LogClass.Ptc, $"Saved Translation Cache (size: {fileSize} bytes, translated functions: {translatedFuncsCount})."); } private static void WriteHeader(MemoryStream stream) @@ -709,10 +715,10 @@ namespace ARMeilleure.Translation.PTC threads.Clear(); - _loggerEvent.Set(); - Translator.ResetPools(); + _loggerEvent.Set(); + PtcJumpTable.Initialize(jumpTable); PtcJumpTable.ReadJumpTable(jumpTable); @@ -736,7 +742,7 @@ namespace ARMeilleure.Translation.PTC Logger.Info?.Print(LogClass.Ptc, $"{_translateCount} of {profiledFuncsToTranslateCount} functions translated"); } - internal static void WriteInfoCodeReloc(ulong address, ulong guestSize, bool highCq, PtcInfo ptcInfo) + internal static void WriteInfoCodeRelocUnwindInfo(ulong address, ulong guestSize, bool highCq, PtcInfo ptcInfo) { lock (_lock) { diff --git a/ARMeilleure/Translation/Translator.cs b/ARMeilleure/Translation/Translator.cs index 612f6647..2c32e9f0 100644 --- a/ARMeilleure/Translation/Translator.cs +++ b/ARMeilleure/Translation/Translator.cs @@ -201,15 +201,14 @@ namespace ARMeilleure.Translation { ArmEmitterContext context = new ArmEmitterContext(memory, jumpTable, address, highCq, Aarch32Mode.User); - PrepareOperandPool(highCq); - PrepareOperationPool(highCq); - Logger.StartPass(PassName.Decoding); Block[] blocks = Decoder.Decode(memory, address, mode, highCq, singleBlock: false); Logger.EndPass(PassName.Decoding); + PreparePool(highCq); + Logger.StartPass(PassName.Translation); EmitSynchronization(context); @@ -240,21 +239,31 @@ namespace ARMeilleure.Translation if (Ptc.State == PtcState.Disabled) { func = Compiler.Compile<GuestFunction>(cfg, argTypes, OperandType.I64, options); + + ReturnPool(highCq); } - else + else using (PtcInfo ptcInfo = new PtcInfo()) { - using (PtcInfo ptcInfo = new PtcInfo()) - { - func = Compiler.Compile<GuestFunction>(cfg, argTypes, OperandType.I64, options, ptcInfo); + func = Compiler.Compile<GuestFunction>(cfg, argTypes, OperandType.I64, options, ptcInfo); - Ptc.WriteInfoCodeReloc(address, funcSize, highCq, ptcInfo); - } + ReturnPool(highCq); + + Ptc.WriteInfoCodeRelocUnwindInfo(address, funcSize, highCq, ptcInfo); } + return new TranslatedFunction(func, funcSize, highCq); + } + + internal static void PreparePool(bool highCq) + { + PrepareOperandPool(highCq); + PrepareOperationPool(highCq); + } + + internal static void ReturnPool(bool highCq) + { ReturnOperandPool(highCq); ReturnOperationPool(highCq); - - return new TranslatedFunction(func, funcSize, highCq); } internal static void ResetPools() |