22using System . Collections ;
33using System . Collections . Generic ;
44using System . Runtime . CompilerServices ;
5+ using System . Runtime . InteropServices ;
56
67namespace Nino . Core
78{
@@ -17,6 +18,9 @@ public sealed class FastMap<TKey, TValue> : IDisposable, IEnumerable<KeyValuePai
1718 private const int MaxKickCount = 16 ;
1819 private const int MinCapacity = 8 ;
1920
21+ // Optimized layout: Pack=1 eliminates padding, improving cache utilization
22+ // Trade-off: potential unaligned access (acceptable on modern CPUs) for better memory density
23+ [ StructLayout ( LayoutKind . Sequential , Pack = 1 ) ]
2024 private struct Entry
2125 {
2226 public uint HashCode ;
@@ -25,6 +29,9 @@ private struct Entry
2529 public TValue Value ;
2630 }
2731
32+ // Cache the equality comparer to avoid repeated lookups in hot paths
33+ private static readonly IEqualityComparer < TKey > KeyComparer = EqualityComparer < TKey > . Default ;
34+
2835 private Entry [ ] _table1 ;
2936 private Entry [ ] _table2 ;
3037 private int _capacity ;
@@ -51,12 +58,12 @@ public ref TValue this[in TKey key]
5158
5259 var index1 = hashCode & _capacityMask ;
5360 ref Entry entry1 = ref _table1 [ index1 ] ;
54- if ( entry1 . HashCode == hashCode && EqualityComparer < TKey > . Default . Equals ( entry1 . Key , key ) )
61+ if ( entry1 . HashCode == hashCode && KeyComparer . Equals ( entry1 . Key , key ) )
5562 return ref entry1 . Value ;
5663
5764 var index2 = ( hashCode >> 8 ) & _capacityMask ;
5865 ref Entry entry2 = ref _table2 [ index2 ] ;
59- if ( entry2 . HashCode == hashCode && EqualityComparer < TKey > . Default . Equals ( entry2 . Key , key ) )
66+ if ( entry2 . HashCode == hashCode && KeyComparer . Equals ( entry2 . Key , key ) )
6067 return ref entry2 . Value ;
6168 throw new KeyNotFoundException ( ) ;
6269 }
@@ -152,7 +159,7 @@ public bool TryAdd(in TKey key, in TValue value)
152159 _version ++ ;
153160 return true ;
154161 }
155- else if ( entry1 . HashCode == hashCode && EqualityComparer < TKey > . Default . Equals ( entry1 . Key , key ) )
162+ else if ( entry1 . HashCode == hashCode && KeyComparer . Equals ( entry1 . Key , key ) )
156163 return false ;
157164
158165 var index2 = ( hashCode >> 8 ) & _capacityMask ;
@@ -167,7 +174,7 @@ public bool TryAdd(in TKey key, in TValue value)
167174 _version ++ ;
168175 return true ;
169176 }
170- else if ( entry2 . HashCode == hashCode && EqualityComparer < TKey > . Default . Equals ( entry2 . Key , key ) )
177+ else if ( entry2 . HashCode == hashCode && KeyComparer . Equals ( entry2 . Key , key ) )
171178 return false ;
172179
173180 bool res = CuckooInsert ( hashCode , key , value , false ) ;
@@ -193,7 +200,7 @@ private bool TryAddOrUpdate(in TKey key, in TValue value)
193200 _version ++ ;
194201 return true ;
195202 }
196- else if ( entry1 . HashCode == hashCode && EqualityComparer < TKey > . Default . Equals ( entry1 . Key , key ) )
203+ else if ( entry1 . HashCode == hashCode && KeyComparer . Equals ( entry1 . Key , key ) )
197204 {
198205 entry1 . Value = value ;
199206 _version ++ ;
@@ -212,7 +219,7 @@ private bool TryAddOrUpdate(in TKey key, in TValue value)
212219 _version ++ ;
213220 return true ;
214221 }
215- else if ( entry2 . HashCode == hashCode && EqualityComparer < TKey > . Default . Equals ( entry2 . Key , key ) )
222+ else if ( entry2 . HashCode == hashCode && KeyComparer . Equals ( entry2 . Key , key ) )
216223 {
217224 entry2 . Value = value ;
218225 _version ++ ;
@@ -247,7 +254,7 @@ private bool CuckooInsert(int hashCode, in TKey key, in TValue value, bool updat
247254 _count ++ ;
248255 return true ;
249256 }
250- else if ( updateIfExists && entry . HashCode == currentHashCode && EqualityComparer < TKey > . Default . Equals ( entry . Key , currentKey ) )
257+ else if ( updateIfExists && entry . HashCode == currentHashCode && KeyComparer . Equals ( entry . Key , currentKey ) )
251258 {
252259 entry . Value = currentValue ;
253260 return true ;
@@ -271,7 +278,7 @@ private bool CuckooInsert(int hashCode, in TKey key, in TValue value, bool updat
271278 _count ++ ;
272279 return true ;
273280 }
274- else if ( updateIfExists && entry . HashCode == currentHashCode && EqualityComparer < TKey > . Default . Equals ( entry . Key , currentKey ) )
281+ else if ( updateIfExists && entry . HashCode == currentHashCode && KeyComparer . Equals ( entry . Key , currentKey ) )
275282 {
276283 entry . Value = currentValue ;
277284 return true ;
@@ -296,7 +303,7 @@ public ref TValue GetValueRefOrAddDefault(TKey key, out bool exists)
296303
297304 var index1 = hashCode & _capacityMask ;
298305 ref Entry entry1 = ref _table1 [ index1 ] ;
299- if ( entry1 . HashCode == hashCode && EqualityComparer < TKey > . Default . Equals ( entry1 . Key , key ) )
306+ if ( entry1 . HashCode == hashCode && KeyComparer . Equals ( entry1 . Key , key ) )
300307 {
301308 exists = true ;
302309 return ref entry1 . Value ;
@@ -305,7 +312,7 @@ public ref TValue GetValueRefOrAddDefault(TKey key, out bool exists)
305312 var index2 = ( hashCode >> 8 ) & _capacityMask ;
306313
307314 ref Entry entry2 = ref _table2 [ index2 ] ;
308- if ( entry2 . HashCode == hashCode && EqualityComparer < TKey > . Default . Equals ( entry2 . Key , key ) )
315+ if ( entry2 . HashCode == hashCode && KeyComparer . Equals ( entry2 . Key , key ) )
309316 {
310317 exists = true ;
311318 return ref entry2 . Value ;
@@ -349,15 +356,15 @@ public bool TryGetValue(in TKey key, out TValue value)
349356
350357 var index1 = hashCode & _capacityMask ;
351358 ref Entry entry1 = ref _table1 [ index1 ] ;
352- if ( entry1 . HashCode == hashCode && EqualityComparer < TKey > . Default . Equals ( entry1 . Key , key ) )
359+ if ( entry1 . HashCode == hashCode && KeyComparer . Equals ( entry1 . Key , key ) )
353360 {
354361 value = entry1 . Value ;
355362 return true ;
356363 }
357364
358365 var index2 = ( hashCode >> 8 ) & _capacityMask ;
359366 ref Entry entry2 = ref _table2 [ index2 ] ;
360- if ( entry2 . HashCode == hashCode && EqualityComparer < TKey > . Default . Equals ( entry2 . Key , key ) )
367+ if ( entry2 . HashCode == hashCode && KeyComparer . Equals ( entry2 . Key , key ) )
361368 {
362369 value = entry2 . Value ;
363370 return true ;
@@ -375,12 +382,12 @@ public ref TValue GetValueRef(in TKey key)
375382
376383 var index1 = hashCode & _capacityMask ;
377384 ref Entry entry1 = ref _table1 [ index1 ] ;
378- if ( entry1 . HashCode == hashCode && EqualityComparer < TKey > . Default . Equals ( entry1 . Key , key ) )
385+ if ( entry1 . HashCode == hashCode && KeyComparer . Equals ( entry1 . Key , key ) )
379386 return ref entry1 . Value ;
380387
381388 var index2 = ( hashCode >> 8 ) & _capacityMask ;
382389 ref Entry entry2 = ref _table2 [ index2 ] ;
383- if ( entry2 . HashCode == hashCode && EqualityComparer < TKey > . Default . Equals ( entry2 . Key , key ) )
390+ if ( entry2 . HashCode == hashCode && KeyComparer . Equals ( entry2 . Key , key ) )
384391 return ref entry2 . Value ;
385392
386393 throw new KeyNotFoundException ( ) ;
@@ -394,12 +401,12 @@ public bool ContainsKey(in TKey key)
394401
395402 var index1 = hashCode & _capacityMask ;
396403 ref Entry entry1 = ref _table1 [ index1 ] ;
397- if ( entry1 . HashCode == hashCode && EqualityComparer < TKey > . Default . Equals ( entry1 . Key , key ) )
404+ if ( entry1 . HashCode == hashCode && KeyComparer . Equals ( entry1 . Key , key ) )
398405 return true ;
399406
400407 var index2 = ( hashCode >> 8 ) & _capacityMask ;
401408 ref Entry entry2 = ref _table2 [ index2 ] ;
402- return entry2 . HashCode == hashCode && EqualityComparer < TKey > . Default . Equals ( entry2 . Key , key ) ;
409+ return entry2 . HashCode == hashCode && KeyComparer . Equals ( entry2 . Key , key ) ;
403410 }
404411
405412 [ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
@@ -428,7 +435,7 @@ public bool Remove(TKey key)
428435
429436 var index1 = hashCode & _capacityMask ;
430437 ref Entry entry1 = ref _table1 [ index1 ] ;
431- if ( entry1 . HashCode == hashCode && EqualityComparer < TKey > . Default . Equals ( entry1 . Key , key ) )
438+ if ( entry1 . HashCode == hashCode && KeyComparer . Equals ( entry1 . Key , key ) )
432439 {
433440 entry1 . IsOccupied = false ;
434441 _count -- ;
@@ -438,7 +445,7 @@ public bool Remove(TKey key)
438445
439446 var index2 = ( hashCode >> 8 ) & _capacityMask ;
440447 ref Entry entry2 = ref _table2 [ index2 ] ;
441- if ( entry2 . HashCode == hashCode && EqualityComparer < TKey > . Default . Equals ( entry2 . Key , key ) )
448+ if ( entry2 . HashCode == hashCode && KeyComparer . Equals ( entry2 . Key , key ) )
442449 {
443450 entry2 . IsOccupied = false ;
444451 _count -- ;
0 commit comments