Skip to content

Conversation

@TimothyMakkison
Copy link
Contributor

@TimothyMakkison TimothyMakkison commented Jan 27, 2026

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
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 accessed
MSBuildLocator.RegisterDefaults();

// Then create workspace
var workspace = 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

<PackageVersion Include="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):

<Project Sdk="Microsoft.NET.Sdk">
    <PropertyGroup>
        <OutputType>Exe</OutputType>
        <TargetFramework>net9.0</TargetFramework>
        <ImplicitUsings>enable</ImplicitUsings>
        <Nullable>enable</Nullable>
        <EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles>
    </PropertyGroup>

    <ItemGroup>
        <PackageReference Include="BenchmarkDotNet" />
        <!-- Critical: MSBuild.Locator is required for MSBuildWorkspace -->
        <PackageReference Include="Microsoft.Build.Locator" />
        <!-- All CodeAnalysis packages must be the same version -->
        <PackageReference Include="Microsoft.CodeAnalysis.Workspaces.MSBuild" VersionOverride="4.12.0" />
        <PackageReference Include="Microsoft.CodeAnalysis.CSharp.Workspaces" PrivateAssets="all" />
        <PackageReference Include="Microsoft.CodeAnalysis.CSharp" PrivateAssets="all" VersionOverride="4.12.0" />
        <PackageReference Include="Microsoft.CodeAnalysis.Common" PrivateAssets="all" VersionOverride="4.12.0" />
    </ItemGroup>

    <ItemGroup>
        <ProjectReference Include="..\TUnit.Core.SourceGenerator\TUnit.Core.SourceGenerator.csproj" />
        <ProjectReference Include="..\TUnit.Core\TUnit.Core.csproj" />
    </ItemGroup>
</Project>

3. Fix Program.cs - Add MSBuildLocator Initialization

using System.Runtime.CompilerServices;
using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Loggers;
using BenchmarkDotNet.Running;
using Microsoft.Build.Locator;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.MSBuild;
using TUnit.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 early
InitializeMSBuild();

BenchmarkRunner.Run<TestMetadataGeneratorBenchmarks>();

static void InitializeMSBuild()
{
    MSBuildLocator.RegisterDefaults();
}

[MemoryDiagnoser]
public class TestMetadataGeneratorBenchmarks
{
    private const string SampleProjectPath = "../TUnit.TestProject/TUnit.TestProject.csproj";

    private MSBuildWorkspace? _workspace;
    private GeneratorDriver? _sampleDriver;
    private Compilation? _sampleCompilation;

    private static string GetDirectoryRelativePath(string projectPath, [CallerFilePath] string callerFilePath = null!) =>
        Path.Combine(Path.GetDirectoryName(callerFilePath)!, projectPath);

    private async Task<(Compilation, CSharpGeneratorDriver)> SetupAsync(string projectPath)
    {
        _workspace = MSBuildWorkspace.Create();
        _workspace.WorkspaceFailed += (sender, args) =>
        {
            ConsoleLogger.Default.WriteLineError("-------------------------");
            ConsoleLogger.Default.WriteLineError(args.Diagnostic.ToString());
            ConsoleLogger.Default.WriteLineError("-------------------------");
        };

        var projectFile = GetDirectoryRelativePath(projectPath);
        if (!File.Exists(projectFile))
            throw new Exception($"Project doesn't exist at: {projectFile}");

        ConsoleLogger.Default.WriteLine($"Project exists at {projectFile}");

        Project project;
        try
        {
            ConsoleLogger.Default.WriteLine("Loading project\n");
            project = await _workspace.OpenProjectAsync(projectFile);
            ConsoleLogger.Default.WriteLine("\nLoaded project");
        }
        catch (Exception ex)
        {
            ConsoleLogger.Default.WriteError($"Error: {ex.Message}");
            throw;
        }

        var compilation = await project.GetCompilationAsync();
        if (compilation == null)
            throw new InvalidOperationException("Compilation returned null");

        var generator = new TestMetadataGenerator().AsSourceGenerator();
        var driver = CSharpGeneratorDriver.Create([generator], parseOptions: (CSharpParseOptions)project.ParseOptions!);

        return (compilation, driver);
    }

    [GlobalSetup(Target = nameof(Compile))]
    public void SetupCompile() => (_sampleCompilation, _sampleDriver) = SetupAsync(SampleProjectPath).GetAwaiter().GetResult();

    [Benchmark]
    public GeneratorDriver Compile() => _sampleDriver!.RunGeneratorsAndUpdateCompilation(_sampleCompilation!, out _, out _);

    [GlobalCleanup]
    public void Cleanup()
    {
        _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
Contributor Author

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
Copy link
Contributor Author

TimothyMakkison commented Jan 27, 2026

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
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!
public class 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
Copy link
Contributor Author

TimothyMakkison commented Jan 28, 2026

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 😅

Method Mean Error StdDev Gen0 Gen1 Allocated
Compile 499.5 ms 19.50 ms 57.48 ms 18000.0000 4000.0000 165.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
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
Contributor Author

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
Contributor Author

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
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:

<PackageVersion Include="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 free to 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