BenchmarkDotNet icon indicating copy to clipboard operation
BenchmarkDotNet copied to clipboard

Async GlobalSetup does not work with InProcess toolchain

Open mstefarov opened this issue 2 years ago • 5 comments

https://github.com/dotnet/BenchmarkDotNet/issues/521 added support for async GlobalSetup, but it appears that InProcess toolchain does not wait for the async setup method to finish. Simple reproducer:

using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Running;
using System.Threading.Tasks;

namespace AsyncGlobalSetupRepro
{
    [InProcess]
    public class MyBenchmarkClass
    {
        private string _foo;

        [GlobalSetup]
        public async Task MyAsyncSetup()
        {
            await Task.Delay(1000);
            _foo = "hello";
        }

        [Benchmark]
        public int MyBenchmark() => _foo.Length; // NullReferenceException!
    }

    public class Program
    {
        public static void Main(string[] args)
        {
            BenchmarkRunner.Run(typeof(MyBenchmarkClass));
        }
    }
}

It looks like MyAsyncSetup gets invoked as a regular method here, and then JITting starts immediately without waiting for it to finish: https://github.com/dotnet/BenchmarkDotNet/blob/e7ff4cefcc8d429205a21a76045e82688ee063c5/src/BenchmarkDotNet/Engines/EngineFactory.cs#L28

mstefarov avatar Jul 07 '21 17:07 mstefarov

Hi, I experience the same problem here ! ✋

When using BDN with dotnet/crank, the --inProcess flag is passed to the BDN executable, and my benchmark throws a NullReferenceException. By testing my benchmarks directly with BDN (not through Crank) I realized that my async GlobalSetup method was not awaited/executed when the --inProcess flag is toggled.

corrieriluca avatar Oct 22 '21 12:10 corrieriluca

Yeah, just hit this myself. Looks like #1968 will fix this so hopefully that gets merged in soon.

Turnerj avatar Sep 13 '22 01:09 Turnerj