From b79b428b452df4c26b4de1d6d52dca96ffc69485 Mon Sep 17 00:00:00 2001 From: "google-labs-jules[bot]" <161369871+google-labs-jules[bot]@users.noreply.github.com> Date: Sat, 20 Jun 2026 19:18:12 +0000 Subject: [PATCH] perf: optimize redundant math in ArenaDictionary probing loop Updates all the probing loops in `ArenaDictionary` to extract the `buckets[index] - 1` math calculation into a single `entryIdx` variable instead of checking for `0` equality, re-accessing it, and calculating the `-1` offset multiple times. Benchmarks show a positive impact by eliminating this redundant work within the high-traffic loops. Co-authored-by: myarichuk <1473701+myarichuk@users.noreply.github.com> --- src/SharpArena/Collections/ArenaDictionary.cs | 78 +++++++++---------- 1 file changed, 39 insertions(+), 39 deletions(-) diff --git a/src/SharpArena/Collections/ArenaDictionary.cs b/src/SharpArena/Collections/ArenaDictionary.cs index 6c5e7bd..fd4fe19 100644 --- a/src/SharpArena/Collections/ArenaDictionary.cs +++ b/src/SharpArena/Collections/ArenaDictionary.cs @@ -86,10 +86,10 @@ private readonly int FindBucket(TKey key) while (true) { - int entryIdxPlusOne = buckets[index]; - if (entryIdxPlusOne == 0) return (int)index; + int entryIdx = buckets[index] - 1; + if (entryIdx < 0) return (int)index; - if (keys[entryIdxPlusOne - 1].Equals(key)) return (int)index; + if (keys[entryIdx].Equals(key)) return (int)index; index = (index + 1) & mask; } @@ -167,8 +167,8 @@ public bool TryAdd(TKey key, TValue value) } int bucketIdx = FindBucket(key); - int entryIdxPlusOne = _header->Buckets[bucketIdx]; - if (entryIdxPlusOne != 0) return false; + int entryIdx = _header->Buckets[bucketIdx] - 1; + if (entryIdx >= 0) return false; int newEntryIdx = _header->Count++; _header->Buckets[bucketIdx] = newEntryIdx + 1; @@ -186,8 +186,8 @@ private void AddOrUpdate(TKey key, TValue value) } int bucketIdx = FindBucket(key); - int entryIdxPlusOne = _header->Buckets[bucketIdx]; - if (entryIdxPlusOne == 0) + int entryIdx = _header->Buckets[bucketIdx] - 1; + if (entryIdx < 0) { int newEntryIdx = _header->Count++; _header->Buckets[bucketIdx] = newEntryIdx + 1; @@ -196,7 +196,7 @@ private void AddOrUpdate(TKey key, TValue value) } else { - ((TValue*)_header->Values)[entryIdxPlusOne - 1] = value; + ((TValue*)_header->Values)[entryIdx] = value; } } @@ -264,9 +264,9 @@ public readonly bool ContainsKey(ReadOnlySpan key) while (true) { - int entryIdxPlusOne = buckets[index]; - if (entryIdxPlusOne == 0) return false; - if (keys[entryIdxPlusOne - 1].Equals(key)) return true; + int entryIdx = buckets[index] - 1; + if (entryIdx < 0) return false; + if (keys[entryIdx].Equals(key)) return true; index = (index + 1) & mask; } } @@ -290,9 +290,9 @@ public readonly bool ContainsKey(ReadOnlySpan key) uint index = hash & mask; while (true) { - int entryIdxPlusOne = buckets[index]; - if (entryIdxPlusOne == 0) return false; - if (keys[entryIdxPlusOne - 1].Equals(byteKey)) return true; + int entryIdx = buckets[index] - 1; + if (entryIdx < 0) return false; + if (keys[entryIdx].Equals(byteKey)) return true; index = (index + 1) & mask; } } @@ -323,9 +323,9 @@ public readonly bool ContainsKey(ReadOnlySpan key) uint index = hash & mask; while (true) { - int entryIdxPlusOne = buckets[index]; - if (entryIdxPlusOne == 0) return false; - if (keys[entryIdxPlusOne - 1].Equals(key)) return true; + int entryIdx = buckets[index] - 1; + if (entryIdx < 0) return false; + if (keys[entryIdx].Equals(key)) return true; index = (index + 1) & mask; } } @@ -350,9 +350,9 @@ public readonly bool ContainsKey(ReadOnlySpan key) while (true) { - int entryIdxPlusOne = buckets[index]; - if (entryIdxPlusOne == 0) return false; - if (keys[entryIdxPlusOne - 1].Equals(charKey)) return true; + int entryIdx = buckets[index] - 1; + if (entryIdx < 0) return false; + if (keys[entryIdx].Equals(charKey)) return true; index = (index + 1) & mask; } } @@ -375,10 +375,10 @@ public readonly bool TryGetValue(TKey key, out TValue value) { CheckAlive(); int bucketIdx = FindBucket(key); - int entryIdxPlusOne = _header->Buckets[bucketIdx]; - if (entryIdxPlusOne != 0) + int entryIdx = _header->Buckets[bucketIdx] - 1; + if (entryIdx >= 0) { - value = ((TValue*)_header->Values)[entryIdxPlusOne - 1]; + value = ((TValue*)_header->Values)[entryIdx]; return true; } value = default; @@ -408,11 +408,11 @@ public readonly bool TryGetValue(ReadOnlySpan key, out TValue value) while (true) { - int entryIdxPlusOne = buckets[index]; - if (entryIdxPlusOne == 0) break; - if (keys[entryIdxPlusOne - 1].Equals(key)) + int entryIdx = buckets[index] - 1; + if (entryIdx < 0) break; + if (keys[entryIdx].Equals(key)) { - value = values[entryIdxPlusOne - 1]; + value = values[entryIdx]; return true; } index = (index + 1) & mask; @@ -439,11 +439,11 @@ public readonly bool TryGetValue(ReadOnlySpan key, out TValue value) uint index = hash & mask; while (true) { - int entryIdxPlusOne = buckets[index]; - if (entryIdxPlusOne == 0) break; - if (keys[entryIdxPlusOne - 1].Equals(byteKey)) + int entryIdx = buckets[index] - 1; + if (entryIdx < 0) break; + if (keys[entryIdx].Equals(byteKey)) { - value = values[entryIdxPlusOne - 1]; + value = values[entryIdx]; return true; } index = (index + 1) & mask; @@ -479,11 +479,11 @@ public readonly bool TryGetValue(ReadOnlySpan key, out TValue value) uint index = hash & mask; while (true) { - int entryIdxPlusOne = buckets[index]; - if (entryIdxPlusOne == 0) break; - if (keys[entryIdxPlusOne - 1].Equals(key)) + int entryIdx = buckets[index] - 1; + if (entryIdx < 0) break; + if (keys[entryIdx].Equals(key)) { - value = values[entryIdxPlusOne - 1]; + value = values[entryIdx]; return true; } index = (index + 1) & mask; @@ -511,11 +511,11 @@ public readonly bool TryGetValue(ReadOnlySpan key, out TValue value) while (true) { - int entryIdxPlusOne = buckets[index]; - if (entryIdxPlusOne == 0) break; - if (keys[entryIdxPlusOne - 1].Equals(charKey)) + int entryIdx = buckets[index] - 1; + if (entryIdx < 0) break; + if (keys[entryIdx].Equals(charKey)) { - value = values[entryIdxPlusOne - 1]; + value = values[entryIdx]; return true; } index = (index + 1) & mask;