From 0c1887d8f83c8e66391603ce8edd0c4929d7a5d7 Mon Sep 17 00:00:00 2001 From: Nitload Date: Thu, 12 Mar 2026 00:49:50 +0800 Subject: [PATCH] Daily update on 20260312-004950 by Nitload Youmu. Additional Message : use one single index mux as replacement of two slab allocators for L4. Signed-off-by: Nitload --- .../Collections/IHashMultiplexer.cs | 53 ---------- StgSharp.Common/Collections/UnmanagedStack.cs | 96 +++++++++++++++++++ .../HighPerformance/IdMultiplexer.cs | 13 +++ .../HighPerformance/Memory/L4.Allocate.cs | 53 ++++++++++ .../HighPerformance/Memory/L4.CacheLine.cs | 13 +-- .../HighPerformance/Memory/L4.Prefetch.cs | 15 +-- StgSharp.Common/HighPerformance/Memory/L4.cs | 42 ++++---- 7 files changed, 197 insertions(+), 88 deletions(-) delete mode 100644 StgSharp.Common/Collections/IHashMultiplexer.cs create mode 100644 StgSharp.Common/Collections/UnmanagedStack.cs create mode 100644 StgSharp.Common/HighPerformance/IdMultiplexer.cs create mode 100644 StgSharp.Common/HighPerformance/Memory/L4.Allocate.cs diff --git a/StgSharp.Common/Collections/IHashMultiplexer.cs b/StgSharp.Common/Collections/IHashMultiplexer.cs deleted file mode 100644 index 6f0acde4..00000000 --- a/StgSharp.Common/Collections/IHashMultiplexer.cs +++ /dev/null @@ -1,53 +0,0 @@ -//----------------------------------------------------------------------- -// ----------------------------------------------------------------------- -// file="IHashMultiplexer" -// Project: StgSharp -// AuthorGroup: Nitload -// Copyright (c) Nitload. All rights reserved. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. -// -// ----------------------------------------------------------------------- -// ----------------------------------------------------------------------- -using System.Collections.Generic; - -namespace StgSharp.Collections -{ - public interface IHashMultiplexer : IEqualityComparer - { - - int RemainedMultiplexCount { get; set; } - - /// - /// Cache hash result for obj with counts. - /// - /// - /// - /// - /// - /// - /// - void CacheHash(T obj, int count); - - void ExtendCache(int count); - - int ForceComputeHash(T count); - - } -} \ No newline at end of file diff --git a/StgSharp.Common/Collections/UnmanagedStack.cs b/StgSharp.Common/Collections/UnmanagedStack.cs new file mode 100644 index 00000000..819f1c21 --- /dev/null +++ b/StgSharp.Common/Collections/UnmanagedStack.cs @@ -0,0 +1,96 @@ +//----------------------------------------------------------------------- +// ----------------------------------------------------------------------- +// file="UnmanagedStack" +// Project: StgSharp +// AuthorGroup: Nitload Space +// Copyright (c) Nitload Space. All rights reserved. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. +// +// ----------------------------------------------------------------------- +// ----------------------------------------------------------------------- +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace StgSharp.Collections +{ + public unsafe class UnmanagedStack(T* address, int capacity, Action freeHandle) : IDisposable + where T: unmanaged + { + + private T* _array = address; + private readonly Action _freeHandle = freeHandle; + private readonly int _capacity = capacity; + private int _index; + + public void Clear() + { + _index = 0; + } + + public void Dispose() + { + if (_array != null) + { + _freeHandle((nuint)_array); + _array = null; + } + GC.SuppressFinalize(this); + } + + public T Pop() + { + if (_index == 0) { + throw new InvalidOperationException("Stack is empty."); + } + return _array[--_index]; + } + + public void Push(T value) + { + _array[_index] = value; + _index++; + } + + public bool TryPop(out T value) + { + if (_index == 0) + { + value = default; + return false; + } + value = _array[--_index]; + return true; + } + + public bool TryPush(T value) + { + if (_index >= _capacity) { + return false; + } + _array[_index] = value; + _index++; + return true; + } + + } +} diff --git a/StgSharp.Common/HighPerformance/IdMultiplexer.cs b/StgSharp.Common/HighPerformance/IdMultiplexer.cs new file mode 100644 index 00000000..08f1f70e --- /dev/null +++ b/StgSharp.Common/HighPerformance/IdMultiplexer.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace StgSharp.HighPerformance +{ + public class IdMultiplexer + { + + } +} diff --git a/StgSharp.Common/HighPerformance/Memory/L4.Allocate.cs b/StgSharp.Common/HighPerformance/Memory/L4.Allocate.cs new file mode 100644 index 00000000..1cda29f9 --- /dev/null +++ b/StgSharp.Common/HighPerformance/Memory/L4.Allocate.cs @@ -0,0 +1,53 @@ +//----------------------------------------------------------------------- +// ----------------------------------------------------------------------- +// file="L4.Allocate.cs" +// Project: StgSharp +// AuthorGroup: Nitload Space +// Copyright (c) Nitload Space. All rights reserved. +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the “Software”), to deal in the Software without restriction, +// including without limitation the rights to use, copy, modify, merge, +// publish, distribute, sublicense, and/or sell copies of the Software, +// and to permit persons to whom the Software is furnished to do so, +// subject to the following conditions: +// +// The above copyright notice and +// this permission notice shall be included in all copies +// or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED “AS IS”, +// WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH +// THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// +// ----------------------------------------------------------------------- +// ----------------------------------------------------------------------- +namespace StgSharp.HighPerformance.Memory +{ + public partial class L4 + { + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private void RecycleLine(int id) + { + _idMux.Push(id); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private bool TryGetEmptyLine(out int index) + { + if (_idMux.TryPop(out index)) { + return true; + } + index = _maxId; + return Interlocked.Increment(ref _maxId) >= CacheLineCount; + } + + } +} diff --git a/StgSharp.Common/HighPerformance/Memory/L4.CacheLine.cs b/StgSharp.Common/HighPerformance/Memory/L4.CacheLine.cs index 24ca8dd3..c6a2f468 100644 --- a/StgSharp.Common/HighPerformance/Memory/L4.CacheLine.cs +++ b/StgSharp.Common/HighPerformance/Memory/L4.CacheLine.cs @@ -2,8 +2,8 @@ // ----------------------------------------------------------------------- // file="L4.CacheLine" // Project: StgSharp -// AuthorGroup: Nitload -// Copyright (c) Nitload. All rights reserved. +// AuthorGroup: Nitload Space +// Copyright (c) Nitload Space. All rights reserved. // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal @@ -63,15 +63,16 @@ namespace StgSharp.HighPerformance.Memory } - [StructLayout(LayoutKind.Sequential)] + [StructLayout(LayoutKind.Sequential, Pack = 16)] private unsafe struct CacheLineHead { - internal CacheLineHead* _next; - internal CacheLineHead* _prev; - internal int _level; + internal int _id; internal int _refCount; + + internal long _profile; internal nuint _address; + internal nuint _origin; } diff --git a/StgSharp.Common/HighPerformance/Memory/L4.Prefetch.cs b/StgSharp.Common/HighPerformance/Memory/L4.Prefetch.cs index bb1838e5..decb6bcc 100644 --- a/StgSharp.Common/HighPerformance/Memory/L4.Prefetch.cs +++ b/StgSharp.Common/HighPerformance/Memory/L4.Prefetch.cs @@ -2,8 +2,8 @@ // ----------------------------------------------------------------------- // file="L4.Prefetch" // Project: StgSharp -// AuthorGroup: Nitload -// Copyright (c) Nitload. All rights reserved. +// AuthorGroup: Nitload Space +// Copyright (c) Nitload Space. All rights reserved. // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal @@ -71,11 +71,14 @@ namespace StgSharp.HighPerformance.Memory } } - private partial bool TestHit( - nuint origin - ) + private partial bool TestHit(nuint origin) { - // needs implementation + if (_map.TryGet(origin, out nuint handle)) + { + CacheLineHead* head = (CacheLineHead*)handle; + int index = head->_id; + (*_eviction)[index] = 0; // reset eviction counter + } return false; } diff --git a/StgSharp.Common/HighPerformance/Memory/L4.cs b/StgSharp.Common/HighPerformance/Memory/L4.cs index d6c010cf..c3a817f6 100644 --- a/StgSharp.Common/HighPerformance/Memory/L4.cs +++ b/StgSharp.Common/HighPerformance/Memory/L4.cs @@ -2,8 +2,8 @@ // ----------------------------------------------------------------------- // file="L4" // Project: StgSharp -// AuthorGroup: Nitload -// Copyright (c) Nitload. All rights reserved. +// AuthorGroup: Nitload Space +// Copyright (c) Nitload Space. All rights reserved. // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal @@ -42,33 +42,36 @@ namespace StgSharp.HighPerformance.Memory private const int CacheLineCount = 8192; private const int PredictionCount = 2048; - private const int PredictionLeaseAhead = 1024; + private const int PredictionLeastAhead = 1024; + + private readonly CacheLineData* _data; private readonly EvictionArray* _eviction; - + private readonly CacheLineHead* _head; private readonly CacheLinePrediction* _prediction; private bool _disposed; private int _activeCount; private int _aheadCount; + private int _maxId; private readonly nuint _baseAddress; - private readonly SlabAllocator _cacheLineAllocator; - - private readonly SlabAllocator _entryAllocator; - private readonly SwissTable _map; + private readonly UnmanagedStack _idMux; public L4() { int cacheSize = Unsafe.SizeOf() * CacheLineCount; int entrySize = Unsafe.SizeOf() * CacheLineCount; + int stackSize = sizeof(int) * CacheLineCount; int mapSize = SwissTable.RequestedNativeMemorySize; - int pprvSize = Unsafe.SizeOf(); - _baseAddress = (nuint)NativeMemory.AlignedAlloc((nuint)(cacheSize + entrySize + mapSize), 16); + int predictionSize = Unsafe.SizeOf() * PredictionCount; + int rrpvSize = Unsafe.SizeOf(); + _baseAddress = (nuint)NativeMemory.AlignedAlloc((nuint)(cacheSize + entrySize + stackSize + mapSize + predictionSize + rrpvSize), 16); nuint _buffer = _baseAddress; - _cacheLineAllocator = SlabAllocator.FromBuffer(_buffer, CacheLineCount, _ => { }); - _entryAllocator = SlabAllocator.FromBuffer(_buffer + (nuint)cacheSize, CacheLineCount, _ => { }); + _data = (CacheLineData*)_buffer; + _head = (CacheLineHead*)(_buffer + (nuint)cacheSize); + _prediction = (CacheLinePrediction*)(_buffer + (nuint)(cacheSize + entrySize)); _map = SwissTable.Create(_baseAddress + (nuint)(cacheSize + entrySize), _ => { }); _eviction = (EvictionArray*)(_baseAddress + (nuint)(cacheSize + entrySize + mapSize)); } @@ -89,13 +92,12 @@ namespace StgSharp.HighPerformance.Memory return; } _disposed = true; + _map.Dispose(); NativeMemory.AlignedFree((void*)_baseAddress); GC.SuppressFinalize(this); } - public CacheLine Map( - nuint origin - ) + public CacheLine Map(nuint origin) { if (_map.TryGet(origin, out nuint entryHandle)) { @@ -114,9 +116,7 @@ namespace StgSharp.HighPerformance.Memory private partial void Prefetch(); - private partial bool TestHit( - nuint origin - ); + private partial bool TestHit(nuint origin); public ref struct CacheLine : IDisposable { @@ -125,11 +125,7 @@ namespace StgSharp.HighPerformance.Memory private ref int _refCount; private nuint _handle; - internal CacheLine( - nuint handle, - ref int activeCount, - ref int cacheRefCount - ) + internal CacheLine(nuint handle, ref int activeCount, ref int cacheRefCount) { _handle = handle; _refCount = ref cacheRefCount;