Optimize ImmutableSortedSet<T>.SetEquals to avoid unnecessary allocations#126549
Conversation
f9f1622 to
1c158bc
Compare
1c158bc to
827bfda
Compare
666ab6c to
41c75bf
Compare
41c75bf to
390c55b
Compare
132ed04 to
9afc5d0
Compare
9afc5d0 to
0302e72
Compare
|
Just gentle ping in case this fell through the cracks. |
0302e72 to
5697f96
Compare
5697f96 to
9ebab32
Compare
|
The count validation has been moved out of This refactoring enables us to implement logic like the following: private static bool IsProperSubsetOf(IEnumerable<T> other, ImmutableSortedSet<T> source)
{
Requires.NotNull(other, nameof(other));
if (Source.IsEmpty)
{
return other.Any();
}
if (other is ICollection<T> otherAsICollectionGeneric)
{
// We check for < instead of != because other is not guaranteed to be a set, it could be a collection with duplicates.
if (otherAsICollectionGeneric.Count <= source.Count)
{
return false;
}
switch (other)
{
case ImmutableSortedSet<T> otherAsImmutableSortedSet:
if (source.EqualityComparer.Equals(otherAsImmutableSortedSet.KeyComparer))
{
return SetEqualsWithImmutableSortedset(otherAsImmutableSortedSet, source);
}
break;
case SortedSet<T> otherAsSortedset:
if (source.EqualityComparer.Equals(otherAsSortedset.Comparer))
{
return SetEqualsWithSortedset(otherAsHashset, source);
}
break;
}
}
else if (other is ICollection otherAsICollection && otherAsICollection.Count <= source.Count)
{
return false;
}
var otherSet = new SortedSet<T>(other, origin.EqualityComparer);
if (otherSet.Count <= source.Count)
{
return false;
}
return SetEqualsWithSortedset(otherSet, source);
} |
9ebab32 to
0c8368d
Compare
0c8368d to
242e272
Compare
242e272 to
f109551
Compare
|
CI seems to be stuck on infrastructure issues. Could someone please trigger a re-run for the failed checks? Thanks! |
|
/ba-g test failures are unrelated |
0bf253a to
f86ad5b
Compare
f86ad5b to
c08493f
Compare
|
Gentle ping @eiriktsarpalis. The changes have been updated based on the feedback and the previous approval. The CI checks seem to be passing now (except for unrelated failures). Please let me know if there's anything else needed to get this merged. Thanks! |
|
/ba-g test failures are unrelated |
Part of #127279
Summary
ImmutableSortedSet<T>.SetEqualsalways creates a new intermediateSortedSet<T>for theothercollection, leading to avoidable allocations and GC pressure, especially for large datasetsOptimization Logic
otheris anImmutableSortedSetorSortedSet, triggering optimized logic only if theirComparermatches.ReferenceEqualscheck and leveragesICollectionto returnfalseearly ifother.Countis less thanthis.Count..Contains()check with a dual-enumeratorwhileloop. This leverages the sorted nature of both sets to achievenew SortedSet<T>is required for generalIEnumerabletypes, the final comparison now uses the same efficientClick to expand Benchmark Source Code
Click to expand Benchmark Results
Benchmark Results (Before Optimization)
Benchmark Results (After Optimization)
Performance Analysis Summary (100,000 Elements)
Performance Analysis Summary (100,000 Elements)
Testing
In addition to the fix, I have added comprehensive unit tests covering various scenarios to ensure correctness:
SetEqualsreturnstruewhen logically equal but with different comparers, andfalsewhen logically different.List<T>with duplicate elements.SetEqualsstill performs early-exit whenother.Count < source.Count.