wpf BenchmarkDotNet SimpleJob属性:如何指定与net6.0-windows等效RuntimeMoniker

hgtggwj0  于 2023-10-22  发布在  Windows
关注(0)|答案(2)|浏览(103)

我想在一个WPF类库中对类进行基准测试,该类库同时具有.NET 6.0和.NET Framework 4.8的多目标。下面是项目文件:
WpfClassLibrary.cs:

<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <TargetFrameworks>net6.0-windows;net4.8</TargetFrameworks>
    <UseWPF>true</UseWPF>
  </PropertyGroup>
</Project>

我想要测试的类,simple示例化了一个System.Windows.Documents.FlowDocument对象:

namespace WpfClassLibrary
{
    using System.Windows.Documents;

    public class WpfClass
    {
        public FlowDocument Document { get; } = new FlowDocument();
    }
}

下面是基准测试项目的项目文件:
BenchmarkingWpfClassLibrary.csproj:

<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFrameworks>net6.0-windows;net4.8</TargetFrameworks>
    <UseWPF>true</UseWPF>
  </PropertyGroup>
  <ItemGroup>
    <PackageReference Include="BenchmarkDotNet" Version="0.13.7" />
  </ItemGroup>
  <ItemGroup>
    <ProjectReference Include="..\WpfClassLibrary\WpfClassLibrary.csproj" />
  </ItemGroup>
</Project>

基准本身:
Program.cs:

namespace Benchmarks
{
    using BenchmarkDotNet.Attributes;
    using BenchmarkDotNet.Jobs;
    using BenchmarkDotNet.Running;
    using WpfClassLibrary;

    internal class Program
    {
        static void Main(string[] args)
        {
            var results = BenchmarkRunner.Run<WpfClassBenchmarks>();
        }
    }

    //[SimpleJob(RuntimeMoniker.Net48)]
    //[SimpleJob(RuntimeMoniker.Net60)]
    public class WpfClassBenchmarks
    {
        [Benchmark]
        public void WpfClass()
        {
            _ = new WpfClass();
        }
    }
}

如果我按原样运行,基准测试就可以构建并运行良好。但是,如果我注解掉这两个SimpleJob属性,.NET Framework 4.8基准测试可以正常构建和运行,但.NET 6.0基准测试却不能。我得到以下错误:

System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation.
 ---> System.IO.FileNotFoundException: Could not load file or assembly 'PresentationFramework, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35'. The system cannot find the file specified.
File name: 'PresentationFramework, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35'
   at WpfClassLibrary.WpfClass..ctor()
   at Benchmarks.WpfClassBenchmarks.WpfClass() in C:\Users\stevensd\source\BenchmarkingWpfClassLibrary\Benchmarks\Program.cs:line 23
   at BenchmarkDotNet.Autogenerated.Runnable_0.WorkloadActionNoUnroll(Int64 invokeCount) in C:\Users\stevensd\source\BenchmarkingWpfClassLibrary\Benchmarks\bin\Release\net6.0-windows\7eaf257f-9929-493b-9995-b7827893b4db\7eaf257f-9929-493b-9995-b7827893b4db.notcs:line 311
   at BenchmarkDotNet.Engines.Engine.RunIteration(IterationData data)
   at BenchmarkDotNet.Engines.EngineFactory.Jit(Engine engine, Int32 jitIndex, Int32 invokeCount, Int32 unrollFactor)
   at BenchmarkDotNet.Engines.EngineFactory.CreateReadyToRun(EngineParameters engineParameters)
   at BenchmarkDotNet.Autogenerated.Runnable_0.Run(IHost host, String benchmarkName) in C:\Users\stevensd\source\BenchmarkingWpfClassLibrary\Benchmarks\bin\Release\net6.0-windows\7eaf257f-9929-493b-9995-b7827893b4db\7eaf257f-9929-493b-9995-b7827893b4db.notcs:line 176
   --- End of inner exception stack trace ---
   at System.RuntimeMethodHandle.InvokeMethod(Object target, Span`1& arguments, Signature sig, Boolean constructor, Boolean wrapExceptions)
   at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
   at System.Reflection.MethodBase.Invoke(Object obj, Object[] parameters)
   at BenchmarkDotNet.Autogenerated.UniqueProgramName.AfterAssemblyLoadingAttached(String[] args) in C:\Users\stevensd\source\BenchmarkingWpfClassLibrary\Benchmarks\bin\Release\net6.0-windows\7eaf257f-9929-493b-9995-b7827893b4db\7eaf257f-9929-493b-9995-b7827893b4db.notcs:line 57

我认为发生的事情是,当没有指定SimpleJob属性时,BenchmarkDotNet正在使用适当的net6.0-windows名字对象构建基准。但是,当将SimpleJob属性与名字对象RuntimeMoniker.Net60一起使用时,它将使用错误的net6.0构建。
如何指定使用net60-windows而不是net60的运行时名字对象的简单作业?
原始程式码:https://github.com/DanStevens/BenchmarkingWpfClassLibrary

tgabmvqs

tgabmvqs1#

我认为你需要使用IConfig来编程实现这一点,即。不能直接使用SimpleJobAttribute

internal class Program
{
    static void Main(string[] args)
    {
        var results = BenchmarkRunner.Run<WpfClassBenchmarks>(
            ManualConfig.Create(DefaultConfig.Instance)
                .AddJob(Job.Default.WithRuntime(ClrRuntime.Net48))
                .AddJob(Job.Default.WithToolchain(
                    CsProjCoreToolchain.From(
                        new NetCoreAppSettings(
                            targetFrameworkMoniker: "net6.0-windows",
                            runtimeFrameworkVersion: null,
                            name: "6.0")))));
    }
}

public class WpfClassBenchmarks
{
    [Benchmark]
    public void WpfClass()
    {
        _ = new WpfClass();
    }
}

或者使用命令行参数指定运行时:

internal class Program
{
    static void Main(string[] args)
    {
        BenchmarkSwitcher.FromAssembly(typeof(Program).Assembly)
            .Run(args);
    }
}

指令:

dotnet run --configuration Release --framework net4.8 --runtimes net6.0-windows net48 --filter *
izkcnapc

izkcnapc2#

虽然可以在配置as suggested by mm8中显式指定工具链,但如果进程以.NET 6.0运行,则默认的Job配置将自动识别并使用“net6.0-windows”名字对象。因此,以下也是可行的:

var config = DefaultConfig.Instance
    .AddJob(Job.Default.WithId("net60"))
    .AddJob(Job.Default.WithRuntime(ClrRuntime.Net48).WithId("net48"));
var results = BenchmarkRunner.Run<WpfClassBenchmarks>(config);

感谢Adam Sitnik的回答。

相关问题