Skip to content

Commit f11f90a

Browse files
feat: added source generator benchmarks
1 parent 258a771 commit f11f90a

File tree

3 files changed

+169
-1
lines changed

3 files changed

+169
-1
lines changed

Refit.Benchmarks/Program.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@
77
}
88
else
99
{
10-
BenchmarkRunner.Run<EndToEndBenchmark>();
10+
// BenchmarkRunner.Run<EndToEndBenchmark>();
1111
// BenchmarkRunner.Run<StartupBenchmark>();
1212
// BenchmarkRunner.Run<PerformanceBenchmark>();
13+
BenchmarkRunner.Run<SourceGeneratorBenchmark>();
1314
}

Refit.Benchmarks/Refit.Benchmarks.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
<ItemGroup>
2121
<PackageReference Include="AutoFixture" Version="4.18.1" />
2222
<PackageReference Include="BenchmarkDotNet" Version="0.14.0" />
23+
<PackageReference Include="Microsoft.CodeAnalysis.CSharp.Workspaces" Version="4.12.0-3.24430.2" />
2324
</ItemGroup>
2425

2526
<ItemGroup>
Lines changed: 166 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,166 @@
1+
using System.Reflection;
2+
3+
using BenchmarkDotNet.Attributes;
4+
5+
using Microsoft.CodeAnalysis;
6+
using Microsoft.CodeAnalysis.CSharp;
7+
8+
using Refit.Generator;
9+
10+
namespace Refit.Benchmarks;
11+
12+
[MemoryDiagnoser]
13+
public class SourceGeneratorBenchmark
14+
{
15+
private const string SmallInterface =
16+
"""
17+
using System;
18+
using System.Collections.Generic;
19+
using System.Linq;
20+
using System.Net.Http;
21+
using System.Text;
22+
using System.Threading;
23+
using System.Threading.Tasks;
24+
using Refit;
25+
26+
namespace RefitGeneratorTest;
27+
28+
public interface IReallyExcitingCrudApi<T, in TKey> where T : class
29+
{
30+
[Post("")]
31+
Task<T> Create([Body] T payload);
32+
33+
[Get("")]
34+
Task<List<T>> ReadAll();
35+
36+
[Get("/{key}")]
37+
Task<T> ReadOne(TKey key);
38+
39+
[Put("/{key}")]
40+
Task Update(TKey key, [Body]T payload);
41+
42+
[Delete("/{key}")]
43+
Task Delete(TKey key);
44+
}
45+
""";
46+
47+
static readonly MetadataReference RefitAssembly = MetadataReference.CreateFromFile(
48+
typeof(GetAttribute).Assembly.Location,
49+
documentation: XmlDocumentationProvider.CreateFromFile(
50+
Path.ChangeExtension(typeof(GetAttribute).Assembly.Location, ".xml")
51+
)
52+
);
53+
static readonly Type[] ImportantAssemblies = {
54+
typeof(Binder),
55+
typeof(GetAttribute),
56+
typeof(Enumerable),
57+
typeof(Newtonsoft.Json.JsonConvert),
58+
typeof(HttpContent),
59+
typeof(Attribute)
60+
};
61+
62+
static Assembly[] AssemblyReferencesForCodegen =>
63+
AppDomain.CurrentDomain
64+
.GetAssemblies()
65+
.Concat(ImportantAssemblies.Select(x=>x.Assembly))
66+
.Distinct()
67+
.Where(a => !a.IsDynamic)
68+
.ToArray();
69+
70+
private Compilation compilation;
71+
private CSharpGeneratorDriver driver;
72+
73+
74+
private static CSharpCompilation CreateLibrary2(params string[] source)
75+
{
76+
var references = new List<MetadataReference>();
77+
var assemblies = AssemblyReferencesForCodegen;
78+
foreach (var assembly in assemblies)
79+
{
80+
if (!assembly.IsDynamic)
81+
{
82+
references.Add(MetadataReference.CreateFromFile(assembly.Location));
83+
}
84+
}
85+
86+
references.Add(RefitAssembly);
87+
var compilation = CSharpCompilation.Create(
88+
"compilation",
89+
source.Select(s => CSharpSyntaxTree.ParseText(s)),
90+
references,
91+
new CSharpCompilationOptions(OutputKind.ConsoleApplication)
92+
);
93+
94+
return compilation;
95+
}
96+
97+
public void Setup(string sourceText)
98+
{
99+
var references = new List<MetadataReference>();
100+
var assemblies = AssemblyReferencesForCodegen;
101+
foreach (var assembly in assemblies)
102+
{
103+
if (!assembly.IsDynamic)
104+
{
105+
references.Add(MetadataReference.CreateFromFile(assembly.Location));
106+
}
107+
}
108+
109+
references.Add(RefitAssembly);
110+
compilation = CSharpCompilation.Create(
111+
"compilation",
112+
[CSharpSyntaxTree.ParseText(sourceText)],
113+
references,
114+
new CSharpCompilationOptions(OutputKind.ConsoleApplication)
115+
);
116+
117+
var generator = GeneratorExtensions.AsSourceGenerator(new InterfaceStubGeneratorV2());
118+
driver = CSharpGeneratorDriver.Create(generator);
119+
}
120+
121+
private static CSharpCompilation CreateLibrary(params string[] source)
122+
{
123+
var references = new List<MetadataReference>();
124+
var assemblies = AssemblyReferencesForCodegen;
125+
foreach (var assembly in assemblies)
126+
{
127+
if (!assembly.IsDynamic)
128+
{
129+
references.Add(MetadataReference.CreateFromFile(assembly.Location));
130+
}
131+
}
132+
133+
references.Add(RefitAssembly);
134+
var compilation = CSharpCompilation.Create(
135+
"compilation",
136+
source.Select(s => CSharpSyntaxTree.ParseText(s)),
137+
references,
138+
new CSharpCompilationOptions(OutputKind.ConsoleApplication)
139+
);
140+
141+
return compilation;
142+
}
143+
144+
145+
[GlobalSetup(Target = nameof(Compile))]
146+
public void SetupSmall() => Setup(SmallInterface);
147+
148+
[Benchmark]
149+
public GeneratorDriver Compile()
150+
{
151+
return driver.RunGeneratorsAndUpdateCompilation(compilation, out _, out _);
152+
}
153+
154+
[GlobalSetup(Target = nameof(Cached))]
155+
public void SetupCached()
156+
{
157+
Setup(SmallInterface);
158+
driver = (CSharpGeneratorDriver)driver.RunGeneratorsAndUpdateCompilation(compilation, out _, out _);
159+
}
160+
161+
[Benchmark]
162+
public GeneratorDriver Cached()
163+
{
164+
return driver.RunGeneratorsAndUpdateCompilation(compilation, out _, out _);
165+
}
166+
}

0 commit comments

Comments
 (0)