Skip to content
This repository was archived by the owner on Jan 23, 2023. It is now read-only.

Commit 6cb9a6f

Browse files
mikednjkotas
authored andcommitted
Make some Dictionary code smaller (#10993)
Store a reference to the relevant entry at the start of the loop to avoid indexing `entries` multiple times. This avoids some redundant range checks in `Remove` and allows the elimination of a duplicate `index++` in `Enumerator.MoveNext`. Saves ~7KB of code.
1 parent dbc3557 commit 6cb9a6f

File tree

1 file changed

+42
-32
lines changed

1 file changed

+42
-32
lines changed

src/mscorlib/src/System/Collections/Generic/Dictionary.cs

Lines changed: 42 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -428,8 +428,7 @@ private bool TryInsert(TKey key, TValue value, InsertionBehavior behavior)
428428

429429
if (buckets == null) Initialize(0);
430430
int hashCode = comparer.GetHashCode(key) & 0x7FFFFFFF;
431-
int targetBucket = hashCode % buckets.Length;
432-
431+
int targetBucket = hashCode % buckets.Length;
433432
#if FEATURE_RANDOMIZED_STRING_HASHING
434433
int collisionCount = 0;
435434
#endif
@@ -452,7 +451,6 @@ private bool TryInsert(TKey key, TValue value, InsertionBehavior behavior)
452451

453452
return false;
454453
}
455-
456454
#if FEATURE_RANDOMIZED_STRING_HASHING
457455
collisionCount++;
458456
#endif
@@ -599,27 +597,33 @@ public bool Remove(TKey key)
599597
int hashCode = comparer.GetHashCode(key) & 0x7FFFFFFF;
600598
int bucket = hashCode % buckets.Length;
601599
int last = -1;
602-
for (int i = buckets[bucket]; i >= 0; last = i, i = entries[i].next)
600+
int i = buckets[bucket];
601+
while (i >= 0)
603602
{
604-
if (entries[i].hashCode == hashCode && comparer.Equals(entries[i].key, key))
603+
ref Entry entry = ref entries[i];
604+
605+
if (entry.hashCode == hashCode && comparer.Equals(entry.key, key))
605606
{
606607
if (last < 0)
607608
{
608-
buckets[bucket] = entries[i].next;
609+
buckets[bucket] = entry.next;
609610
}
610611
else
611612
{
612-
entries[last].next = entries[i].next;
613+
entries[last].next = entry.next;
613614
}
614-
entries[i].hashCode = -1;
615-
entries[i].next = freeList;
616-
entries[i].key = default(TKey);
617-
entries[i].value = default(TValue);
615+
entry.hashCode = -1;
616+
entry.next = freeList;
617+
entry.key = default(TKey);
618+
entry.value = default(TValue);
618619
freeList = i;
619620
freeCount++;
620621
version++;
621622
return true;
622623
}
624+
625+
last = i;
626+
i = entry.next;
623627
}
624628
}
625629
return false;
@@ -640,30 +644,36 @@ public bool Remove(TKey key, out TValue value)
640644
int hashCode = comparer.GetHashCode(key) & 0x7FFFFFFF;
641645
int bucket = hashCode % buckets.Length;
642646
int last = -1;
643-
for (int i = buckets[bucket]; i >= 0; last = i, i = entries[i].next)
647+
int i = buckets[bucket];
648+
while (i >= 0)
644649
{
645-
if (entries[i].hashCode == hashCode && comparer.Equals(entries[i].key, key))
650+
ref Entry entry = ref entries[i];
651+
652+
if (entry.hashCode == hashCode && comparer.Equals(entry.key, key))
646653
{
647654
if (last < 0)
648655
{
649-
buckets[bucket] = entries[i].next;
656+
buckets[bucket] = entry.next;
650657
}
651658
else
652659
{
653-
entries[last].next = entries[i].next;
660+
entries[last].next = entry.next;
654661
}
655662

656-
value = entries[i].value;
663+
value = entry.value;
657664

658-
entries[i].hashCode = -1;
659-
entries[i].next = freeList;
660-
entries[i].key = default(TKey);
661-
entries[i].value = default(TValue);
665+
entry.hashCode = -1;
666+
entry.next = freeList;
667+
entry.key = default(TKey);
668+
entry.value = default(TValue);
662669
freeList = i;
663670
freeCount++;
664671
version++;
665672
return true;
666673
}
674+
675+
last = i;
676+
i = entry.next;
667677
}
668678
}
669679
value = default(TValue);
@@ -955,13 +965,13 @@ public bool MoveNext()
955965
// dictionary.count+1 could be negative if dictionary.count is Int32.MaxValue
956966
while ((uint)index < (uint)dictionary.count)
957967
{
958-
if (dictionary.entries[index].hashCode >= 0)
968+
ref Entry entry = ref dictionary.entries[index++];
969+
970+
if (entry.hashCode >= 0)
959971
{
960-
current = new KeyValuePair<TKey, TValue>(dictionary.entries[index].key, dictionary.entries[index].value);
961-
index++;
972+
current = new KeyValuePair<TKey, TValue>(entry.key, entry.value);
962973
return true;
963974
}
964-
index++;
965975
}
966976

967977
index = dictionary.count + 1;
@@ -1231,13 +1241,13 @@ public bool MoveNext()
12311241

12321242
while ((uint)index < (uint)dictionary.count)
12331243
{
1234-
if (dictionary.entries[index].hashCode >= 0)
1244+
ref Entry entry = ref dictionary.entries[index++];
1245+
1246+
if (entry.hashCode >= 0)
12351247
{
1236-
currentKey = dictionary.entries[index].key;
1237-
index++;
1248+
currentKey = entry.key;
12381249
return true;
12391250
}
1240-
index++;
12411251
}
12421252

12431253
index = dictionary.count + 1;
@@ -1459,13 +1469,13 @@ public bool MoveNext()
14591469

14601470
while ((uint)index < (uint)dictionary.count)
14611471
{
1462-
if (dictionary.entries[index].hashCode >= 0)
1472+
ref Entry entry = ref dictionary.entries[index++];
1473+
1474+
if (entry.hashCode >= 0)
14631475
{
1464-
currentValue = dictionary.entries[index].value;
1465-
index++;
1476+
currentValue = entry.value;
14661477
return true;
14671478
}
1468-
index++;
14691479
}
14701480
index = dictionary.count + 1;
14711481
currentValue = default(TValue);

0 commit comments

Comments
 (0)