File: Harness\Configs.cs
Web Access
Project: src\test\Microsoft.ML.PerformanceTests\Microsoft.ML.PerformanceTests.csproj (Microsoft.ML.PerformanceTests)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
 
using System;
using System.Collections.Generic;
using System.Runtime.Versioning;
using BenchmarkDotNet.Configs;
using BenchmarkDotNet.Jobs;
using BenchmarkDotNet.Toolchains;
using BenchmarkDotNet.Toolchains.CsProj;
using BenchmarkDotNet.Toolchains.DotNetCli;
using Microsoft.ML.PerformanceTests.Harness;
 
namespace Microsoft.ML.PerformanceTests
{
    public class RecommendedConfig : ManualConfig
    {
        public RecommendedConfig()
        {
            Add(DefaultConfig.Instance.WithOption(ConfigOptions.Default, true).WithBuildTimeout(TimeSpan.FromMinutes(5))); // this config contains all of the basic settings (exporters, columns etc)
 
            AddJob(GetJobDefinition()// job defines how many times given benchmark should be executed
                .WithCustomBuildConfiguration(GetBuildConfigurationName())
                .WithToolchain(CreateToolchain())); // toolchain is responsible for generating, building and running dedicated executable per benchmark
 
            AddColumn(new ExtraMetricColumn()); // an extra column that can display additional metric reported by the benchmarks
        }
 
        protected virtual Job GetJobDefinition()
            => Job.Default
                .WithWarmupCount(1) // ML.NET benchmarks are typically CPU-heavy benchmarks, 1 warmup is usually enough
                .WithMaxIterationCount(20)
                .AsDefault(); // this way we tell BDN that it's a default config which can be overwritten
 
        /// <summary>
        /// we need our own toolchain because MSBuild by default does not copy recursive native dependencies to the output
        /// </summary>
        private IToolchain CreateToolchain()
        {
#if NETFRAMEWORK
            var tfm = "net462";
            var csProj = CsProjClassicNetToolchain.From(tfm);
#else
            var frameworkName = new FrameworkName(AppContext.TargetFrameworkName);
            var frameworkVersion = frameworkName.Version.ToString(2);
            var settings = new NetCoreAppSettings($"net{frameworkVersion}", null, $".NET {frameworkVersion}");
 
            var tfm = settings.TargetFrameworkMoniker;
            var csProj = CsProjCoreToolchain.From(settings);
#endif
            return new Toolchain(
                tfm,
                new ProjectGenerator(tfm), // custom generator that copies native dependencies
                csProj.Builder,
                csProj.Executor);
        }
 
        protected static string GetBuildConfigurationName()
        {
#if NETFRAMEWORK
            return "Release-netfx";
#else
            return "Release";
#endif
        }
    }
 
    public class TrainConfig : RecommendedConfig
    {
        protected override Job GetJobDefinition()
            => Job.Dry // the "Dry" job runs the benchmark exactly once, without any warmup to mimic real-world scenario
                  .WithCustomBuildConfiguration(GetBuildConfigurationName())
                  .WithLaunchCount(3); // BDN will run 3 dedicated processes, sequentially
    }
}