Skip to content

Commit 3305c6a

Browse files
committed
[Count] use visitor concept.
1 parent beb5879 commit 3305c6a

File tree

7 files changed

+145
-56
lines changed

7 files changed

+145
-56
lines changed

Documents/BenchmarksResults/ArrayWhereCount.md

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,8 @@ Intel Core i7-7700 CPU 3.60GHz (Kaby Lake), 1 CPU, 8 logical and 4 physical core
1616
```
1717
| Method | Mean | Error | StdDev | Ratio | RatioSD | Gen 0 | Gen 1 | Gen 2 | Allocated |
1818
|------------------------------- |----------:|----------:|----------:|------:|--------:|------:|------:|------:|----------:|
19-
| HandmadedCode | 9.018 μs | 0.1786 μs | 0.3442 μs | 1.00 | 0.00 | - | - | - | - |
20-
| SysLinq | 28.411 μs | 0.1726 μs | 0.1614 μs | 3.13 | 0.12 | - | - | - | 48 B |
21-
| StructLinqWithDelegate | 31.017 μs | 0.6127 μs | 1.5259 μs | 3.47 | 0.24 | - | - | - | 64 B |
22-
| StructLinqWithDelegateZeoAlloc | 30.736 μs | 0.6101 μs | 1.5195 μs | 3.42 | 0.25 | - | - | - | - |
23-
| StructLinqWithFunction | 16.965 μs | 0.3245 μs | 0.4104 μs | 1.87 | 0.09 | - | - | - | - |
19+
| HandmadedCode | 7.818 μs | 0.0381 μs | 0.0338 μs | 1.00 | 0.00 | - | - | - | - |
20+
| SysLinq | 28.221 μs | 0.3126 μs | 0.2771 μs | 3.61 | 0.04 | - | - | - | 48 B |
21+
| StructLinqWithDelegate | 25.198 μs | 0.1475 μs | 0.1232 μs | 3.22 | 0.02 | - | - | - | 64 B |
22+
| StructLinqWithDelegateZeoAlloc | 27.106 μs | 0.1202 μs | 0.1066 μs | 3.47 | 0.02 | - | - | - | - |
23+
| StructLinqWithFunction | 7.768 μs | 0.0525 μs | 0.0491 μs | 0.99 | 0.01 | - | - | - | - |

src/StructLinq.Tests/CountTests.cs renamed to src/StructLinq.Tests/CollectionCountTests.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33

44
namespace StructLinq.Tests
55
{
6-
public class CountTests
6+
public class CollectionCountTests
77
{
88
[Fact]
99
public void ShouldReturnIntCount()
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
using FluentAssertions;
2+
using Xunit;
3+
4+
namespace StructLinq.Tests
5+
{
6+
public class EnumerableCountTests
7+
{
8+
[Fact]
9+
public void ShouldReturnIntCount()
10+
{
11+
var expected = 100;
12+
var count = StructEnumerable.Range(0, expected).Where(x=> true).Count();
13+
count.Should().Be(expected);
14+
}
15+
16+
[Fact]
17+
public void ShouldReturnIntCount2()
18+
{
19+
var expected = 100;
20+
var count = StructEnumerable.Range(0, expected).Where(x=> true).Count(x=> x);
21+
count.Should().Be(expected);
22+
}
23+
24+
[Fact]
25+
public void ShouldReturnUIntCount()
26+
{
27+
uint expected = 100;
28+
var count = StructEnumerable.Range(0, (int) expected).Where(x=> true).UIntCount();
29+
count.Should().Be(expected);
30+
}
31+
32+
[Fact]
33+
public void ShouldReturnUIntCount2()
34+
{
35+
uint expected = 100;
36+
var count = StructEnumerable.Range(0, (int) expected).Where(x=> true).UIntCount(x => x);
37+
count.Should().Be(expected);
38+
}
39+
40+
[Fact]
41+
public void ShouldReturnLongCount()
42+
{
43+
long expected = 100;
44+
var count = StructEnumerable.Range(0, (int)expected).Where(x=> true).LongCount();
45+
count.Should().Be(expected);
46+
}
47+
48+
[Fact]
49+
public void ShouldReturnLongCount2()
50+
{
51+
long expected = 100;
52+
var count = StructEnumerable.Range(0, (int)expected).Where(x=> true).LongCount(x => x);
53+
count.Should().Be(expected);
54+
}
55+
56+
}
57+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
using System.Runtime.CompilerServices;
2+
3+
namespace StructLinq.Count
4+
{
5+
internal struct IntCountVisitor<T> : IVisitor<T>
6+
{
7+
public int Count;
8+
9+
public IntCountVisitor(int count)
10+
{
11+
Count = count;
12+
}
13+
14+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
15+
public bool Visit(T input)
16+
{
17+
Count++;
18+
return true;
19+
}
20+
}
21+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
using System.Runtime.CompilerServices;
2+
3+
namespace StructLinq.Count
4+
{
5+
internal struct LongCountVisitor<T> : IVisitor<T>
6+
{
7+
public long Count;
8+
9+
public LongCountVisitor(long count)
10+
{
11+
Count = count;
12+
}
13+
14+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
15+
public bool Visit(T input)
16+
{
17+
Count++;
18+
return true;
19+
}
20+
}
21+
}

src/StructLinq/Count/StructEnumerable.Count.cs

Lines changed: 19 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -4,98 +4,68 @@
44

55
using System;
66
using System.Runtime.CompilerServices;
7+
using StructLinq.Count;
78

89
// ReSharper disable once CheckNamespace
910
namespace StructLinq
1011
{
1112
public static partial class StructEnumerable
1213
{
13-
[MethodImpl(MethodImplOptions.AggressiveInlining)]
14-
private static int IntCount<T,TEnumerator>(ref TEnumerator enumerator)
15-
where TEnumerator : struct, IStructEnumerator<T>
16-
{
17-
int count = 0;
18-
while (enumerator.MoveNext())
19-
{
20-
count++;
21-
}
22-
enumerator.Dispose();
23-
return count;
24-
}
25-
2614
[MethodImpl(MethodImplOptions.AggressiveInlining)]
2715
public static int Count<T, TEnumerator>(this IStructEnumerable<T, TEnumerator> enumerable)
2816
where TEnumerator : struct, IStructEnumerator<T>
2917
{
30-
var structEnumerator = enumerable.GetEnumerator();
31-
return IntCount<T, TEnumerator>(ref structEnumerator);
18+
var visitor = new IntCountVisitor<T>(0);
19+
enumerable.Visit(ref visitor);
20+
return visitor.Count;
3221
}
3322

3423
[MethodImpl(MethodImplOptions.AggressiveInlining)]
3524
public static int Count<T, TEnumerable, TEnumerator>(this TEnumerable enumerable, Func<TEnumerable, IStructEnumerable<T, TEnumerator>> _)
3625
where TEnumerable : IStructEnumerable<T, TEnumerator>
3726
where TEnumerator : struct, IStructEnumerator<T>
3827
{
39-
var enumerator = enumerable.GetEnumerator();
40-
return IntCount<T, TEnumerator>(ref enumerator);
41-
}
42-
43-
private static long LongCount<T, TEnumerator>(ref TEnumerator enumerator)
44-
where TEnumerator : struct, IStructEnumerator<T>
45-
{
46-
long count = 0;
47-
while (enumerator.MoveNext())
48-
{
49-
count++;
50-
}
51-
enumerator.Dispose();
52-
return count;
28+
var visitor = new IntCountVisitor<T>(0);
29+
enumerable.Visit(ref visitor);
30+
return visitor.Count;
5331
}
5432

5533
[MethodImpl(MethodImplOptions.AggressiveInlining)]
5634
public static long LongCount<T, TEnumerator>(this IStructEnumerable<T, TEnumerator> enumerable)
5735
where TEnumerator : struct, IStructEnumerator<T>
5836
{
59-
var structEnumerator = enumerable.GetEnumerator();
60-
return LongCount<T, TEnumerator>(ref structEnumerator);
37+
var visitor = new LongCountVisitor<T>(0);
38+
enumerable.Visit(ref visitor);
39+
return visitor.Count;
6140
}
6241

6342
[MethodImpl(MethodImplOptions.AggressiveInlining)]
6443
public static long LongCount<T, TEnumerable, TEnumerator>(this TEnumerable enumerable, Func<TEnumerable, IStructEnumerable<T, TEnumerator>> _)
6544
where TEnumerable : struct, IStructEnumerable<T, TEnumerator>
6645
where TEnumerator : struct, IStructEnumerator<T>
6746
{
68-
var enumerator = enumerable.GetEnumerator();
69-
return LongCount<T, TEnumerator>(ref enumerator);
70-
}
71-
72-
private static uint UintCount<T, TEnumerator>(ref TEnumerator enumerator)
73-
where TEnumerator : struct, IStructEnumerator<T>
74-
{
75-
uint count = 0;
76-
while (enumerator.MoveNext())
77-
{
78-
count++;
79-
}
80-
enumerator.Dispose();
81-
return count;
47+
var visitor = new LongCountVisitor<T>(0);
48+
enumerable.Visit(ref visitor);
49+
return visitor.Count;
8250
}
8351

8452
[MethodImpl(MethodImplOptions.AggressiveInlining)]
8553
public static uint UIntCount<T, TEnumerator>(this IStructEnumerable<T, TEnumerator> enumerable)
8654
where TEnumerator : struct, IStructEnumerator<T>
8755
{
88-
var structEnumerator = enumerable.GetEnumerator();
89-
return UintCount<T, TEnumerator>(ref structEnumerator);
56+
var visitor = new UIntCountVisitor<T>(0);
57+
enumerable.Visit(ref visitor);
58+
return visitor.Count;
9059
}
9160

9261
[MethodImpl(MethodImplOptions.AggressiveInlining)]
9362
public static uint UIntCount<T, TEnumerable, TEnumerator>(this TEnumerable enumerable, Func<TEnumerable, IStructEnumerable<T, TEnumerator>> _)
9463
where TEnumerable : struct, IStructEnumerable<T, TEnumerator>
9564
where TEnumerator : struct, IStructEnumerator<T>
9665
{
97-
var enumerator = enumerable.GetEnumerator();
98-
return UintCount<T, TEnumerator>(ref enumerator);
66+
var visitor = new UIntCountVisitor<T>(0);
67+
enumerable.Visit(ref visitor);
68+
return visitor.Count;
9969
}
10070

10171
[MethodImpl(MethodImplOptions.AggressiveInlining)]
@@ -142,6 +112,5 @@ public static long LongCount<T, TEnumerator>(this IStructCollection<T, TEnumerat
142112
{
143113
return collection.Count;
144114
}
145-
146115
}
147116
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
using System.Runtime.CompilerServices;
2+
3+
namespace StructLinq.Count
4+
{
5+
internal struct UIntCountVisitor<T> : IVisitor<T>
6+
{
7+
public uint Count;
8+
9+
public UIntCountVisitor(uint count)
10+
{
11+
Count = count;
12+
}
13+
14+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
15+
public bool Visit(T input)
16+
{
17+
Count++;
18+
return true;
19+
}
20+
}
21+
}

0 commit comments

Comments
 (0)