From c766a83178cc3145ce537943932c3cdcbc196502 Mon Sep 17 00:00:00 2001 From: Loretta Date: Wed, 28 Jan 2026 17:23:53 +0100 Subject: [PATCH] Comment out IdentityMap implementation The entire IdentityMap class and related types have been commented out, leaving the code inactive but preserved for reference. No functional code remains in the file; all logic is now present only as comments. --- AyCode.Core/Serializers/IdentityMap.cs | 406 +++++++++++++++++++++++++ 1 file changed, 406 insertions(+) create mode 100644 AyCode.Core/Serializers/IdentityMap.cs diff --git a/AyCode.Core/Serializers/IdentityMap.cs b/AyCode.Core/Serializers/IdentityMap.cs new file mode 100644 index 0000000..acca254 --- /dev/null +++ b/AyCode.Core/Serializers/IdentityMap.cs @@ -0,0 +1,406 @@ +//using System.Runtime.CompilerServices; + +//namespace AyCode.Core.Serializers; + +//#region IId Reference Tracking + +///// +///// Specifies the accessor type for IId.Id property to enable typed getter dispatch without boxing. +///// +//public enum IdAccessorType : byte +//{ +// None = 0, +// /// Id is int (most common). +// Int32 = 1, +// /// Id is long. +// Int64 = 2, +// /// Id is Guid. +// Guid = 3, +//} +///// +///// Interface for identity maps used in serialization tracking. +///// Enables type-safe Reset() without knowing the generic type parameter. +///// +//public interface IIdentityMap +//{ +// /// +// /// Resets the identity map for reuse between serializations. +// /// +// void Reset(); +//} + +///// +///// High-performance identity map for tracking IId values during serialization/deserialization. +///// Uses custom hash table optimized for our use case: +///// - Small int keys (0-4095): direct array access with bitmap +///// - Large keys: custom hash table with chaining +///// No Dictionary overhead, no per-entry allocation. +///// +///// The ID type (int, long, Guid, string) +//public sealed class IdentityMap : IIdentityMap where TId : notnull +//{ +// // Small int optimization (TId = int only, 0-4095) +// private const int SmallSize = 4096; +// private const int SmallBitmapSize = SmallSize / 64; // 64 ulongs + +// // Slot for storing tracked values +// private struct Slot +// { +// public object? Value; // stored object for deserialization +// public int Next; // next slot index in chain (-1 = end) +// } + +// // Small int storage (only used when TId is int) +// private ulong[]? _smallBitmap; // quick "seen?" check +// private Slot[]? _smallSlots; // direct indexed storage + +// // Hash table storage (for large ints and other types) +// private int[]? _buckets; // bucket index → first entry index +// private Slot[]? _entries; // hash table entries +// private TId[]? _keys; // keys for equality check +// private int _count; // number of entries in hash table + +// private const int InitialHashCapacity = 16; + +// // Type checks (JIT eliminates these at compile time) +// private static readonly bool IsInt32 = typeof(TId) == typeof(int); +// private static readonly bool IsInt64 = typeof(TId) == typeof(long); +// private static readonly bool IsGuid = typeof(TId) == typeof(Guid); +// private static readonly bool IsString = typeof(TId) == typeof(string); + +// public IdentityMap() +// { +// } + +// /// +// /// Tries to add a key to tracking (serialization). +// /// Returns true if first occurrence (key was added). +// /// Returns false if already seen. +// /// +// [MethodImpl(MethodImplOptions.AggressiveInlining)] +// public bool TryAddKey(TId key) +// { +// // Small int fast path +// if (IsInt32) +// { +// var intKey = Unsafe.As(ref key); +// if ((uint)intKey < SmallSize) +// { +// return TryAddSmallInt(intKey); +// } +// } + +// // Hash table path +// return TryAddHash(key, out _); +// } + +// [MethodImpl(MethodImplOptions.AggressiveInlining)] +// private bool TryAddSmallInt(int key) +// { +// // Lazy init +// if (_smallBitmap == null) +// { +// _smallBitmap = new ulong[SmallBitmapSize]; +// _smallSlots = new Slot[SmallSize]; +// } + +// var wordIdx = key >> 6; +// var bit = 1UL << (key & 63); + +// ref var word = ref _smallBitmap[wordIdx]; +// if ((word & bit) != 0) +// return false; // already seen + +// word |= bit; +// _smallSlots![key] = default; // init slot +// return true; +// } + +// [MethodImpl(MethodImplOptions.AggressiveInlining)] +// private bool TryAddHash(TId key, out int slotIndex) +// { +// var hash = GetHashCode(key); + +// // Lazy init +// if (_buckets == null) +// { +// InitHashTable(InitialHashCapacity); +// } + +// var bucketIdx = (hash & 0x7FFFFFFF) % _buckets!.Length; + +// // Search chain +// for (var i = _buckets[bucketIdx]; i >= 0; i = _entries![i].Next) +// { +// if (EqualityComparer.Default.Equals(_keys![i], key)) +// { +// slotIndex = i; +// return false; // already seen +// } +// } + +// // Resize if needed +// if (_count >= _entries!.Length) +// { +// Resize(); +// bucketIdx = (hash & 0x7FFFFFFF) % _buckets.Length; +// } + +// // Add new entry +// slotIndex = _count++; +// _keys![slotIndex] = key; +// _entries[slotIndex] = new Slot { Next = _buckets[bucketIdx] }; +// _buckets[bucketIdx] = slotIndex; +// return true; +// } + +// [MethodImpl(MethodImplOptions.AggressiveInlining)] +// private static int GetHashCode(TId key) +// { +// // Specialized hash for known types +// if (IsInt32) return Unsafe.As(ref key); +// if (IsInt64) return Unsafe.As(ref key).GetHashCode(); +// if (IsGuid) return Unsafe.As(ref key).GetHashCode(); +// return key.GetHashCode(); +// } + +// private void InitHashTable(int capacity) +// { +// _buckets = new int[capacity]; +// Array.Fill(_buckets, -1); +// _entries = new Slot[capacity]; +// _keys = new TId[capacity]; +// _count = 0; +// } + +// private void Resize() +// { +// var newCapacity = _buckets!.Length * 2; +// var newBuckets = new int[newCapacity]; +// Array.Fill(newBuckets, -1); +// var newEntries = new Slot[newCapacity]; +// var newKeys = new TId[newCapacity]; + +// // Copy entries +// Array.Copy(_entries!, newEntries, _count); +// Array.Copy(_keys!, newKeys, _count); + +// // Rebuild bucket chains +// for (var i = 0; i < _count; i++) +// { +// var bucketIdx = (GetHashCode(newKeys[i]) & 0x7FFFFFFF) % newCapacity; +// newEntries[i].Next = newBuckets[bucketIdx]; +// newBuckets[bucketIdx] = i; +// } + +// _buckets = newBuckets; +// _entries = newEntries; +// _keys = newKeys; +// } + +// [MethodImpl(MethodImplOptions.AggressiveInlining)] +// public bool HasKey(TId key) +// { +// // Small int fast path +// if (IsInt32) +// { +// var intKey = Unsafe.As(ref key); +// if ((uint)intKey < SmallSize && _smallBitmap != null) +// { +// var wordIdx = intKey >> 6; +// var bit = 1UL << (intKey & 63); +// return (_smallBitmap[wordIdx] & bit) != 0; +// } +// } + +// // Hash table path +// if (_buckets == null) return false; + +// var hash = GetHashCode(key); +// var bucketIdx = (hash & 0x7FFFFFFF) % _buckets.Length; + +// for (var i = _buckets[bucketIdx]; i >= 0; i = _entries![i].Next) +// { +// if (EqualityComparer.Default.Equals(_keys![i], key)) +// return true; +// } +// return false; +// } + +// /// +// /// Checks if key exists and returns existing value, or adds new key (deserialization). +// /// Returns true if first occurrence (key was added, out = null). +// /// Returns false if already seen (out = existing value). +// /// +// [MethodImpl(MethodImplOptions.AggressiveInlining)] +// public bool TryGetOrAddKey(TId key, out object? existing) +// { +// // Small int fast path +// if (IsInt32) +// { +// var intKey = Unsafe.As(ref key); +// if ((uint)intKey < SmallSize) +// { +// return TryGetOrAddSmallInt(intKey, out existing); +// } +// } + +// // Hash table path +// if (!TryAddHash(key, out var slotIndex)) +// { +// existing = _entries![slotIndex].Value; +// return false; +// } +// existing = null; +// return true; +// } + +// [MethodImpl(MethodImplOptions.AggressiveInlining)] +// private bool TryGetOrAddSmallInt(int key, out object? existing) +// { +// // Lazy init +// if (_smallBitmap == null) +// { +// _smallBitmap = new ulong[SmallBitmapSize]; +// _smallSlots = new Slot[SmallSize]; +// } + +// var wordIdx = key >> 6; +// var bit = 1UL << (key & 63); + +// ref var word = ref _smallBitmap[wordIdx]; +// if ((word & bit) != 0) +// { +// existing = _smallSlots![key].Value; +// return false; // already seen +// } + +// word |= bit; +// _smallSlots![key] = default; +// existing = null; +// return true; +// } + +// /// +// /// Gets existing value or adds new value for key (deserialization with object storage). +// /// Returns the existing value if key was seen before, or stores and returns newValue. +// /// +// [MethodImpl(MethodImplOptions.AggressiveInlining)] +// public object TryGetOrAddValue(TId key, object newValue) +// { +// // Small int fast path +// if (IsInt32) +// { +// var intKey = Unsafe.As(ref key); +// if ((uint)intKey < SmallSize) +// { +// return TryGetOrAddSmallIntValue(intKey, newValue); +// } +// } + +// // Hash table path +// if (!TryAddHash(key, out var slotIndex)) +// { +// var existing = _entries![slotIndex].Value; +// if (existing != null) return existing; +// } +// _entries![slotIndex].Value = newValue; +// return newValue; +// } + +// [MethodImpl(MethodImplOptions.AggressiveInlining)] +// private object TryGetOrAddSmallIntValue(int key, object newValue) +// { +// // Lazy init +// if (_smallBitmap == null) +// { +// _smallBitmap = new ulong[SmallBitmapSize]; +// _smallSlots = new Slot[SmallSize]; +// } + +// var wordIdx = key >> 6; +// var bit = 1UL << (key & 63); + +// ref var word = ref _smallBitmap[wordIdx]; +// if ((word & bit) != 0) +// { +// var existing = _smallSlots![key].Value; +// if (existing != null) return existing; +// } + +// word |= bit; +// _smallSlots![key].Value = newValue; +// return newValue; +// } + +// /// +// /// Tries to get the value for a key (ObjectRef lookup). +// /// Returns true if found, false if not. +// /// +// [MethodImpl(MethodImplOptions.AggressiveInlining)] +// public bool TryGetValue(TId key, out object? value) +// { +// // Small int fast path +// if (IsInt32) +// { +// var intKey = Unsafe.As(ref key); +// if ((uint)intKey < SmallSize && _smallBitmap != null) +// { +// var wordIdx = intKey >> 6; +// var bit = 1UL << (intKey & 63); +// if ((_smallBitmap[wordIdx] & bit) != 0) +// { +// value = _smallSlots![intKey].Value; +// return true; +// } +// value = null; +// return false; +// } +// } + +// // Hash table path +// if (_buckets == null) +// { +// value = null; +// return false; +// } + +// var hash = GetHashCode(key); +// var bucketIdx = (hash & 0x7FFFFFFF) % _buckets.Length; + +// for (var i = _buckets[bucketIdx]; i >= 0; i = _entries![i].Next) +// { +// if (EqualityComparer.Default.Equals(_keys![i], key)) +// { +// value = _entries[i].Value; +// return true; +// } +// } +// value = null; +// return false; +// } + +// /// +// /// Resets the identity map for reuse. +// /// +// public void Reset() +// { +// // Clear small int storage +// if (_smallBitmap != null) +// { +// Array.Clear(_smallBitmap); +// Array.Clear(_smallSlots!); +// } + +// // Clear hash table +// if (_buckets != null) +// { +// Array.Fill(_buckets, -1); +// Array.Clear(_entries!); +// Array.Clear(_keys!); +// _count = 0; +// } +// } +//} + +//#endregion \ No newline at end of file