Skip to content

Commit 67856cf

Browse files
updated projects to dotnet9 + switched to incremental source generator (#1)
1 parent 8d69ce3 commit 67856cf

26 files changed

+647
-658
lines changed

.github/workflows/dotnet.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ jobs:
1616
- name: Setup .NET
1717
uses: actions/setup-dotnet@v1
1818
with:
19-
dotnet-version: 5.0.x
19+
dotnet-version: 9.0.x
2020
- name: Restore dependencies
2121
run: dotnet restore
2222
- name: Build

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -348,3 +348,6 @@ MigrationBackup/
348348

349349
# Ionide (cross platform F# VS Code tools) working folder
350350
.ionide/
351+
352+
.idea
353+
.DS_Store

README.md

Lines changed: 20 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -4,30 +4,30 @@ Source code for [Dotnet code generation overview by example](https://mtkachenko.
44

55
``` ini
66

7-
BenchmarkDotNet=v0.13.1, OS=Windows 10.0.19043.1237 (21H1/May2021Update)
8-
Intel Core i7-8550U CPU 1.80GHz (Kaby Lake R), 1 CPU, 8 logical and 4 physical cores
9-
.NET SDK=5.0.401
10-
[Host] : .NET 5.0.10 (5.0.1021.41214), X64 RyuJIT
11-
DefaultJob : .NET 5.0.10 (5.0.1021.41214), X64 RyuJIT
7+
BenchmarkDotNet v0.15.4, macOS 26.0.1 (25A362) [Darwin 25.0.0]
8+
Apple M4, 1 CPU, 10 logical and 10 physical cores
9+
.NET SDK 9.0.305
10+
[Host] : .NET 9.0.9 (9.0.9, 9.0.925.41916), Arm64 RyuJIT armv8.0-a
11+
DefaultJob : .NET 9.0.9 (9.0.9, 9.0.925.41916), Arm64 RyuJIT armv8.0-a
1212

1313

1414
```
1515

1616
## Generation of parser
17-
| Method | Mean | Error | StdDev | Gen 0 | Gen 1 | Gen 2 | Allocated |
18-
|--------------- |-------------:|-------------:|-------------:|----------:|-------:|-------:|----------:|
19-
| EmitIl | 22.02 μs | 0.495 μs | 1.429 μs | 1.2817 | 0.6409 | 0.0305 | 5 KB |
20-
| ExpressionTree | 683.68 μs | 13.609 μs | 31.268 μs | 2.9297 | 0.9766 | - | 14 KB |
21-
| Sigil | 642.63 μs | 12.305 μs | 29.243 μs | 112.3047 | - | - | 460 KB |
22-
| Roslyn | 71,605.64 μs | 2,533.732 μs | 7,350.817 μs | 1000.0000 | - | - | 5,826 KB |
17+
| Method | Mean | Error | StdDev | Gen0 | Gen1 | Gen2 | Allocated |
18+
|--------------- |--------------:|------------:|------------:|----------:|---------:|---------:|-----------:|
19+
| EmitIl | 3.370 us | 0.0283 us | 0.0251 us | 0.4196 | 0.2060 | 0.0305 | 3.48 KB |
20+
| ExpressionTree | 131.847 us | 0.4957 us | 0.4394 us | 1.2207 | 0.4883 | - | 11.4 KB |
21+
| Sigil | 130.371 us | 1.2540 us | 1.1730 us | 52.7344 | 13.6719 | - | 433.2 KB |
22+
| Roslyn | 14,522.046 us | 263.8589 us | 246.8138 us | 1031.2500 | 343.7500 | 125.0000 | 7757.56 KB |
2323

2424
## Invocation of parser
25-
| Method | Mean | Error | StdDev | Ratio | RatioSD | Gen 0 | Allocated |
26-
|---------------- |------------:|----------:|----------:|------:|--------:|-------:|----------:|
27-
| EmitIl | 374.7 ns | 7.75 ns | 22.36 ns | 1.02 | 0.08 | 0.0095 | 40 B |
28-
| ExpressionTree | 378.1 ns | 7.56 ns | 20.57 ns | 1.03 | 0.08 | 0.0095 | 40 B |
29-
| Reflection | 13,625.0 ns | 272.60 ns | 750.81 ns | 37.29 | 2.29 | 0.7782 | 3,256 B |
30-
| Sigil | 378.9 ns | 7.69 ns | 21.06 ns | 1.03 | 0.07 | 0.0095 | 40 B |
31-
| Roslyn | 404.2 ns | 7.55 ns | 17.80 ns | 1.10 | 0.07 | 0.0095 | 40 B |
32-
| SourceGenerator | 384.4 ns | 7.79 ns | 21.46 ns | 1.05 | 0.08 | 0.0095 | 40 B |
33-
| ManuallyWritten | 367.8 ns | 7.36 ns | 15.68 ns | 1.00 | 0.00 | 0.0095 | 40 B |
25+
| Method | Mean | Error | StdDev | Ratio | RatioSD | Gen0 | Allocated | Alloc Ratio |
26+
|---------------- |------------:|----------:|----------:|------:|--------:|-------:|----------:|------------:|
27+
| EmitIl | 75.14 ns | 0.352 ns | 0.294 ns | 1.01 | 0.00 | 0.0048 | 40 B | 1.00 |
28+
| ExpressionTree | 76.12 ns | 1.306 ns | 1.222 ns | 1.02 | 0.02 | 0.0048 | 40 B | 1.00 |
29+
| Reflection | 1,084.40 ns | 21.704 ns | 25.837 ns | 14.52 | 0.34 | 0.0992 | 832 B | 20.80 |
30+
| Sigil | 75.51 ns | 0.319 ns | 0.249 ns | 1.01 | 0.00 | 0.0048 | 40 B | 1.00 |
31+
| Roslyn | 82.45 ns | 0.117 ns | 0.110 ns | 1.10 | 0.00 | 0.0048 | 40 B | 1.00 |
32+
| SourceGenerator | 75.59 ns | 0.092 ns | 0.086 ns | 1.01 | 0.00 | 0.0048 | 40 B | 1.00 |
33+
| ManuallyWritten | 74.66 ns | 0.142 ns | 0.133 ns | 1.00 | 0.00 | 0.0048 | 40 B | 1.00 |

benchmark/Data.cs

Lines changed: 11 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,16 @@
11
using System;
22

3-
namespace Parsers.Benchmarks
3+
namespace Parsers.Benchmarks;
4+
5+
[ParserOutput]
6+
public class Data
47
{
5-
[ParserOutput]
6-
public class Data
7-
{
8-
[ArrayIndex(0)]
9-
public string Name { get; set; }
8+
[ArrayIndex(0)]
9+
public string Name { get; set; }
1010

11-
[ArrayIndex(2)]
12-
public int Number { get; set; }
11+
[ArrayIndex(2)]
12+
public int Number { get; set; }
1313

14-
[ArrayIndex(1)]
15-
public DateTime Birthday { get; set; }
16-
}
17-
}
14+
[ArrayIndex(1)]
15+
public DateTime Birthday { get; set; }
16+
}

benchmark/GetParser_Benchmark.cs

Lines changed: 35 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,46 +1,45 @@
11
using System;
22
using BenchmarkDotNet.Attributes;
33

4-
namespace Parsers.Benchmarks
4+
namespace Parsers.Benchmarks;
5+
6+
// ReSharper disable once InconsistentNaming
7+
[MemoryDiagnoser]
8+
public class GetParser_Benchmark
59
{
6-
// ReSharper disable once InconsistentNaming
7-
[MemoryDiagnoser]
8-
public class GetParser_Benchmark
9-
{
10-
private EmitIlParserFactory _emitIlParserFactory;
11-
private ExpressionTreeParserFactory _expressionTreeParserFactory;
12-
private SigilParserFactory _sigilParserFactory;
10+
private EmitIlParserFactory _emitIlParserFactory;
11+
private ExpressionTreeParserFactory _expressionTreeParserFactory;
12+
private SigilParserFactory _sigilParserFactory;
1313

14-
[GlobalSetup]
15-
public void GlobalSetup()
16-
{
17-
_emitIlParserFactory = new EmitIlParserFactory();
18-
_expressionTreeParserFactory = new ExpressionTreeParserFactory();
19-
_sigilParserFactory = new SigilParserFactory();
20-
}
14+
[GlobalSetup]
15+
public void GlobalSetup()
16+
{
17+
_emitIlParserFactory = new EmitIlParserFactory();
18+
_expressionTreeParserFactory = new ExpressionTreeParserFactory();
19+
_sigilParserFactory = new SigilParserFactory();
20+
}
2121

22-
[Benchmark]
23-
public Func<string[], Data> EmitIl()
24-
{
25-
return _emitIlParserFactory.GetParser<Data>();
26-
}
22+
[Benchmark]
23+
public Func<string[], Data> EmitIl()
24+
{
25+
return _emitIlParserFactory.GetParser<Data>();
26+
}
2727

28-
[Benchmark]
29-
public Func<string[], Data> ExpressionTree()
30-
{
31-
return _expressionTreeParserFactory.GetParser<Data>();
32-
}
28+
[Benchmark]
29+
public Func<string[], Data> ExpressionTree()
30+
{
31+
return _expressionTreeParserFactory.GetParser<Data>();
32+
}
3333

34-
[Benchmark]
35-
public Func<string[], Data> Sigil()
36-
{
37-
return _sigilParserFactory.GetParser<Data>();
38-
}
34+
[Benchmark]
35+
public Func<string[], Data> Sigil()
36+
{
37+
return _sigilParserFactory.GetParser<Data>();
38+
}
3939

40-
[Benchmark]
41-
public Func<string[], Data> Roslyn()
42-
{
43-
return RoslynParserInitializer.CreateFactory().GetParser<Data>();
44-
}
40+
[Benchmark]
41+
public Func<string[], Data> Roslyn()
42+
{
43+
return RoslynParserInitializer.CreateFactory().GetParser<Data>();
4544
}
46-
}
45+
}
Lines changed: 67 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -1,86 +1,85 @@
11
using System;
22
using BenchmarkDotNet.Attributes;
33

4-
namespace Parsers.Benchmarks
4+
namespace Parsers.Benchmarks;
5+
6+
// ReSharper disable once InconsistentNaming
7+
[MemoryDiagnoser]
8+
public class ParserInvocation_Benchmark
59
{
6-
// ReSharper disable once InconsistentNaming
7-
[MemoryDiagnoser]
8-
public class ParserInvocation_Benchmark
9-
{
10-
private Func<string[], Data> _emitIlParser;
11-
private Func<string[], Data> _expressionTreeParser;
12-
private Func<string[], Data> _reflectionParser;
13-
private Func<string[], Data> _sigilParser;
14-
private Func<string[], Data> _roslynParser;
15-
private Func<string[], Data> _sourceGeneratorParser;
10+
private Func<string[], Data> _emitIlParser;
11+
private Func<string[], Data> _expressionTreeParser;
12+
private Func<string[], Data> _reflectionParser;
13+
private Func<string[], Data> _sigilParser;
14+
private Func<string[], Data> _roslynParser;
15+
private Func<string[], Data> _sourceGeneratorParser;
1616

17-
private static readonly string[] Input = { "one", "1994-11-05T13:15:30", "22" };
17+
private static readonly string[] Input = { "one", "1994-11-05T13:15:30", "22" };
1818

19-
[GlobalSetup]
20-
public void GlobalSetup()
21-
{
22-
_emitIlParser = new EmitIlParserFactory().GetParser<Data>();
23-
_expressionTreeParser = new ExpressionTreeParserFactory().GetParser<Data>();
24-
_reflectionParser = new ReflectionParserFactory().GetParser<Data>();
25-
_sigilParser = new SigilParserFactory().GetParser<Data>();
26-
_roslynParser = RoslynParserInitializer.CreateFactory().GetParser<Data>();
27-
// ReSharper disable once PossibleNullReferenceException
28-
_sourceGeneratorParser = ((IParserFactory)Activator.CreateInstance(Type.GetType("BySourceGenerator.Parser"))).GetParser<Data>();
29-
}
19+
[GlobalSetup]
20+
public void GlobalSetup()
21+
{
22+
_emitIlParser = new EmitIlParserFactory().GetParser<Data>();
23+
_expressionTreeParser = new ExpressionTreeParserFactory().GetParser<Data>();
24+
_reflectionParser = new ReflectionParserFactory().GetParser<Data>();
25+
_sigilParser = new SigilParserFactory().GetParser<Data>();
26+
_roslynParser = RoslynParserInitializer.CreateFactory().GetParser<Data>();
27+
// ReSharper disable once PossibleNullReferenceException
28+
_sourceGeneratorParser = ((IParserFactory)Activator.CreateInstance(Type.GetType("BySourceGenerator.Parser"))).GetParser<Data>();
29+
}
3030

31-
[Benchmark]
32-
public Data EmitIl()
33-
{
34-
return _emitIlParser.Invoke(Input);
35-
}
31+
[Benchmark]
32+
public Data EmitIl()
33+
{
34+
return _emitIlParser.Invoke(Input);
35+
}
3636

37-
[Benchmark]
38-
public Data ExpressionTree()
39-
{
40-
return _expressionTreeParser.Invoke(Input);
41-
}
37+
[Benchmark]
38+
public Data ExpressionTree()
39+
{
40+
return _expressionTreeParser.Invoke(Input);
41+
}
4242

43-
[Benchmark]
44-
public Data Reflection()
45-
{
46-
return _reflectionParser.Invoke(Input);
47-
}
43+
[Benchmark]
44+
public Data Reflection()
45+
{
46+
return _reflectionParser.Invoke(Input);
47+
}
4848

49-
[Benchmark]
50-
public Data Sigil()
51-
{
52-
return _sigilParser.Invoke(Input);
53-
}
49+
[Benchmark]
50+
public Data Sigil()
51+
{
52+
return _sigilParser.Invoke(Input);
53+
}
5454

55-
[Benchmark]
56-
public Data Roslyn()
55+
[Benchmark]
56+
public Data Roslyn()
57+
{
58+
return _roslynParser.Invoke(Input);
59+
}
60+
61+
[Benchmark]
62+
public Data SourceGenerator()
63+
{
64+
return _sourceGeneratorParser.Invoke(Input);
65+
}
66+
67+
[Benchmark(Baseline = true)]
68+
public Data ManuallyWritten()
69+
{
70+
var data = new Data();
71+
if (0 < Input.Length)
5772
{
58-
return _roslynParser.Invoke(Input);
73+
data.Name = Input[0];
5974
}
60-
61-
[Benchmark]
62-
public Data SourceGenerator()
75+
if (1 < Input.Length && DateTime.TryParse(Input[1], out var bd))
6376
{
64-
return _sourceGeneratorParser.Invoke(Input);
77+
data.Birthday = bd;
6578
}
66-
67-
[Benchmark(Baseline = true)]
68-
public Data ManuallyWritten()
79+
if (2 < Input.Length && int.TryParse(Input[2], out var n))
6980
{
70-
var data = new Data();
71-
if (0 < Input.Length)
72-
{
73-
data.Name = Input[0];
74-
}
75-
if (1 < Input.Length && DateTime.TryParse(Input[1], out var bd))
76-
{
77-
data.Birthday = bd;
78-
}
79-
if (2 < Input.Length && int.TryParse(Input[2], out var n))
80-
{
81-
data.Number = n;
82-
}
83-
return data;
81+
data.Number = n;
8482
}
83+
return data;
8584
}
86-
}
85+
}

benchmark/Parsers.Benchmarks.csproj

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,11 @@
22

33
<PropertyGroup>
44
<OutputType>Exe</OutputType>
5-
<TargetFramework>net5.0</TargetFramework>
5+
<TargetFramework>net9.0</TargetFramework>
66
</PropertyGroup>
77

88
<ItemGroup>
9-
<PackageReference Include="BenchmarkDotNet" Version="0.13.1" />
9+
<PackageReference Include="BenchmarkDotNet" Version="0.15.4" />
1010
</ItemGroup>
1111

1212
<ItemGroup>

benchmark/Program.cs

Lines changed: 14 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,17 @@
11
using BenchmarkDotNet.Running;
2+
using Parsers.Benchmarks;
23

3-
namespace Parsers.Benchmarks
4+
var mode = args.Length == 1 ? args[0] : "all";
5+
switch (mode)
46
{
5-
class Program
6-
{
7-
private const string AllMode = "all";
8-
private const string GetParserMode = "gp";
9-
private const string ParserInvocationMode = "pi";
10-
11-
static void Main(string[] args)
12-
{
13-
var mode = args.Length == 1 ? args[0] : AllMode;
14-
15-
switch (mode)
16-
{
17-
case GetParserMode:
18-
BenchmarkRunner.Run<GetParser_Benchmark>();
19-
break;
20-
case ParserInvocationMode:
21-
BenchmarkRunner.Run<ParserInvocation_Benchmark>();
22-
break;
23-
default:
24-
BenchmarkRunner.Run<GetParser_Benchmark>();
25-
BenchmarkRunner.Run<ParserInvocation_Benchmark>();
26-
break;
27-
}
28-
}
29-
}
30-
}
7+
case "gp":
8+
BenchmarkRunner.Run<GetParser_Benchmark>();
9+
break;
10+
case "pi":
11+
BenchmarkRunner.Run<ParserInvocation_Benchmark>();
12+
break;
13+
default:
14+
BenchmarkRunner.Run<GetParser_Benchmark>();
15+
BenchmarkRunner.Run<ParserInvocation_Benchmark>();
16+
break;
17+
}

benchmark/run.cmd

Lines changed: 0 additions & 2 deletions
This file was deleted.

0 commit comments

Comments
 (0)