Skip to content

Commit 1f9373c

Browse files
committed
[Except] Implement Visitor to improve performance.
1 parent e13cb69 commit 1f9373c

File tree

3 files changed

+52
-11
lines changed

3 files changed

+52
-11
lines changed

Documents/BenchmarksResults/Except.md

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,10 @@ Intel Core i7-7700 CPU 3.60GHz (Kaby Lake), 1 CPU, 8 logical and 4 physical core
1414

1515

1616
```
17-
| Method | Mean | Error | StdDev | Ratio | Gen 0 | Gen 1 | Gen 2 | Allocated |
18-
|---------------------------------- |---------:|--------:|--------:|------:|--------:|--------:|--------:|----------:|
19-
| Linq | 405.5 μs | 4.10 μs | 3.64 μs | 1.00 | 90.8203 | 90.8203 | 90.8203 | 524848 B |
20-
| StructLinq | 169.1 μs | 1.25 μs | 1.05 μs | 0.42 | - | - | - | 64 B |
21-
| StructLinqZeroAlloc | 169.5 μs | 1.44 μs | 1.28 μs | 0.42 | - | - | - | - |
22-
| StructLinqZeroAllocAndComparer | 148.6 μs | 0.81 μs | 0.76 μs | 0.37 | - | - | - | - |
23-
| StructLinqZeroAllocAndComparerSum | 129.5 μs | 0.62 μs | 0.52 μs | 0.32 | - | - | - | - |
17+
| Method | Mean | Error | StdDev | Ratio | Gen 0 | Gen 1 | Gen 2 | Allocated |
18+
|---------------------------------- |---------:|--------:|---------:|------:|--------:|--------:|--------:|----------:|
19+
| Linq | 501.7 μs | 9.40 μs | 16.47 μs | 1.00 | 90.8203 | 90.8203 | 90.8203 | 524848 B |
20+
| StructLinq | 176.3 μs | 0.64 μs | 0.57 μs | 0.36 | - | - | - | 64 B |
21+
| StructLinqZeroAlloc | 177.2 μs | 1.65 μs | 1.54 μs | 0.36 | - | - | - | - |
22+
| StructLinqZeroAllocAndComparer | 147.7 μs | 1.51 μs | 1.34 μs | 0.30 | - | - | - | - |
23+
| StructLinqZeroAllocAndComparerSum | 113.7 μs | 1.06 μs | 0.94 μs | 0.23 | - | - | - | - |

src/StructLinq.Tests/ExceptTests.cs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,5 +28,16 @@ public void SameAsSystem()
2828
var value = array1.ToStructEnumerable().Except(array2.ToStructEnumerable()).ToArray();
2929
Assert.Equal(expected, value);
3030
}
31+
32+
[Fact]
33+
public void SameAsSystemEnumerable()
34+
{
35+
var array1 = new int[] { 1, 1, 2, 3, 4, 4, 5 };
36+
var array2 = new int[] { 4, 5, 6, 6, 7, 8, 9 };
37+
38+
var expected = array1.Except(array2);
39+
var value = array1.ToStructEnumerable().Except(array2.ToStructEnumerable()).ToEnumerable();
40+
Assert.Equal(expected, value);
41+
}
3142
}
3243
}

src/StructLinq/Except/ExceptEnumerable.cs

Lines changed: 34 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -44,13 +44,43 @@ public ExceptEnumerator<T, TEnumerator1, TEnumerator2, TComparer> GetEnumerator(
4444
public VisitStatus Visit<TVisitor>(ref TVisitor visitor)
4545
where TVisitor : IVisitor<T>
4646
{
47-
foreach (var input in this)
47+
var exceptVisitor = new ExceptVisitor<TVisitor>(capacity, bucketPool, slotPool, comparer, ref visitor);
48+
enumerable2.Visit(ref exceptVisitor);
49+
exceptVisitor.Add = false;
50+
var visitStatus = enumerable1.Visit(ref exceptVisitor);
51+
visitor = exceptVisitor.Visitor;
52+
exceptVisitor.Dispose();
53+
return visitStatus;
54+
}
55+
56+
private struct ExceptVisitor<TVisitor> : IVisitor<T>
57+
where TVisitor : IVisitor<T>
58+
{
59+
public TVisitor Visitor;
60+
public bool Add;
61+
private PooledSet<T, TComparer> set;
62+
63+
public ExceptVisitor(int capacity, ArrayPool<int> bucketPool, ArrayPool<Slot<T>> slotPool, TComparer comparer, ref TVisitor visitor)
4864
{
49-
if (!visitor.Visit(input))
50-
return VisitStatus.VisitorFinished;
65+
this.Visitor = visitor;
66+
set = new PooledSet<T, TComparer>(capacity, bucketPool, slotPool, comparer);
67+
Add = true;
5168
}
5269

53-
return VisitStatus.EnumeratorFinished;
70+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
71+
public bool Visit(T input)
72+
{
73+
if (!Add)
74+
return !set.AddIfNotPresent(input) || Visitor.Visit(input);
75+
set.AddIfNotPresent(input);
76+
return true;
77+
}
78+
79+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
80+
public void Dispose()
81+
{
82+
set.Dispose();
83+
}
5484
}
5585
}
5686
}

0 commit comments

Comments
 (0)