BenchmarkDotNet icon indicating copy to clipboard operation
BenchmarkDotNet copied to clipboard

NativeAot build fails with `ValueTask` and `UniTask`

Open timcassell opened this issue 3 years ago • 2 comments
trafficstars

Trying to benchmark UniTask and ValueTask in NativeAot causes the build to fail. If I comment out the UniTask code, it works to benchmark ValueTask, and likewise if I comment out the ValueTask code, it works to benchmark UniTask. But if both are present, the build fails.

Code

class Program
{
    static void Main(string[] args)
    {
        BenchmarkSwitcher.FromAssembly(typeof(Program).Assembly).Run("--runtimes nativeaot60 --filter *".Split(' '));
    }
}

public struct Struct32
{
    public long l1, l2, l3, l4;
}

public class AsyncAwait
{
    [Params(true, false)]
    public bool Pending;

    private readonly Stack<AutoResetUniTaskCompletionSource> _completionSources = new Stack<AutoResetUniTaskCompletionSource>(1);

    private void ResolveSources()
    {
        while (_completionSources.Count > 0)
        {
            _completionSources.Pop().TrySetResult();
        }
    }
        
    [Benchmark]
    public void UniTask()
    {
        UniTask_ExecuteAsync().Forget();
        ResolveSources();
    }

    private async UniTask UniTask_ExecuteAsync()
    {
        await UniTask_GetAndConsumeValuesAsync<Struct32, object>();
        await UniTask_GetAndConsumeValuesAsync<object, Struct32>();
    }

    private async UniTask UniTask_GetAndConsumeValuesAsync<T1, T2>()
    {
        _ = await UniTask_GetValueAsync<T1>();
        _ = await UniTask_GetValueAsync<T2>();
    }

    private async UniTask<T> UniTask_GetValueAsync<T>()
    {
        await GetBaseUniTask();
        return default;
    }

    private UniTask GetBaseUniTask()
    {
        if (!Pending)
        {
            return Cysharp.Threading.Tasks.UniTask.CompletedTask;
        }
        var completionSource = AutoResetUniTaskCompletionSource.Create();
        _completionSources.Push(completionSource);
        return completionSource.Task;
    }

    [Benchmark]
    public void ValueTask()
    {
        _ = ValueTask_ExecuteAsync();
        ResolveSources();
    }

    private async ValueTask ValueTask_ExecuteAsync()
    {
        await ValueTask_GetAndConsumeValuesAsync<Struct32, object>();
        await ValueTask_GetAndConsumeValuesAsync<object, Struct32>();
    }

    private async ValueTask ValueTask_GetAndConsumeValuesAsync<T1, T2>()
    {
        _ = await ValueTask_GetValueAsync<T1>();
        _ = await ValueTask_GetValueAsync<T2>();
    }

    private async ValueTask<T> ValueTask_GetValueAsync<T>()
    {
        await GetBaseValueTask();
        return default;
    }

    private ValueTask GetBaseValueTask()
    {
        if (!Pending)
        {
            return new ValueTask();
        }
        // Using UniTask as the base source since it is convertible to ValueTask without allocating.
        var completionSource = AutoResetUniTaskCompletionSource.Create();
        _completionSources.Push(completionSource);
        return completionSource.Task;
    }
}
// Build Error: Standard output:

 Standard error:
 Microsoft (R) Build Engine version 17.2.0+41abc5629 for .NET
Copyright (C) Microsoft Corporation. All rights reserved.
  Generating native code
EXEC : error : Failed to load type 'Cysharp.Threading.Tasks.IUniTaskSource`1' from assembly 'UniTask, Version=2.3.1.0, Culture=neutral, PublicKeyToken=7a576c6e8
fde454a' [C:\Users\Tim\source\repos\UniTaskBenchmark\bin\Release\net472\06426ff3-2141-4880-8179-04bce4183209\BenchmarkDotNet.Autogenerated.csproj]
  Internal.TypeSystem.TypeSystemException+TypeLoadException: Failed to load type 'Cysharp.Threading.Tasks.IUniTaskSource`1' from assembly 'UniTask, Version=2.3.
1.0, Culture=neutral, PublicKeyToken=7a576c6e8fde454a'
     at Internal.TypeSystem.ThrowHelper.ThrowTypeLoadException(ExceptionStringID id, String typeName, String assemblyName) in ILCompiler.TypeSystem.dll:token 0x
6000426+0x8
     at ILCompiler.DependencyAnalysis.NodeFactory.CreateConstructedTypeNode(TypeDesc type) in ILCompiler.Compiler.dll:token 0x6000be5+0x0
     at System.Collections.Concurrent.ConcurrentDictionary`2.GetOrAdd(TKey key, Func`2 valueFactory) in System.Collections.Concurrent.dll:token 0x60000d3+0x4f
     at ILCompiler.DependencyAnalysis.TentativeInstanceMethodNode.GetConditionalStaticDependencies(NodeFactory factory) in ILCompiler.Compiler.dll:token 0x60007
17+0x2f
     at ILCompiler.DependencyAnalysisFramework.DependencyAnalyzer`2.GetStaticDependenciesImpl(DependencyNodeCore`1 node) in ILCompiler.DependencyAnalysisFramewo
rk.dll:token 0x6000038+0x54
     at ILCompiler.DependencyAnalysisFramework.DependencyAnalyzer`2.GetStaticDependencies(DependencyNodeCore`1 node) in ILCompiler.DependencyAnalysisFramework.d
ll:token 0x6000039+0x8
     at ILCompiler.DependencyAnalysisFramework.DependencyAnalyzer`2.ProcessMarkStack() in ILCompiler.DependencyAnalysisFramework.dll:token 0x600003a+0x2c
     at ILCompiler.DependencyAnalysisFramework.DependencyAnalyzer`2.ComputeMarkedNodes() in ILCompiler.DependencyAnalysisFramework.dll:token 0x600003b+0x19
     at ILCompiler.ILScanner.ILCompiler.IILScanner.Scan() in ILCompiler.Compiler.dll:token 0x60002ee+0x0
     at ILCompiler.Program.Run(String[] args) in ilc.dll:token 0x600010f+0xb3e
     at ILCompiler.Program.Main(String[] args) in ilc.dll:token 0x6000115+0x5
C:\Users\Tim\.nuget\packages\microsoft.dotnet.ilcompiler\6.0.0-rc.1.21420.1\build\Microsoft.NETCore.Native.targets(283,5): error MSB3073: The command ""C:\Users
\Tim\.nuget\packages\runtime.win-x64.microsoft.dotnet.ilcompiler\6.0.0-rc.1.21420.1\tools\ilc" @"obj\Release\net6.0\win-x64\native\06426ff3-2141-4880-8179-04bce
4183209.ilc.rsp"" exited with code 1. [C:\Users\Tim\source\repos\UniTaskBenchmark\bin\Release\net472\06426ff3-2141-4880-8179-04bce4183209\BenchmarkDotNet.Autoge
nerated.csproj]

// BenchmarkDotNet has failed to build the auto-generated boilerplate code.
// It can be found in C:\Users\Tim\source\repos\UniTaskBenchmark\bin\Release\net472\06426ff3-2141-4880-8179-04bce4183209
// Please follow the troubleshooting guide: https://benchmarkdotnet.org/articles/guides/troubleshooting.html

I thought that #2012 might fix it (since UniTask depends on a higher version of System.Threading.Tasks.Extensions), but I tried with those changes and it still fails.

timcassell avatar Jun 26 '22 02:06 timcassell

bin\Release\net472\

What is the target framework moniker of this project? Could you please upload the project file as well?

adamsitnik avatar Jun 27 '22 08:06 adamsitnik

<TargetFrameworks>net6.0;net472</TargetFrameworks> I tried the root project build in both, and got the same failure.

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFrameworks>net472;net6.0</TargetFrameworks>
  </PropertyGroup>
  
  <ItemGroup>
    <PackageReference Include="UniTask" Version="2.3.1" />
  </ItemGroup>
  
  <ItemGroup>
    <ProjectReference Include="..\..\..\Documents\git\BenchmarkDotNet_net6\src\BenchmarkDotNet\BenchmarkDotNet.csproj" />
  </ItemGroup>

</Project>

(I referenced a local clone for the #2012 changes.)

timcassell avatar Jun 27 '22 10:06 timcassell