Skip to content

Conversation

@LoopedBard3
Copy link
Member

@LoopedBard3 LoopedBard3 commented Jan 26, 2026

Fix MonoAOT file name not provided error during benchmark generation.

After updating to latest BDN (and using a dev ASM Resolver version) the performance repo started hitting the error:

// start   restore "/<dir>/e/performance/artifacts/bin/MicroBenchmarks/Release/net11.0/MicroBenchmarks-MonoAOTLLVM-1/DllGatherer.csproj" --packages "/<dir>/e/performance/artifacts/packages" --nodeReuse:false /p:UseSharedCompilation=false /p:Deterministic=true /p:Optimize=true -bl:MicroBenchmarks-MonoAOTLLVM-1-restore.binlog /p:ArtifactsPath="/<dir>/e/performance/artifacts/bin/MicroBenchmarks/Release/net11.0/MicroBenchmarks-MonoAOTLLVM-1/" /p:OutDir="/<dir>/e/performance/artifacts/bin/MicroBenchmarks/Release/net11.0/MicroBenchmarks-MonoAOTLLVM-1/bin/Release/net11.0/linux-x64/" /p:OutputPath="/<dir>/e/performance/artifacts/bin/MicroBenchmarks/Release/net11.0/MicroBenchmarks-MonoAOTLLVM-1/bin/Release/net11.0/linux-x64/" /p:PublishDir="/<dir>/e/performance/artifacts/bin/MicroBenchmarks/Release/net11.0/MicroBenchmarks-MonoAOTLLVM-1/bin/Release/net11.0/linux-x64/publish/" in /<dir>/e/performance/artifacts/bin/MicroBenchmarks/Release/net11.0/MicroBenchmarks-MonoAOTLLVM-1
// ***** Done, took 00:00:00 (0.18 sec)   *****
// Found 2 benchmarks:
//   ArrayDeAbstraction.foreach_static_readonly_array_in_loop: MonoAOTLLVM(Runtime=MonoAOTLLVM, Toolchain=MonoAOTLLVM, IterationTime=250ms, MaxIterationCount=20, MinIterationCount=15, WarmupCount=1)
//   ArrayDeAbstraction.foreach_member_array_via_interface_property: MonoAOTLLVM(Runtime=MonoAOTLLVM, Toolchain=MonoAOTLLVM, IterationTime=250ms, MaxIterationCount=20, MinIterationCount=15, WarmupCount=1)

// Generate Exception: System.InvalidOperationException: Cannot start process because a file name has not been provided.
   at System.Diagnostics.Process.Start()
   at BenchmarkDotNet.Toolchains.DotNetCli.DotNetCliCommandExecutor.Execute(DotNetCliCommand parameters)
   at BenchmarkDotNet.Toolchains.DotNetCli.DotNetCliCommand.Restore()
   at BenchmarkDotNet.Toolchains.DotNetCli.DotNetCliCommand.RestoreThenBuild()
   at BenchmarkDotNet.Toolchains.CsProj.CsProjGenerator.GatherReferences(BuildPartition buildPartition, ArtifactsPaths artifactsPaths, ILogger logger)
   at BenchmarkDotNet.Toolchains.MonoAotLLVM.MonoAotLLVMGenerator.GenerateProject(BuildPartition buildPartition, ArtifactsPaths artifactsPaths, ILogger logger)
   at BenchmarkDotNet.Toolchains.GeneratorBase.GenerateProject(BuildPartition buildPartition, ILogger logger, String rootArtifactsFolderPath)

// BenchmarkDotNet has failed to build the auto-generated boilerplate code.
// It can be found in /<dir>/e/performance/artifacts/bin/MicroBenchmarks/Release/net11.0/MicroBenchmarks-MonoAOTLLVM-1
// Please follow the troubleshooting guide: https://benchmarkdotnet.org/articles/guides/troubleshooting.html

// ** Remained 336 (99.4%) benchmark(s) to run. Estimated finish 2026-01-21 22:41 (0h 0m from now) **
// ***** BenchmarkRunner: Finish  *****

// * Export *
  <dir>/uploads/BenchmarkDotNet.Artifacts/results/ArrayDeAbstraction-report-github.md
  <dir>/uploads/BenchmarkDotNet.Artifacts/results/ArrayDeAbstraction-report-full.json
  <dir>/uploads/BenchmarkDotNet.Artifacts/results/ArrayDeAbstraction-perf-lab-report.json

With this change (and a dev AsmResolver version) this error seems to be fixed in local MonoAOT testing:

// start dotnet  restore "<path>/performance/artifacts/bin/MicroBenchmarks/Release/net11.0/MicroBenchmarks-MonoAOTLLVM-1/BenchmarkDotNet.Autogenerated.csproj" --packages "<path>/performance/artifacts/packages" --nodeReuse:false /p:UseSharedCompilation=false /p:Deterministic=true /p:Optimize=true -bl:MicroBenchmarks-MonoAOTLLVM-1-restore.binlog /p:ArtifactsPath="<path>/performance/artifacts/bin/MicroBenchmarks/Release/net11.0/MicroBenchmarks-MonoAOTLLVM-1/" /p:OutDir="<path>/performance/artifacts/bin/MicroBenchmarks/Release/net11.0/MicroBenchmarks-MonoAOTLLVM-1/bin/Release/net11.0/linux-x64/" /p:OutputPath="<path>/performance/artifacts/bin/MicroBenchmarks/Release/net11.0/MicroBenchmarks-MonoAOTLLVM-1/bin/Release/net11.0/linux-x64/" /p:PublishDir="<path>/performance/artifacts/bin/MicroBenchmarks/Release/net11.0/MicroBenchmarks-MonoAOTLLVM-1/bin/Release/net11.0/linux-x64/publish/" in <path>/performance/artifacts/bin/MicroBenchmarks/Release/net11.0/MicroBenchmarks-MonoAOTLLVM-1
  Determining projects to restore...
  Packaged ID: <path>/performance/monoaot/pack
  Restored <path>/performance/artifacts/bin/MicroBenchmarks/Release/net11.0/MicroBenchmarks-MonoAOTLLVM-1/BenchmarkDotNet.Autogenerated.csproj (in 4.11 sec).
  3 of 4 projects are up-to-date for restore.
// command took 6 sec and exited with 0
// start dotnet  build "<path>/performance/artifacts/bin/MicroBenchmarks/Release/net11.0/MicroBenchmarks-MonoAOTLLVM-1/BenchmarkDotNet.Autogenerated.csproj" -f net11.0 -c Release --no-restore --nodeReuse:false /p:UseSharedCompilation=false /p:Deterministic=true /p:Optimize=true /p:NuGetPackageRoot="<path>/performance/artifacts/packages" -bl:MicroBenchmarks-MonoAOTLLVM-1-build-no-restore.binlog /p:ArtifactsPath="<path>/performance/artifacts/bin/MicroBenchmarks/Release/net11.0/MicroBenchmarks-MonoAOTLLVM-1/" /p:OutDir="<path>/performance/artifacts/bin/MicroBenchmarks/Release/net11.0/MicroBenchmarks-MonoAOTLLVM-1/bin/Release/net11.0/linux-x64/" /p:OutputPath="<path>/performance/artifacts/bin/MicroBenchmarks/Release/net11.0/MicroBenchmarks-MonoAOTLLVM-1/bin/Release/net11.0/linux-x64/" /p:PublishDir="<path>/performance/artifacts/bin/MicroBenchmarks/Release/net11.0/MicroBenchmarks-MonoAOTLLVM-1/bin/Release/net11.0/linux-x64/publish/" --output "<path>/performance/artifacts/bin/MicroBenchmarks/Release/net11.0/MicroBenchmarks-MonoAOTLLVM-1/bin/Release/net11.0/linux-x64/" in <path>/performance/artifacts/bin/MicroBenchmarks/Release/net11.0/MicroBenchmarks-MonoAOTLLVM-1
  Packaged ID: <path>/performance/monoaot/pack
  Reporting -> <path>/performance/artifacts/bin/MicroBenchmarks/Release/net11.0/MicroBenchmarks-MonoAOTLLVM-1/bin/Release/net11.0/linux-x64/Reporting.dll
  BenchmarkDotNet.Extensions -> <path>/performance/artifacts/bin/MicroBenchmarks/Release/net11.0/MicroBenchmarks-MonoAOTLLVM-1/bin/Release/net11.0/linux-x64/BenchmarkDotNet.Extensions.dll
  MicroBenchmarks -> <path>/performance/artifacts/bin/MicroBenchmarks/Release/net11.0/MicroBenchmarks-MonoAOTLLVM-1/bin/Release/net11.0/linux-x64/MicroBenchmarks.dll
  BenchmarkDotNet.Autogenerated -> <path>/performance/artifacts/bin/MicroBenchmarks/Release/net11.0/MicroBenchmarks-MonoAOTLLVM-1/bin/Release/net11.0/linux-x64/MicroBenchmarks-MonoAOTLLVM-1.dll
  BenchmarkDotNet.Autogenerated -> <path>/performance/artifacts/bin/MicroBenchmarks/Release/net11.0/MicroBenchmarks-MonoAOTLLVM-1/bin/Release/net11.0/linux-x64/publish/
  [1/229] System.Diagnostics.Tracing.dll -> System.Diagnostics.Tracing.dll.so, System.Diagnostics.Tracing.dll-llvm.o
  [2/229] System.Buffers.dll -> System.Buffers.dll.so, System.Buffers.dll-llvm.o
...
  [229/229] Microsoft.CodeAnalysis.dll -> Microsoft.CodeAnalysis.dll.so, Microsoft.CodeAnalysis.dll-llvm.o
  CompiledAssemblies:
Build succeeded.
    0 Warning(s)
    0 Error(s)
Time Elapsed 00:05:36.47
// command took 336.81 sec and exited with 0
// ***** Done, took 00:06:00 (360.8 sec)   *****
// Found 1 benchmarks:
//   BilinearTest.Interpol_Scalar: MonoAOTLLVM(Runtime=MonoAOTLLVM, Toolchain=MonoAOTLLVM, IterationTime=250ms, MaxIterationCount=20, MinIterationCount=15, WarmupCount=1)
// **************************
// Benchmark: BilinearTest.Interpol_Scalar: MonoAOTLLVM(Runtime=MonoAOTLLVM, Toolchain=MonoAOTLLVM, IterationTime=250ms, MaxIterationCount=20, MinIterationCount=15, WarmupCount=1)
// *** Execute ***
// Launch: 1 / 1
// Execute: <path>/performance/artifacts/bin/MicroBenchmarks/Release/net11.0/MicroBenchmarks-MonoAOTLLVM-1/bin/Release/net11.0/linux-x64/publish/MicroBenchmarks-MonoAOTLLVM-1 --anonymousPipes 221 222 --benchmarkName BilinearTest.Interpol_Scalar --job MonoAOTLLVM --diagnoserRunMode 3 --benchmarkId 0 in <path>/performance/artifacts/bin/MicroBenchmarks/Release/net11.0/MicroBenchmarks-MonoAOTLLVM-1/bin/Release/net11.0/linux-x64/publish
// Failed to set up high priority (Permission denied). In order to run benchmarks with high priority, make sure you have the right permissions.
// BeforeAnythingElse
// Benchmark Process Environment Information:
// BenchmarkDotNet v0.16.0-custom.20260126.102
// Runtime=.NET 11.0.0 (11.0.0-ci, 42.42.42.42424) using MonoVM, X64 x86-64-v2
// GC=Non-concurrent Workstation
// HardwareIntrinsics=SSE3+SSSE3+SSE4.1+SSE4.2+POPCNT,X86Base+SSE+SSE2,AES+PCLMUL VectorSize=128
// Job: MonoAOTLLVM(IterationTime=250ms, MaxIterationCount=20, MinIterationCount=15, WarmupCount=1)
OverheadJitting  1: 1 op, 7501.00 ns, 7.5010 us/op
WorkloadJitting  1: 1 op, 66611.00 ns, 66.6110 us/op
OverheadJitting  2: 30 op, 1600.00 ns, 53.3333 ns/op
WorkloadJitting  2: 30 op, 791024.00 ns, 26.3675 us/op
OverheadJitting  3: 30 op, 1800.00 ns, 60.0000 ns/op
WorkloadJitting  3: 30 op, 553487.00 ns, 18.4496 us/op
OverheadJitting  4: 30 op, 7301.00 ns, 243.3667 ns/op
WorkloadJitting  4: 30 op, 1428524.00 ns, 47.6175 us/op
OverheadJitting  5: 1 op, 2901.00 ns, 2.9010 us/op
WorkloadJitting  5: 1 op, 26104.00 ns, 26.1040 us/op
WorkloadPilot    1: 1 op, 56609.00 ns, 56.6090 us/op

Cause based on copilot investigation:
<Copilot>
Root Cause: The commit 9368a7d ("Update gather references") introduced a bug where the CliPath from CsProjGenerator is passed directly to DotNetCliCommand, but when
options.CliPath is null, the ConfigParser passes an empty string "" instead. The code only handled null using the ?? operator, treating empty strings as valid paths,
which caused Process.Start() to fail with "Cannot start process because a file name has not been provided."

Fix: Changed two locations to use IsBlank() (which checks for null, empty, or whitespace) instead of just null-coalescing:

     - DotNetCliCommand.cs line 42:  // Before
       CliPath = cliPath ?? DotNetCliCommandExecutor.DefaultDotNetCliPath.Value;
       // After
       CliPath = cliPath.IsBlank() ? DotNetCliCommandExecutor.DefaultDotNetCliPath.Value : cliPath;
     - DotNetCliCommandExecutor.cs line 109:  // Before
       FileName = customDotNetCliPath ?? DefaultDotNetCliPath.Value,
       // After
       FileName = customDotNetCliPath.IsBlank() ? DefaultDotNetCliPath.Value : customDotNetCliPath

</ Copilot>

@timcassell timcassell merged commit 9612c51 into dotnet:master Jan 27, 2026
19 of 21 checks passed
@timcassell timcassell added this to the v0.16.0 milestone Jan 27, 2026
@LoopedBard3 LoopedBard3 deleted the FixMonoAOTError branch January 27, 2026 20:15
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants