Add support for mono AOT pass (#940)
* Add support for mono AOT pass * Add documentation for using mono aot args
This commit is contained in:
Родитель
8d971412a8
Коммит
573566b70f
|
@ -9,6 +9,9 @@ If you apply `[MonoJob]` attribute to your class we use your default mono runtim
|
|||
If you want to compare different versions of Mono you need to provide use the custom paths.
|
||||
You can do this today by using the overloaded ctor of MonoJob attribute or by specifying the runtime in a fluent way.
|
||||
|
||||
The mono runtime can also operate as an ahead-of-time compiler. Using mono's AOT mode requires providing the AOT compilation
|
||||
arguments, as well as the path to mono's corlib. (See IntroCustomMonoObjectStyleAot in the below example).
|
||||
|
||||
### Source code
|
||||
|
||||
[!code-csharp[IntroCustomMono.cs](../../../samples/BenchmarkDotNet.Samples/IntroCustomMono.cs)]
|
||||
|
|
|
@ -3,6 +3,7 @@ using BenchmarkDotNet.Configs;
|
|||
using BenchmarkDotNet.Environments;
|
||||
using BenchmarkDotNet.Jobs;
|
||||
using BenchmarkDotNet.Running;
|
||||
using System;
|
||||
|
||||
namespace BenchmarkDotNet.Samples
|
||||
{
|
||||
|
@ -42,6 +43,36 @@ namespace BenchmarkDotNet.Samples
|
|||
}
|
||||
}
|
||||
|
||||
// ** Object Style, Using AOT **
|
||||
|
||||
[Config(typeof(Config))]
|
||||
public class IntroCustomMonoObjectStyleAot
|
||||
{
|
||||
private class Config : ManualConfig
|
||||
{
|
||||
public void AddMono (string name, string mono_top_dir)
|
||||
{
|
||||
var aot_compile_args = "--aot=llvm";
|
||||
var mono_bcl = String.Format(@"{0}\lib\mono\4.5", mono_top_dir);
|
||||
var mono_bin = String.Format(@"{0}\bin\mono", mono_top_dir);
|
||||
Add(Job.ShortRun.With(new MonoRuntime(
|
||||
name, mono_bin, aot_compile_args, mono_bcl)));
|
||||
}
|
||||
|
||||
public Config()
|
||||
{
|
||||
AddMono("Mono x64", @"C:\Program Files\Mono");
|
||||
AddMono("Mono x86", @"C:\Program Files (x86)");
|
||||
}
|
||||
}
|
||||
|
||||
[Benchmark]
|
||||
public void Foo()
|
||||
{
|
||||
// Benchmark body
|
||||
}
|
||||
}
|
||||
|
||||
// *** Fluent Config ***
|
||||
|
||||
public class IntroCustomMonoFluentConfig
|
||||
|
|
|
@ -78,16 +78,28 @@ namespace BenchmarkDotNet.Environments
|
|||
{
|
||||
public string CustomPath { get; }
|
||||
|
||||
public string AotArgs { get; }
|
||||
|
||||
public string MonoBclPath { get; }
|
||||
|
||||
public MonoRuntime() : base("Mono")
|
||||
{
|
||||
}
|
||||
|
||||
public MonoRuntime(string name, string customPath) : base(name) => CustomPath = customPath;
|
||||
|
||||
public MonoRuntime(string name, string customPath, string aotArgs, string monoBclPath) : base(name)
|
||||
{
|
||||
CustomPath = customPath;
|
||||
AotArgs = aotArgs;
|
||||
MonoBclPath = monoBclPath;
|
||||
}
|
||||
|
||||
public override bool Equals(object obj) => obj is MonoRuntime other && Equals(other);
|
||||
|
||||
public bool Equals(MonoRuntime other) => other != null && Name == other.Name && CustomPath == other.CustomPath;
|
||||
public bool Equals(MonoRuntime other) => other != null && Name == other.Name && CustomPath == other.CustomPath && AotArgs == other.AotArgs && MonoBclPath == other.MonoBclPath;
|
||||
|
||||
public override int GetHashCode() => Name.GetHashCode() ^ (CustomPath?.GetHashCode() ?? 0);
|
||||
int GetHashCodeComposite() => String.Format("{0}{1}{2}", CustomPath?.GetHashCode(), AotArgs?.GetHashCode(), MonoBclPath?.GetHashCode()).GetHashCode ();
|
||||
public override int GetHashCode() => Name.GetHashCode() ^ GetHashCodeComposite ();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -118,6 +118,8 @@ namespace BenchmarkDotNet.Toolchains
|
|||
case MonoRuntime mono:
|
||||
start.FileName = mono.CustomPath ?? "mono";
|
||||
start.Arguments = GetMonoArguments(benchmarkCase.Job, exePath, args, resolver);
|
||||
if (mono.MonoBclPath != null)
|
||||
start.EnvironmentVariables["MONO_PATH"] = mono.MonoBclPath;
|
||||
break;
|
||||
default:
|
||||
throw new NotSupportedException("Runtime = " + runtime);
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
|
@ -11,9 +12,74 @@ using JetBrains.Annotations;
|
|||
using Microsoft.CodeAnalysis;
|
||||
using Microsoft.CodeAnalysis.CSharp;
|
||||
using OurPlatform = BenchmarkDotNet.Environments.Platform;
|
||||
using MonoRuntime = BenchmarkDotNet.Environments.MonoRuntime;
|
||||
|
||||
namespace BenchmarkDotNet.Toolchains.Roslyn
|
||||
{
|
||||
[PublicAPI]
|
||||
public class MonoAotBuilder : Builder
|
||||
{
|
||||
MonoRuntime mono;
|
||||
|
||||
public MonoAotBuilder (MonoRuntime monoReference) => mono = monoReference;
|
||||
|
||||
[PublicAPI]
|
||||
public override BuildResult Build(GenerateResult generateResult, BuildPartition buildPartition, ILogger logger)
|
||||
{
|
||||
BuildResult result = base.Build(generateResult, buildPartition, logger);
|
||||
|
||||
if (!result.IsBuildSuccess)
|
||||
return result;
|
||||
|
||||
var dllPath = generateResult.ArtifactsPaths.ExecutablePath;
|
||||
var monoPath = mono.CustomPath ?? "mono";
|
||||
|
||||
try
|
||||
{
|
||||
using (var process = new Process { StartInfo = CreateMonoAot(monoPath, dllPath) })
|
||||
{
|
||||
logger.WriteLineInfo("// Execute: " + process.StartInfo.FileName + " " + process.StartInfo.Arguments);
|
||||
ConsoleExitHandler.Instance.Process = process;
|
||||
process.Start();
|
||||
process.WaitForExit(); // should we add timeout here?
|
||||
|
||||
if (process.ExitCode != 0) {
|
||||
string failure = String.Format("Attempt to AOT failed: {0} {1} with exit code: {2}", process.StartInfo.FileName, process.StartInfo.Arguments, process.ExitCode);
|
||||
logger.WriteLineError(failure);
|
||||
return BuildResult.Failure(generateResult, failure);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
ConsoleExitHandler.Instance.Process = null;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private ProcessStartInfo CreateMonoAot(string monoPath, string filePath)
|
||||
{
|
||||
var absFilePath = Path.GetFullPath(filePath);
|
||||
var start = new ProcessStartInfo
|
||||
{
|
||||
UseShellExecute = false,
|
||||
RedirectStandardOutput = true,
|
||||
RedirectStandardInput = true,
|
||||
RedirectStandardError = true,
|
||||
CreateNoWindow = true,
|
||||
WorkingDirectory = Path.GetDirectoryName(absFilePath)
|
||||
};
|
||||
start.FileName = monoPath;
|
||||
start.Arguments = String.Format("{0} {1}", mono.AotArgs, absFilePath);
|
||||
if (mono.MonoBclPath != null)
|
||||
start.EnvironmentVariables["MONO_PATH"] = mono.MonoBclPath;
|
||||
|
||||
return start;
|
||||
}
|
||||
}
|
||||
|
||||
[PublicAPI]
|
||||
public class Builder : IBuilder
|
||||
{
|
||||
|
@ -22,7 +88,7 @@ namespace BenchmarkDotNet.Toolchains.Roslyn
|
|||
private static readonly Lazy<AssemblyMetadata[]> FrameworkAssembliesMetadata = new Lazy<AssemblyMetadata[]>(GetFrameworkAssembliesMetadata);
|
||||
|
||||
[PublicAPI]
|
||||
public BuildResult Build(GenerateResult generateResult, BuildPartition buildPartition, ILogger logger)
|
||||
public virtual BuildResult Build(GenerateResult generateResult, BuildPartition buildPartition, ILogger logger)
|
||||
{
|
||||
logger.WriteLineInfo($"BuildScript: {generateResult.ArtifactsPaths.BuildScriptFilePath}");
|
||||
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
using BenchmarkDotNet.Jobs;
|
||||
using BenchmarkDotNet.Loggers;
|
||||
using BenchmarkDotNet.Running;
|
||||
using BenchmarkDotNet.Environments;
|
||||
using JetBrains.Annotations;
|
||||
|
||||
namespace BenchmarkDotNet.Toolchains.Roslyn
|
||||
|
@ -14,6 +15,11 @@ namespace BenchmarkDotNet.Toolchains.Roslyn
|
|||
{
|
||||
public static IToolchain Instance = new RoslynToolchain();
|
||||
|
||||
[PublicAPI]
|
||||
public RoslynToolchain(MonoRuntime mono) : base("MonoAot", new Generator(), new MonoAotBuilder(mono), new Executor())
|
||||
{
|
||||
}
|
||||
|
||||
[PublicAPI]
|
||||
public RoslynToolchain() : base("Roslyn", new Generator(), new Builder(), new Executor())
|
||||
{
|
||||
|
|
|
@ -20,10 +20,14 @@ namespace BenchmarkDotNet.Toolchains
|
|||
switch (runtime)
|
||||
{
|
||||
case ClrRuntime _:
|
||||
case MonoRuntime _:
|
||||
if(RuntimeInformation.IsNetCore)
|
||||
return CsProjClassicNetToolchain.Current.Value;
|
||||
|
||||
return RoslynToolchain.Instance;
|
||||
case MonoRuntime mono:
|
||||
if(mono.AotArgs != null)
|
||||
return new RoslynToolchain (mono);
|
||||
|
||||
return RoslynToolchain.Instance;
|
||||
case CoreRuntime _:
|
||||
return CsProjCoreToolchain.Current.Value;
|
||||
|
|
Загрузка…
Ссылка в новой задаче