Skip to content

Commit 1ea6f28

Browse files
committed
update Skip and Take
1 parent 94b144f commit 1ea6f28

30 files changed

+519
-136
lines changed
Lines changed: 139 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,139 @@
1+
// LinqGen.Benchmarks, Maxwell Keonwoo Kang <code.athei@gmail.com>, 2022
2+
3+
using BenchmarkDotNet.Attributes;
4+
using StructLinq;
5+
using Cathei.LinqGen;
6+
using NetFabric.Hyperlinq;
7+
8+
namespace Cathei.LinqGen.Benchmarks.Cases;
9+
10+
[MemoryDiagnoser]
11+
public class ReferenceWhereSelectSum
12+
{
13+
private const int Count = 10_000;
14+
15+
private static List<ReferenceValue<int>> TestData;
16+
17+
static ReferenceWhereSelectSum()
18+
{
19+
TestData = new List<ReferenceValue<int>>();
20+
21+
for (int i = 0; i < Count; ++i)
22+
TestData.Add(new ReferenceValue<int>(i));
23+
}
24+
25+
[Benchmark]
26+
public double ForEachLoop()
27+
{
28+
double sum = 0;
29+
30+
foreach (var i in TestData)
31+
{
32+
if (i.Value % 2 == 0)
33+
sum += i.Value * 2.0;
34+
}
35+
36+
return sum;
37+
}
38+
39+
[Benchmark(Baseline = true)]
40+
public double Linq()
41+
{
42+
return TestData
43+
.Where(x => x.Value % 2 == 0)
44+
.Select(x=> x.Value * 2.0)
45+
.Sum();
46+
}
47+
48+
[Benchmark]
49+
public double LinqGenDelegate()
50+
{
51+
return TestData.Specialize()
52+
.Where(x => x.Value % 2 == 0)
53+
.Select(x => x.Value * 2.0)
54+
.Sum();
55+
}
56+
57+
[Benchmark]
58+
public double LinqGenStruct()
59+
{
60+
var predicate = new Predicate();
61+
var selector = new Selector();
62+
63+
return TestData.Specialize()
64+
.Where(predicate)
65+
.Select(selector)
66+
.Sum();
67+
}
68+
69+
[Benchmark]
70+
public double StructLinqDelegate()
71+
{
72+
return TestData.ToStructEnumerable()
73+
.Where(x => x.Value % 2 == 0)
74+
.Select(x => x.Value * 2.0)
75+
.Sum();
76+
}
77+
78+
[Benchmark]
79+
public double StructLinqStruct()
80+
{
81+
var predicate = new Predicate();
82+
var selector = new Selector();
83+
84+
return TestData.ToStructEnumerable()
85+
.Where(ref predicate, x => x)
86+
.Select(ref selector, x => x, x => x)
87+
.Sum(x=> x);
88+
}
89+
90+
[Benchmark]
91+
public double HyperLinqDelegate()
92+
{
93+
return TestData.AsValueEnumerable()
94+
.Where(x => x.Value % 2 == 0)
95+
.Select(x => x.Value * 2.0)
96+
.Sum();
97+
}
98+
99+
[Benchmark]
100+
public double HyperLinqStruct()
101+
{
102+
return TestData.AsValueEnumerable()
103+
.Where<Predicate>()
104+
.Select<double, Selector>()
105+
.Sum();
106+
}
107+
108+
readonly struct Predicate :
109+
StructLinq.IFunction<ReferenceValue<int>, bool>,
110+
NetFabric.Hyperlinq.IFunction<ReferenceValue<int>, bool>,
111+
IStructFunction<ReferenceValue<int>, bool>
112+
{
113+
public bool Eval(ReferenceValue<int> element)
114+
{
115+
return element.Value % 2 == 0;
116+
}
117+
118+
public bool Invoke(ReferenceValue<int> arg)
119+
{
120+
return arg.Value % 2 == 0;
121+
}
122+
}
123+
124+
readonly struct Selector :
125+
StructLinq.IFunction<ReferenceValue<int>, double>,
126+
NetFabric.Hyperlinq.IFunction<ReferenceValue<int>, double>,
127+
IStructFunction<ReferenceValue<int>, double>
128+
{
129+
public double Eval(ReferenceValue<int> element)
130+
{
131+
return element.Value * 2.0;
132+
}
133+
134+
public double Invoke(ReferenceValue<int> arg)
135+
{
136+
return arg.Value * 2.0;
137+
}
138+
}
139+
}

LinqGen.Benchmarks/Cases/SelectSum.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -59,9 +59,9 @@ public double LinqGenStruct()
5959
var selector = new Selector();
6060

6161
return GenEnumerable
62-
.Range(0, Count)
63-
.Select(selector)
64-
.Sum();
62+
.Range(0, Count)
63+
.Select(selector)
64+
.Sum();
6565
}
6666

6767
[Benchmark]

LinqGen.Benchmarks/CommonTypes.cs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
// LinqGen.Benchmarks, Maxwell Keonwoo Kang <code.athei@gmail.com>, 2022
2+
3+
using BenchmarkDotNet.Attributes;
4+
using StructLinq;
5+
using Cathei.LinqGen;
6+
using NetFabric.Hyperlinq;
7+
8+
namespace Cathei.LinqGen.Benchmarks;
9+
10+
public class ReferenceValue<T>
11+
{
12+
public T Value { get; }
13+
14+
public ReferenceValue(T value)
15+
{
16+
Value = value;
17+
}
18+
}

LinqGen.Generator/CodeGenUtils.cs

Lines changed: 45 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -84,36 +84,41 @@ symbol.TypeArguments[1] is not INamedTypeSymbol resultSignatureSymbol ||
8484

8585
// known type names
8686
public static readonly PredefinedTypeSyntax IntType = PredefinedType(Token(SyntaxKind.IntKeyword));
87-
public static readonly IdentifierNameSyntax EnumeratorName = IdentifierName("Enumerator");
87+
public static readonly IdentifierNameSyntax EnumeratorType = IdentifierName("Enumerator");
8888

8989
// known method names
90-
public static readonly IdentifierNameSyntax InvokeName = IdentifierName("Invoke");
91-
public static readonly IdentifierNameSyntax MoveNextName = IdentifierName("MoveNext");
92-
public static readonly IdentifierNameSyntax DisposeName = IdentifierName("Dispose");
93-
public static readonly IdentifierNameSyntax GetEnumeratorName = IdentifierName("GetEnumerator");
94-
public static readonly IdentifierNameSyntax GetSliceEnumeratorName = IdentifierName("GetSliceEnumerator");
90+
public static readonly IdentifierNameSyntax InvokeMethod = IdentifierName("Invoke");
91+
public static readonly IdentifierNameSyntax MoveNextMethod = IdentifierName("MoveNext");
92+
public static readonly IdentifierNameSyntax DisposeMethod = IdentifierName("Dispose");
93+
public static readonly IdentifierNameSyntax GetEnumeratorMethod = IdentifierName("GetEnumerator");
94+
public static readonly IdentifierNameSyntax GetSliceEnumeratorMethod = IdentifierName("GetSliceEnumerator");
9595

9696
// known property names
97-
public static readonly IdentifierNameSyntax CurrentName = IdentifierName("Current");
98-
public static readonly IdentifierNameSyntax CountName = IdentifierName("Count");
99-
public static readonly IdentifierNameSyntax LengthName = IdentifierName("Length");
97+
public static readonly IdentifierNameSyntax CurrentProperty = IdentifierName("Current");
98+
public static readonly IdentifierNameSyntax CountProperty = IdentifierName("Count");
99+
public static readonly IdentifierNameSyntax LengthProperty = IdentifierName("Length");
100+
public static readonly IdentifierNameSyntax HasValueProperty = IdentifierName("HasValue");
101+
public static readonly IdentifierNameSyntax ValueProperty = IdentifierName("Value");
100102

101103
// custom variable names
102-
public static readonly IdentifierNameSyntax ParentName = IdentifierName("parent");
103-
public static readonly IdentifierNameSyntax SourceName = IdentifierName("source");
104-
public static readonly IdentifierNameSyntax IteratorName = IdentifierName("iter");
105-
public static readonly IdentifierNameSyntax IndexName = IdentifierName("index");
106-
public static readonly IdentifierNameSyntax SelectorName = IdentifierName("select");
107-
public static readonly IdentifierNameSyntax PredicateName = IdentifierName("predicate");
108-
public static readonly IdentifierNameSyntax InitialValueName = IdentifierName("initialValue");
109-
public static readonly IdentifierNameSyntax SkipName = IdentifierName("skip");
110-
public static readonly IdentifierNameSyntax TakeName = IdentifierName("take");
104+
public static readonly IdentifierNameSyntax ParentField = IdentifierName("parent");
105+
public static readonly IdentifierNameSyntax SourceField = IdentifierName("source");
106+
public static readonly IdentifierNameSyntax IteratorField = IdentifierName("iter");
107+
public static readonly IdentifierNameSyntax IndexField = IdentifierName("index");
108+
public static readonly IdentifierNameSyntax SelectorField = IdentifierName("select");
109+
public static readonly IdentifierNameSyntax PredicateField = IdentifierName("predicate");
110+
public static readonly IdentifierNameSyntax InitialValueField = IdentifierName("initialValue");
111+
public static readonly IdentifierNameSyntax SkipField = IdentifierName("skip");
112+
public static readonly IdentifierNameSyntax TakeField = IdentifierName("take");
113+
public static readonly IdentifierNameSyntax ValueField = IdentifierName("value");
111114

112115
public static readonly TypeSyntax VarType = IdentifierName("var");
113116
public static readonly TypeSyntax ObjectType = IdentifierName("object");
114117

115118
public static readonly LiteralExpressionSyntax DefaultLiteral =
116119
SyntaxFactory.LiteralExpression(SyntaxKind.DefaultLiteralExpression);
120+
public static readonly LiteralExpressionSyntax NullLiteral =
121+
SyntaxFactory.LiteralExpression(SyntaxKind.NullLiteralExpression);
117122

118123
public static readonly SyntaxToken UsingKeywordToken = Token(SyntaxKind.UsingKeyword);
119124
public static readonly SyntaxToken SemicolonToken = Token(SyntaxKind.SemicolonToken);
@@ -275,6 +280,11 @@ public static PrefixUnaryExpressionSyntax PreIncrementExpression(ExpressionSynta
275280
return SyntaxFactory.PrefixUnaryExpression(SyntaxKind.PreIncrementExpression, operand);
276281
}
277282

283+
public static PrefixUnaryExpressionSyntax PreDecrementExpression(ExpressionSyntax operand)
284+
{
285+
return SyntaxFactory.PrefixUnaryExpression(SyntaxKind.PreDecrementExpression, operand);
286+
}
287+
278288
public static PrefixUnaryExpressionSyntax LogicalNotExpression(ExpressionSyntax operand)
279289
{
280290
return SyntaxFactory.PrefixUnaryExpression(SyntaxKind.LogicalNotExpression, operand);
@@ -290,11 +300,21 @@ public static BinaryExpressionSyntax GreaterOrEqualExpression(ExpressionSyntax l
290300
return SyntaxFactory.BinaryExpression(SyntaxKind.GreaterThanOrEqualExpression, left, right);
291301
}
292302

303+
public static BinaryExpressionSyntax AddExpression(ExpressionSyntax left, ExpressionSyntax right)
304+
{
305+
return SyntaxFactory.BinaryExpression(SyntaxKind.AddExpression, left, right);
306+
}
307+
293308
public static BinaryExpressionSyntax SubtractExpression(ExpressionSyntax left, ExpressionSyntax right)
294309
{
295310
return SyntaxFactory.BinaryExpression(SyntaxKind.SubtractExpression, left, right);
296311
}
297312

313+
public static BinaryExpressionSyntax NullCoalesce(ExpressionSyntax left, ExpressionSyntax right)
314+
{
315+
return SyntaxFactory.BinaryExpression(SyntaxKind.CoalesceExpression, left, right);
316+
}
317+
298318
public static BinaryExpressionSyntax IsExpression(ExpressionSyntax left, ExpressionSyntax right)
299319
{
300320
return SyntaxFactory.BinaryExpression(SyntaxKind.IsExpression, left, right);
@@ -307,6 +327,13 @@ public static ExpressionSyntax MathMin(ExpressionSyntax left, ExpressionSyntax r
307327
ArgumentList(left, right));
308328
}
309329

330+
public static ExpressionSyntax MathMax(ExpressionSyntax left, ExpressionSyntax right)
331+
{
332+
return SyntaxFactory.InvocationExpression(
333+
MemberAccessExpression(IdentifierName("Math"), IdentifierName("Max")),
334+
ArgumentList(left, right));
335+
}
336+
310337
public static ExpressionSyntax TrueExpression()
311338
{
312339
return SyntaxFactory.LiteralExpression(SyntaxKind.TrueLiteralExpression);

LinqGen.Generator/Instructions/Evaluations/CountEvaluation.cs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ public override IEnumerable<ParameterSyntax> GetParameters()
4848
yield return Parameter(default, default, WithStruct
4949
? IdentifierName($"{TypeParameterPrefix}1")
5050
: FunctionType,
51-
PredicateName.Identifier, default);
51+
PredicateField.Identifier, default);
5252
}
5353
}
5454

@@ -62,19 +62,19 @@ public override BlockSyntax RenderMethodBody()
6262
{
6363
if (FunctionType == null && Upstream!.IsCountable)
6464
{
65-
return Block(ReturnStatement(MemberAccessExpression(SourceName, CountName)));
65+
return Block(ReturnStatement(MemberAccessExpression(SourceField, CountProperty)));
6666
}
6767

6868
var localCountName = IdentifierName("count");
6969

7070
return Block(UsingLocalDeclarationStatement(
71-
IteratorName.Identifier, InvocationExpression(SourceName, GetEnumeratorName)),
71+
IteratorField.Identifier, InvocationExpression(SourceField, GetEnumeratorMethod)),
7272
LocalDeclarationStatement(localCountName.Identifier, LiteralExpression(0)),
73-
WhileStatement(InvocationExpression(IteratorName, MoveNextName),
73+
WhileStatement(InvocationExpression(IteratorField, MoveNextMethod),
7474
FunctionType == null
7575
? ExpressionStatement(PreIncrementExpression(localCountName))
76-
: IfStatement(InvocationExpression(MemberAccessExpression(PredicateName, InvokeName),
77-
ArgumentList(MemberAccessExpression(IteratorName, CurrentName))),
76+
: IfStatement(InvocationExpression(MemberAccessExpression(PredicateField, InvokeMethod),
77+
ArgumentList(MemberAccessExpression(IteratorField, CurrentProperty))),
7878
ExpressionStatement(PreIncrementExpression(localCountName)))),
7979
ReturnStatement(localCountName));
8080
}

LinqGen.Generator/Instructions/Evaluations/Evaluation.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ public void SetUpstream(Generation upstream)
5353
public virtual IEnumerable<ParameterSyntax> GetParameters()
5454
{
5555
yield return Parameter(default, ThisTokenList,
56-
UpstreamResolvedClassName, SourceName.Identifier, default);
56+
UpstreamResolvedClassName, SourceField.Identifier, default);
5757
}
5858

5959
public abstract BlockSyntax RenderMethodBody();

LinqGen.Generator/Instructions/Evaluations/FirstEvaluation.cs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -30,19 +30,19 @@ private InvocationExpressionSyntax GetEnumeratorExpression()
3030
if (Upstream!.IsPartition)
3131
{
3232
return InvocationExpression(
33-
MemberAccessExpression(SourceName, GetSliceEnumeratorName),
33+
MemberAccessExpression(SourceField, GetSliceEnumeratorMethod),
3434
ArgumentList(LiteralExpression(0), LiteralExpression(1)));
3535
}
3636

37-
return InvocationExpression(SourceName, GetEnumeratorName);
37+
return InvocationExpression(SourceField, GetEnumeratorMethod);
3838
}
3939

4040
public override BlockSyntax RenderMethodBody()
4141
{
4242
return Block(UsingLocalDeclarationStatement(
43-
IteratorName.Identifier, GetEnumeratorExpression()),
44-
IfStatement(InvocationExpression(IteratorName, MoveNextName),
45-
ReturnStatement(MemberAccessExpression(IteratorName, CurrentName))),
43+
IteratorField.Identifier, GetEnumeratorExpression()),
44+
IfStatement(InvocationExpression(IteratorField, MoveNextMethod),
45+
ReturnStatement(MemberAccessExpression(IteratorField, CurrentProperty))),
4646
OrDefault ? ReturnDefaultStatement() : ThrowInvalidOperationStatement());
4747
}
4848
}

LinqGen.Generator/Instructions/Evaluations/LastEvaluation.cs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -29,13 +29,13 @@ public override BlockSyntax RenderMethodBody()
2929
var lastValue = IdentifierName("lastValue");
3030

3131
return Block(UsingLocalDeclarationStatement(
32-
IteratorName.Identifier, InvocationExpression(SourceName, GetEnumeratorName)),
33-
IfStatement(LogicalNotExpression(InvocationExpression(IteratorName, MoveNextName)),
32+
IteratorField.Identifier, InvocationExpression(SourceField, GetEnumeratorMethod)),
33+
IfStatement(LogicalNotExpression(InvocationExpression(IteratorField, MoveNextMethod)),
3434
OrDefault ? ReturnDefaultStatement() : ThrowInvalidOperationStatement()),
35-
LocalDeclarationStatement(lastValue.Identifier, MemberAccessExpression(IteratorName, CurrentName)),
36-
WhileStatement(InvocationExpression(IteratorName, MoveNextName),
35+
LocalDeclarationStatement(lastValue.Identifier, MemberAccessExpression(IteratorField, CurrentProperty)),
36+
WhileStatement(InvocationExpression(IteratorField, MoveNextMethod),
3737
ExpressionStatement(SimpleAssignmentExpression(
38-
lastValue, MemberAccessExpression(IteratorName, CurrentName)))),
38+
lastValue, MemberAccessExpression(IteratorField, CurrentProperty)))),
3939
ReturnStatement(lastValue));
4040
}
4141
}

0 commit comments

Comments
 (0)