Skip to content

feat: source generator benchmarks - #4579

Merged
thomhurst merged 1 commit into
thomhurst:mainfrom
TimothyMakkison:source_gen_bench
Jan 28, 2026
Merged

feat: source generator benchmarks#4579
thomhurst merged 1 commit into
thomhurst:mainfrom
TimothyMakkison:source_gen_bench

Conversation

@TimothyMakkison

@TimothyMakkisonTimothyMakkison commented Jan 27, 2026

Copy link
Copy Markdown
Contributor

Trying to add benchmarks for the source generators, I've been able to do this for Mapperly, Mediator and Refit, but I can't get it to work here.

I'd welcome someone else to try, I think it's an issue with the references.

Error I usually get

C:\Users\Lenovo ThinkPad\Desktop\coding\C#\TUnit\TUnit.SourceGenerator.Benchmarks\bin\release\net10.0\TUnit.SourceGenerator.Benchmarks-1\TUnit.SourceGenerator.Benchmarks-1.notcs(239,40): error CS0234: The type or namespace name 'GeneratorDriver' does not exist in the namespace 'Microsoft.CodeAnalysis' (are you missing an assembly reference?) [C:\Users\Lenovo ThinkPad\Desktop\coding\C#\TUnit\TUnit.SourceGenerator.Benchmarks\bin\release\net10.0\TUnit.SourceGenerator.Benchmarks-1\BenchmarkDotNet.Autogenerated.csproj::TargetFramework=net10.0]
C:\Users\Lenovo ThinkPad\Desktop\coding\C#\TUnit\TUnit.SourceGenerator.Benchmarks\bin\release\net10.0\TUnit.SourceGenerator.Benchmarks-1\TUnit.SourceGenerator.Benchmarks-1.notcs(318,39): error CS0234: The type or namespace name 'GeneratorDriver' does not exist in the namespace 'Microsoft.CodeAnalysis' (are you missing an assembly reference?) [C:\Users\Lenovo ThinkPad\Desktop\coding\C#\TUnit\TUnit.SourceGenerator.Benchmarks\bin\release\net10.0\TUnit.SourceGenerator.Benchmarks-1\BenchmarkDotNet.Autogenerated.csproj::TargetFramework=net10.0]
C:\Users\Lenovo ThinkPad\Desktop\coding\C#\TUnit\TUnit.SourceGenerator.Benchmarks\bin\release\net10.0\TUnit.SourceGenerator.Benchmarks-1\TUnit.SourceGenerator.Benchmarks-1.notcs(186,48): error CS0234: The type or namespace name 'GeneratorDriver' does not exist in the namespace 'Microsoft.CodeAnalysis' (are you missing an assembly reference?) [C:\Users\Lenovo ThinkPad\Desktop\coding\C#\TUnit\TUnit.SourceGenerator.Benchmarks\bin\release\net10.0\TUnit.SourceGenerator.Benchmarks-1\BenchmarkDotNet.Autogenerated.csproj::TargetFramework=net10.0]
C:\Users\Lenovo ThinkPad\Desktop\coding\C#\TUnit\TUnit.SourceGenerator.Benchmarks\bin\release\net10.0\TUnit.SourceGenerator.Benchmarks-1\TUnit.SourceGenerator.Benchmarks-1.notcs(188,49): error CS0234: The type or namespace name 'GeneratorDriver' does not exist in the namespace 'Microsoft.CodeAnalysis' (are you missing an assembly reference?) [C:\Users\Lenovo ThinkPad\Desktop\coding\C#\TUnit\TUnit.SourceGenerator.Benchmarks\bin\release\net10.0\TUnit.SourceGenerator.Benchmarks-1\BenchmarkDotNet.Autogenerated.csproj::TargetFramework=net10.0]
Build FAILED.
C:\Program Files\dotnet\sdk\10.0.101\Microsoft.Common.CurrentVersion.targets(2189,5): warning MSB9008: The referenced project ..\TUnit.Core.SourceGenerator.Roslyn47\TUnit.Core.Roslyn47.SourceGenerator.csproj does not exist. [C:\Users\Lenovo ThinkPad\Desktop\coding\C#\TUnit\TUnit.SourceGenerator.Benchmarks\TUnit.SourceGenerator.Benchmarks.csproj::TargetFramework=net10.0]
C:\Users\Lenovo ThinkPad\Desktop\coding\C#\TUnit\TUnit.SourceGenerator.Benchmarks\Program.cs(41,25): warning CS8618: Non-nullable field 'compilation' must contain a non-null value when exiting constructor. Consider adding the 'required' modifier or declaring the field as nullable. [C:\Users\Lenovo ThinkPad\Desktop\coding\C#\TUnit\TUnit.SourceGenerator.Benchmarks\TUnit.SourceGenerator.Benchmarks.csproj::TargetFramework=net10.0]
C:\Users\Lenovo ThinkPad\Desktop\coding\C#\TUnit\TUnit.SourceGenerator.Benchmarks\Program.cs(42,35): warning CS8618: Non-nullable field 'driver' must contain a non-null value when exiting constructor. Consider adding the 'required' modifier or declaring the field as nullable. [C:\Users\Lenovo ThinkPad\Desktop\coding\C#\TUnit\TUnit.SourceGenerator.Benchmarks\TUnit.SourceGenerator.Benchmarks.csproj::TargetFramework=net10.0]
C:\Users\Lenovo ThinkPad\Desktop\coding\C#\TUnit\TUnit.SourceGenerator.Benchmarks\bin\release\net10.0\TUnit.SourceGenerator.Benchmarks-1\TUnit.SourceGenerator.Benchmarks-1.notcs(239,40): error CS0234: The type or namespace name 'GeneratorDriver' does not exist in the namespace 'Microsoft.CodeAnalysis' (are you missing an assembly reference?) [C:\Users\Lenovo ThinkPad\Desktop\coding\C#\TUnit\TUnit.SourceGenerator.Benchmarks\bin\release\net10.0\TUnit.SourceGenerator.Benchmarks-1\BenchmarkDotNet.Autogenerated.csproj::TargetFramework=net10.0]
C:\Users\Lenovo ThinkPad\Desktop\coding\C#\TUnit\TUnit.SourceGenerator.Benchmarks\bin\release\net10.0\TUnit.SourceGenerator.Benchmarks-1\TUnit.SourceGenerator.Benchmarks-1.notcs(318,39): error CS0234: The type or namespace name 'GeneratorDriver' does not exist in the namespace 'Microsoft.CodeAnalysis' (are you missing an assembly reference?) [C:\Users\Lenovo ThinkPad\Desktop\coding\C#\TUnit\TUnit.SourceGenerator.Benchmarks\bin\release\net10.0\TUnit.SourceGenerator.Benchmarks-1\BenchmarkDotNet.Autogenerated.csproj::TargetFramework=net10.0]
C:\Users\Lenovo ThinkPad\Desktop\coding\C#\TUnit\TUnit.SourceGenerator.Benchmarks\bin\release\net10.0\TUnit.SourceGenerator.Benchmarks-1\TUnit.SourceGenerator.Benchmarks-1.notcs(186,48): error CS0234: The type or namespace name 'GeneratorDriver' does not exist in the namespace 'Microsoft.CodeAnalysis' (are you missing an assembly reference?) [C:\Users\Lenovo ThinkPad\Desktop\coding\C#\TUnit\TUnit.SourceGenerator.Benchmarks\bin\release\net10.0\TUnit.SourceGenerator.Benchmarks-1\BenchmarkDotNet.Autogenerated.csproj::TargetFramework=net10.0]
C:\Users\Lenovo ThinkPad\Desktop\coding\C#\TUnit\TUnit.SourceGenerator.Benchmarks\bin\release\net10.0\TUnit.SourceGenerator.Benchmarks-1\TUnit.SourceGenerator.Benchmarks-1.notcs(188,49): error CS0234: The type or namespace name 'GeneratorDriver' does not exist in the namespace 'Microsoft.CodeAnalysis' (are you missing an assembly reference?) [C:\Users\Lenovo ThinkPad\Desktop\coding\C#\TUnit\TUnit.SourceGenerator.Benchmarks\bin\release\net10.0\TUnit.SourceGenerator.Benchmarks-1\BenchmarkDotNet.Autogenerated.csproj::TargetFramework=net10.0]
3 Warning(s)
4 Error(s)
Time Elapsed 00:01:13.44
// BenchmarkDotNet has failed to build the auto-generated boilerplate code.

@thomhurst

Copy link
Copy Markdown
Owner

AI-Generated Analysis

I investigated this PR and identified the root causes of the issues. Here's what needs to be fixed:

Root Cause 1: Missing Microsoft.Build.Locator (PRIMARY CAUSE)

MSBuildWorkspace requires Microsoft.Build.Locator to find and load MSBuild assemblies. Without this, MSBuildWorkspace will fail with assembly loading errors.

From Mapperly's working benchmark (which you referenced), they call:

// MUST be called before any MSBuild types are accessedMSBuildLocator.RegisterDefaults();// Then create workspacevarworkspace=MSBuildWorkspace.Create();

Root Cause 2: Roslyn Version Mismatches

The PR has inconsistent Roslyn versions in the benchmark project:

  • Microsoft.CodeAnalysis.Workspaces.MSBuild at 5.0.0
  • Microsoft.CodeAnalysis.CSharp.Workspaces at 4.7.0
  • Microsoft.CodeAnalysis.CSharp at 5.0.0

All Microsoft.CodeAnalysis. packages must use the same version.*

Root Cause 3: Unnecessary Changes to Existing Projects

The PR modifies existing generator projects which shouldn't be needed:

  • TUnit.Core.SourceGenerator.csproj - changed to Roslyn 5.0.0
  • TUnit.Core.SourceGenerator.Roslyn47 - changed RoslynVersion from 4.7 to 4.14

These changes break TUnit's multi-Roslyn version architecture and should be reverted.


Recommended Fixes

1. Add Microsoft.Build.Locator to Directory.Packages.props

<PackageVersionInclude="Microsoft.Build.Locator"Version="1.6.10" />

2. Fix TUnit.SourceGenerator.Benchmarks.csproj

Use consistent versions (4.12.0 matches the existing CSharp.Workspaces version in Directory.Packages.props):

<ProjectSdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net9.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles>
</PropertyGroup>
<ItemGroup>
<PackageReferenceInclude="BenchmarkDotNet" />
<!-- Critical: MSBuild.Locator is required for MSBuildWorkspace -->
<PackageReferenceInclude="Microsoft.Build.Locator" />
<!-- All CodeAnalysis packages must be the same version -->
<PackageReferenceInclude="Microsoft.CodeAnalysis.Workspaces.MSBuild"VersionOverride="4.12.0" />
<PackageReferenceInclude="Microsoft.CodeAnalysis.CSharp.Workspaces"PrivateAssets="all" />
<PackageReferenceInclude="Microsoft.CodeAnalysis.CSharp"PrivateAssets="all"VersionOverride="4.12.0" />
<PackageReferenceInclude="Microsoft.CodeAnalysis.Common"PrivateAssets="all"VersionOverride="4.12.0" />
</ItemGroup>
<ItemGroup>
<ProjectReferenceInclude="..\TUnit.Core.SourceGenerator\TUnit.Core.SourceGenerator.csproj" />
<ProjectReferenceInclude="..\TUnit.Core\TUnit.Core.csproj" />
</ItemGroup>
</Project>

3. Fix Program.cs - Add MSBuildLocator Initialization

usingSystem.Runtime.CompilerServices;usingBenchmarkDotNet.Attributes;usingBenchmarkDotNet.Loggers;usingBenchmarkDotNet.Running;usingMicrosoft.Build.Locator;usingMicrosoft.CodeAnalysis;usingMicrosoft.CodeAnalysis.CSharp;usingMicrosoft.CodeAnalysis.MSBuild;usingTUnit.Core.SourceGenerator.Generators;// CRITICAL: Must be called before ANY MSBuild types are accessed// Must be in a separate method that's called first to avoid JIT loading the types earlyInitializeMSBuild();BenchmarkRunner.Run<TestMetadataGeneratorBenchmarks>();staticvoidInitializeMSBuild(){MSBuildLocator.RegisterDefaults();}[MemoryDiagnoser]publicclassTestMetadataGeneratorBenchmarks{privateconststringSampleProjectPath="../TUnit.TestProject/TUnit.TestProject.csproj";privateMSBuildWorkspace?_workspace;privateGeneratorDriver?_sampleDriver;privateCompilation?_sampleCompilation;privatestaticstringGetDirectoryRelativePath(stringprojectPath,[CallerFilePath]stringcallerFilePath=null!)=>Path.Combine(Path.GetDirectoryName(callerFilePath)!,projectPath);privateasyncTask<(Compilation,CSharpGeneratorDriver)>SetupAsync(stringprojectPath){_workspace=MSBuildWorkspace.Create();_workspace.WorkspaceFailed+=(sender,args)=>{ConsoleLogger.Default.WriteLineError("-------------------------");ConsoleLogger.Default.WriteLineError(args.Diagnostic.ToString());ConsoleLogger.Default.WriteLineError("-------------------------");};varprojectFile=GetDirectoryRelativePath(projectPath);if(!File.Exists(projectFile))thrownewException($"Project doesn't exist at: {projectFile}");ConsoleLogger.Default.WriteLine($"Project exists at {projectFile}");Projectproject;try{ConsoleLogger.Default.WriteLine("Loading project\n");project=await_workspace.OpenProjectAsync(projectFile);ConsoleLogger.Default.WriteLine("\nLoaded project");}catch(Exceptionex){ConsoleLogger.Default.WriteError($"Error: {ex.Message}");throw;}varcompilation=awaitproject.GetCompilationAsync();if(compilation==null)thrownewInvalidOperationException("Compilation returned null");vargenerator=newTestMetadataGenerator().AsSourceGenerator();vardriver=CSharpGeneratorDriver.Create([generator],parseOptions:(CSharpParseOptions)project.ParseOptions!);return(compilation,driver);}[GlobalSetup(Target=nameof(Compile))]publicvoidSetupCompile()=>(_sampleCompilation,_sampleDriver)=SetupAsync(SampleProjectPath).GetAwaiter().GetResult();[Benchmark]publicGeneratorDriverCompile()=>_sampleDriver!.RunGeneratorsAndUpdateCompilation(_sampleCompilation!,out_,out_);[GlobalCleanup]publicvoidCleanup(){_workspace?.Dispose();}}

4. Revert Changes to Existing Projects

Remove the changes to:

  • TUnit.Core.SourceGenerator/TUnit.Core.SourceGenerator.csproj - revert Roslyn version overrides
  • TUnit.Core.SourceGenerator.Roslyn47/TUnit.Core.SourceGenerator.Roslyn47.csproj - revert RoslynVersion back to 4.7

Key Points

  1. MSBuildLocator.RegisterDefaults() MUST be called before ANY MSBuild types are accessed - This includes MSBuildWorkspace.Create(). The call must be in a separate method to avoid JIT loading the types.

  2. All Microsoft.CodeAnalysis. packages must be the same version* - The benchmark project can use VersionOverride to use a higher version than the source generators without modifying the generator projects.

  3. Don't modify the source generator projects - The benchmark project should work with the existing generator architecture. The generators target older Roslyn versions intentionally for broad compatibility.

  4. Also note: Path.Combine(callerFilePath, projectPath) should be Path.Combine(Path.GetDirectoryName(callerFilePath)!, projectPath) - you want the directory, not the file path itself.

@TimothyMakkison

Copy link
Copy Markdown
ContributorAuthor

Root Cause 1: Missing Microsoft.Build.Locator (PRIMARY CAUSE)

  1. Fix Program.cs - Add MSBuildLocator Initialization

I'll try doing this, I don't think I've done this before, not sure what the difference is this time, It appears I need to import more packages with special exclusions.

  1. Revert Changes to Existing Projects

👍

  1. Fix TUnit.SourceGenerator.Benchmarks.csproj

I've tried this along with not using overrides, former didn't do much, latter just caused conflicts between AsyncEnumerable versions

@TimothyMakkison

TimothyMakkison commented Jan 27, 2026

Copy link
Copy Markdown
ContributorAuthor

Added MSBuildLocator.RegisterDefaults();

Same error message 😢

 Standard error:
C:\Users\Lenovo ThinkPad\Desktop\coding\C#\TUnit\TUnit.SourceGenerator.Benchmarks\TUnit.SourceGenerator.Benchmarks.csproj : warning NU1903: Package 'Microsoft.Build.Tasks.Core' 17.7.2 has a known high severity vulnerability, https://github.com/advisories/GHSA-h4j7-5rxr-p4wc [TargetFramework=net10.0]
C:\Users\Lenovo ThinkPad\Desktop\coding\C#\TUnit\TUnit.SourceGenerator.Benchmarks\TUnit.SourceGenerator.Benchmarks.csproj : warning NU1903: Package 'System.Formats.Asn1' 7.0.0 has a known high severity vulnerability, https://github.com/advisories/GHSA-447r-wph3-92pm [TargetFramework=net10.0]
TUnit.Core.SourceGenerator -> C:\Users\Lenovo ThinkPad\Desktop\coding\C#\TUnit\TUnit.SourceGenerator.Benchmarks\bin\release\net10.0\TUnit.SourceGenerator.Benchmarks-1\bin\Release\net10.0\TUnit.Core.SourceGenerator.dll
TUnit.Core -> C:\Users\Lenovo ThinkPad\Desktop\coding\C#\TUnit\TUnit.SourceGenerator.Benchmarks\bin\release\net10.0\TUnit.SourceGenerator.Benchmarks-1\bin\Release\net10.0\TUnit.Core.dll
TUnit.SourceGenerator.Benchmarks -> C:\Users\Lenovo ThinkPad\Desktop\coding\C#\TUnit\TUnit.SourceGenerator.Benchmarks\bin\release\net10.0\TUnit.SourceGenerator.Benchmarks-1\bin\Release\net10.0\TUnit.SourceGenerator.Benchmarks.dll
C:\Users\Lenovo ThinkPad\Desktop\coding\C#\TUnit\TUnit.SourceGenerator.Benchmarks\bin\release\net10.0\TUnit.SourceGenerator.Benchmarks-1\TUnit.SourceGenerator.Benchmarks-1.notcs(239,40): error CS0234: The type or namespace name 'GeneratorDriver' does not exist in the namespace 'Microsoft.CodeAnalysis' (are you missing an assembly reference?) [C:\Users\Lenovo ThinkPad\Desktop\coding\C#\TUnit\TUnit.SourceGenerator.Benchmarks\bin\release\net10.0\TUnit.SourceGenerator.Benchmarks-1\BenchmarkDotNet.Autogenerated.csproj::TargetFramework=net10.0]
C:\Users\Lenovo ThinkPad\Desktop\coding\C#\TUnit\TUnit.SourceGenerator.Benchmarks\bin\release\net10.0\TUnit.SourceGenerator.Benchmarks-1\TUnit.SourceGenerator.Benchmarks-1.notcs(318,39): error CS0234: The type or namespace name 'GeneratorDriver' does not exist in the namespace 'Microsoft.CodeAnalysis' (are you missing an assembly reference?) [C:\Users\Lenovo ThinkPad\Desktop\coding\C#\TUnit\TUnit.SourceGenerator.Benchmarks\bin\release\net10.0\TUnit.SourceGenerator.Benchmarks-1\BenchmarkDotNet.Autogenerated.csproj::TargetFramework=net10.0]
C:\Users\Lenovo ThinkPad\Desktop\coding\C#\TUnit\TUnit.SourceGenerator.Benchmarks\bin\release\net10.0\TUnit.SourceGenerator.Benchmarks-1\TUnit.SourceGenerator.Benchmarks-1.notcs(186,48): error CS0234: The type or namespace name 'GeneratorDriver' does not exist in the namespace 'Microsoft.CodeAnalysis' (are you missing an assembly reference?) [C:\Users\Lenovo ThinkPad\Desktop\coding\C#\TUnit\TUnit.SourceGenerator.Benchmarks\bin\release\net10.0\TUnit.SourceGenerator.Benchmarks-1\BenchmarkDotNet.Autogenerated.csproj::TargetFramework=net10.0]
C:\Users\Lenovo ThinkPad\Desktop\coding\C#\TUnit\TUnit.SourceGenerator.Benchmarks\bin\release\net10.0\TUnit.SourceGenerator.Benchmarks-1\TUnit.SourceGenerator.Benchmarks-1.notcs(188,49): error CS0234: The type or namespace name 'GeneratorDriver' does not exist in the namespace 'Microsoft.CodeAnalysis' (are you missing an assembly reference?) [C:\Users\Lenovo ThinkPad\Desktop\coding\C#\TUnit\TUnit.SourceGenerator.Benchmarks\bin\release\net10.0\TUnit.SourceGenerator.Benchmarks-1\BenchmarkDotNet.Autogenerated.csproj::TargetFramework=net10.0]
Build FAILED.
C:\Users\Lenovo ThinkPad\Desktop\coding\C#\TUnit\TUnit.SourceGenerator.Benchmarks\TUnit.SourceGenerator.Benchmarks.csproj : warning NU1903: Package 'Microsoft.Build.Tasks.Core' 17.7.2 has a known high severity vulnerability, https://github.com/advisories/GHSA-h4j7-5rxr-p4wc [TargetFramework=net10.0]
C:\Users\Lenovo ThinkPad\Desktop\coding\C#\TUnit\TUnit.SourceGenerator.Benchmarks\TUnit.SourceGenerator.Benchmarks.csproj : warning NU1903: Package 'System.Formats.Asn1' 7.0.0 has a known high severity vulnerability, https://github.com/advisories/GHSA-447r-wph3-92pm [TargetFramework=net10.0]
C:\Users\Lenovo ThinkPad\Desktop\coding\C#\TUnit\TUnit.SourceGenerator.Benchmarks\bin\release\net10.0\TUnit.SourceGenerator.Benchmarks-1\TUnit.SourceGenerator.Benchmarks-1.notcs(239,40): error CS0234: The type or namespace name 'GeneratorDriver' does not exist in the namespace 'Microsoft.CodeAnalysis' (are you missing an assembly reference?) [C:\Users\Lenovo ThinkPad\Desktop\coding\C#\TUnit\TUnit.SourceGenerator.Benchmarks\bin\release\net10.0\TUnit.SourceGenerator.Benchmarks-1\BenchmarkDotNet.Autogenerated.csproj::TargetFramework=net10.0]
C:\Users\Lenovo ThinkPad\Desktop\coding\C#\TUnit\TUnit.SourceGenerator.Benchmarks\bin\release\net10.0\TUnit.SourceGenerator.Benchmarks-1\TUnit.SourceGenerator.Benchmarks-1.notcs(318,39): error CS0234: The type or namespace name 'GeneratorDriver' does not exist in the namespace 'Microsoft.CodeAnalysis' (are you missing an assembly reference?) [C:\Users\Lenovo ThinkPad\Desktop\coding\C#\TUnit\TUnit.SourceGenerator.Benchmarks\bin\release\net10.0\TUnit.SourceGenerator.Benchmarks-1\BenchmarkDotNet.Autogenerated.csproj::TargetFramework=net10.0]
C:\Users\Lenovo ThinkPad\Desktop\coding\C#\TUnit\TUnit.SourceGenerator.Benchmarks\bin\release\net10.0\TUnit.SourceGenerator.Benchmarks-1\TUnit.SourceGenerator.Benchmarks-1.notcs(186,48): error CS0234: The type or namespace name 'GeneratorDriver' does not exist in the namespace 'Microsoft.CodeAnalysis' (are you missing an assembly reference?) [C:\Users\Lenovo ThinkPad\Desktop\coding\C#\TUnit\TUnit.SourceGenerator.Benchmarks\bin\release\net10.0\TUnit.SourceGenerator.Benchmarks-1\BenchmarkDotNet.Autogenerated.csproj::TargetFramework=net10.0]
C:\Users\Lenovo ThinkPad\Desktop\coding\C#\TUnit\TUnit.SourceGenerator.Benchmarks\bin\release\net10.0\TUnit.SourceGenerator.Benchmarks-1\TUnit.SourceGenerator.Benchmarks-1.notcs(188,49): error CS0234: The type or namespace name 'GeneratorDriver' does not exist in the namespace 'Microsoft.CodeAnalysis' (are you missing an assembly reference?) [C:\Users\Lenovo ThinkPad\Desktop\coding\C#\TUnit\TUnit.SourceGenerator.Benchmarks\bin\release\net10.0\TUnit.SourceGenerator.Benchmarks-1\BenchmarkDotNet.Autogenerated.csproj::TargetFramework=net10.0]
2 Warning(s)
4 Error(s)
Time Elapsed 00:00:43.60
// BenchmarkDotNet has failed to build the auto-generated boilerplate code.

@thomhurst

Copy link
Copy Markdown
Owner

Follow-up: The Real Fix

After looking at your latest error more closely and comparing with Mapperly's working benchmark, I found the actual issue.

The Problem: BenchmarkDotNet runs benchmarks out-of-process by default. It:

  1. Generates a copy of the benchmark code (the .notcs file you see in errors)
  2. Creates its own minimal BenchmarkDotNet.Autogenerated.csproj
  3. Compiles and runs that project separately

The auto-generated project doesn't include the Microsoft.CodeAnalysis packages, so GeneratorDriver can't be found - regardless of whether you add MSBuildLocator or not.

The Fix: Mapperly uses the [InProcess] attribute:

[ArtifactsPath("artifacts")][MemoryDiagnoser][InProcess]// <-- Add this!publicclass TestMetadataGeneratorBenchmarks

This tells BenchmarkDotNet to run the benchmark in the same process, avoiding the need to generate and compile a separate project entirely.

Correction to my earlier comment:

  • MSBuildLocator.RegisterDefaults() is NOT needed - Mapperly doesn't use it
  • You can remove the Microsoft.Build.Locator package reference
  • The [InProcess] attribute is the key difference

[MemoryDiagnoser] still works with [InProcess], so you'll get the memory diagnostics you need.

@TimothyMakkison

TimothyMakkison commented Jan 28, 2026

Copy link
Copy Markdown
ContributorAuthor

Thank you so much for your help 🙏 with a bit of tweaking it appears to run now!
I must have seen 3 dozen differen error message 😅

MethodMeanErrorStdDevGen0Gen1Allocated
Compile499.5 ms19.50 ms57.48 ms18000.00004000.0000165.61 MB

I'll clean it up tomorrow and see what else I should add, is the name of project okay etc?

@thomhurst

Copy link
Copy Markdown
Owner

No problem 😄

Will this benchmark all source generators, or just the Core? If all, naming looks good to me.

If it's just Core, I'd probably put Core in the name too, as the Assertions library also has a source generator

@TimothyMakkison

Copy link
Copy Markdown
ContributorAuthor

Will this benchmark all source generators, or just the Core? If all, naming looks good to me.
If it's just Core, I'd probably put Core in the name too, as the Assertions library also has a source generator

I was thinking it could be used for all source generators in the solution (if possible). I'm hoping it will be easy to a benchmark for each source generator as needed. I just need to make the build logic generic

@TimothyMakkison

Copy link
Copy Markdown
ContributorAuthor

Okay, should be good to go, I've made the build logic completely reusable so it can be used for the other projects 👍

@thomhurst

Copy link
Copy Markdown
Owner

Summary

Adds a benchmark project for measuring TUnit source generator performance, now working after resolving assembly reference issues.

Critical Issues

None found ✅

Suggestions

1. Update PR title

The title says "feat: add broken source gen benchmarks" but per the comments, the benchmarks are now working. Consider updating to "feat: add source generator benchmarks" or similar.

2. Consider TargetFramework version

The project targets net10.0 which may not be generally available yet. Consider net9.0 or net8.0 to match the rest of the TUnit solution, unless there's a specific reason for net10.0.

3. Add Directory.Packages.props entry for Microsoft.Build.Locator

The comments mentioned adding Microsoft.Build.Locator, but I don't see it in the Directory.Packages.props changes in the diff. If Microsoft.Build.Locator is being used, it should be added to the central package management:

<PackageVersionInclude="Microsoft.Build.Locator"Version="1.7.1" />

4. Minor: Whitespace changes

The changes to Directory.Packages.props and TUnit.Core.SourceGenerator.Roslyn47.csproj only add newlines at EOF. While this is good practice, these could be separated into a cleanup commit if you want to keep the feature commit focused.

Previous Review Status

The maintainer (thomhurst) provided extensive troubleshooting help in comments. Key issues resolved:

  • ✅ Fixed assembly reference errors by using [InProcess] attribute
  • ✅ Made build logic reusable for other generators
  • ✅ Confirmed benchmarks are running successfully

Verdict

APPROVE - No critical issues. The suggestions are optional improvements. The project structure looks good and follows the patterns from similar projects (Mapperly, Mediator, Refit) that were referenced.

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@TimothyMakkison@thomhurst