Skip to content

Commit 5196e6f

Browse files
author
Nathan Ricci
authored
Add AOT options to wasm runtime (#1722)
1 parent 6ffdb24 commit 5196e6f

File tree

9 files changed

+125
-15
lines changed

9 files changed

+125
-15
lines changed
Binary file not shown.

src/BenchmarkDotNet/ConsoleArguments/CommandLineOptions.cs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,9 @@ public class CommandLineOptions
190190
[Option("AOTCompilerMode", Required = false, Default = MonoAotCompilerMode.mini, HelpText = "Mono AOT compiler mode, either 'mini' or 'llvm'")]
191191
public MonoAotCompilerMode AOTCompilerMode { get; set; }
192192

193+
[Option("runtimeSrcDir", Required = false, HelpText = "Path to a local copy of dotnet/runtime. . Used by the WASM toolchain when AOTCompilerMode is 'wasm'.")]
194+
public DirectoryInfo RuntimeSrcDir { get; set; }
195+
193196
internal bool UserProvidedFilters => Filters.Any() || AttributeNames.Any() || AllCategories.Any() || AnyCategories.Any();
194197

195198
[Usage(ApplicationAlias = "")]
@@ -225,4 +228,4 @@ public static IEnumerable<Example> Examples
225228

226229
private static string Escape(string input) => UserInteractionHelper.EscapeCommandExample(input);
227230
}
228-
}
231+
}

src/BenchmarkDotNet/ConsoleArguments/ConfigParser.cs

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,7 @@ private static bool Validate(CommandLineOptions options, ILogger logger)
112112
logger.WriteLineError($"The provided runtime \"{runtime}\" is invalid. Available options are: {string.Join(", ", Enum.GetNames(typeof(RuntimeMoniker)).Select(name => name.ToLower()))}.");
113113
return false;
114114
}
115-
else if (runtimeMoniker == RuntimeMoniker.Wasm && (options.WasmMainJs == null || options.WasmMainJs.IsNotNullButDoesNotExist()))
115+
else if (runtimeMoniker == RuntimeMoniker.Wasm && !(options.AOTCompilerMode == MonoAotCompilerMode.wasm) && (options.WasmMainJs == null || options.WasmMainJs.IsNotNullButDoesNotExist()))
116116
{
117117
logger.WriteLineError($"The provided {nameof(options.WasmMainJs)} \"{options.WasmMainJs}\" does NOT exist. It MUST be provided.");
118118
return false;
@@ -121,6 +121,11 @@ private static bool Validate(CommandLineOptions options, ILogger logger)
121121
{
122122
logger.WriteLineError($"The provided {nameof(options.AOTCompilerPath)} \"{ options.AOTCompilerPath }\" does NOT exist. It MUST be provided.");
123123
}
124+
else if (runtimeMoniker == RuntimeMoniker.Wasm && options.AOTCompilerMode == MonoAotCompilerMode.wasm && (options.RuntimeSrcDir == null || options.RuntimeSrcDir.IsNotNullButDoesNotExist()))
125+
{
126+
logger.WriteLineError($"The provided {nameof(options.RuntimeSrcDir)} \"{options.RuntimeSrcDir}\" does NOT exist. It MUST be provided.");
127+
return false;
128+
}
124129
}
125130

126131
foreach (string exporter in options.Exporters)
@@ -414,11 +419,15 @@ private static Job CreateJobForGivenRuntime(Job baseJob, string runtimeId, Comma
414419

415420
private static Job MakeWasmJob(Job baseJob, CommandLineOptions options, TimeSpan? timeOut, string msBuildMoniker)
416421
{
422+
bool wasmAot = options.AOTCompilerMode == MonoAotCompilerMode.wasm;
423+
417424
var wasmRuntime = new WasmRuntime(
418425
mainJs: options.WasmMainJs,
419426
msBuildMoniker: msBuildMoniker,
420427
javaScriptEngine: options.WasmJavascriptEngine?.FullName ?? "v8",
421-
javaScriptEngineArguments: options.WasmJavaScriptEngineArguments);
428+
javaScriptEngineArguments: options.WasmJavaScriptEngineArguments,
429+
aot: wasmAot,
430+
runtimeSrcDir: options.RuntimeSrcDir);
422431

423432
var toolChain = WasmToolChain.From(new NetCoreAppSettings(
424433
targetFrameworkMoniker: wasmRuntime.MsBuildMoniker,
@@ -427,7 +436,8 @@ private static Job MakeWasmJob(Job baseJob, CommandLineOptions options, TimeSpan
427436
customDotNetCliPath: options.CliPath?.FullName,
428437
packagesPath: options.RestorePath?.FullName,
429438
timeout: timeOut ?? NetCoreAppSettings.DefaultBuildTimeout,
430-
customRuntimePack: options.CustomRuntimePack));
439+
customRuntimePack: options.CustomRuntimePack,
440+
aotCompilerMode: options.AOTCompilerMode));
431441

432442
return baseJob.WithRuntime(wasmRuntime).WithToolchain(toolChain);
433443
}

src/BenchmarkDotNet/Environments/Runtimes/WasmRuntime.cs

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
using System.IO;
44
using BenchmarkDotNet.Extensions;
55
using BenchmarkDotNet.Jobs;
6+
using BenchmarkDotNet.Toolchains.MonoWasm;
67

78
namespace BenchmarkDotNet.Environments
89
{
@@ -17,6 +18,10 @@ public class WasmRuntime : Runtime, IEquatable<WasmRuntime>
1718

1819
public string JavaScriptEngineArguments { get; }
1920

21+
public bool Aot { get; }
22+
23+
public DirectoryInfo RuntimeSrcDir { get; }
24+
2025
/// <summary>
2126
/// creates new instance of WasmRuntime
2227
/// </summary>
@@ -26,18 +31,20 @@ public class WasmRuntime : Runtime, IEquatable<WasmRuntime>
2631
/// <param name="msBuildMoniker">moniker, default: "net5.0"</param>
2732
/// <param name="displayName">default: "Wasm"</param>
2833
/// <remarks>path to mainJs MUST be provided</remarks>
29-
public WasmRuntime(FileInfo mainJs, string msBuildMoniker = "net5.0", string displayName = "Wasm", string javaScriptEngine = "v8", string javaScriptEngineArguments = "--expose_wasm") : base(RuntimeMoniker.Wasm, msBuildMoniker, displayName)
34+
public WasmRuntime(FileInfo mainJs, string msBuildMoniker = "net5.0", string displayName = "Wasm", string javaScriptEngine = "v8", string javaScriptEngineArguments = "--expose_wasm", bool aot = false, DirectoryInfo runtimeSrcDir = null) : base(RuntimeMoniker.Wasm, msBuildMoniker, displayName)
3035
{
31-
if (mainJs == null)
36+
if (!aot && mainJs == null)
3237
throw new ArgumentNullException(paramName: nameof(mainJs));
33-
if (mainJs.IsNotNullButDoesNotExist())
38+
if (!aot && mainJs.IsNotNullButDoesNotExist())
3439
throw new FileNotFoundException($"Provided {nameof(mainJs)} file: \"{mainJs.FullName}\" doest NOT exist");
3540
if (!string.IsNullOrEmpty(javaScriptEngine) && javaScriptEngine != "v8" && !File.Exists(javaScriptEngine))
3641
throw new FileNotFoundException($"Provided {nameof(javaScriptEngine)} file: \"{javaScriptEngine}\" doest NOT exist");
3742

3843
MainJs = mainJs;
3944
JavaScriptEngine = javaScriptEngine;
4045
JavaScriptEngineArguments = javaScriptEngineArguments;
46+
Aot = aot;
47+
RuntimeSrcDir = runtimeSrcDir;
4148
}
4249

4350
// this ctor exists only for the purpose of having .Default property that returns something consumable by RuntimeInformation.GetCurrentRuntime()
@@ -52,9 +59,9 @@ public override bool Equals(object obj)
5259
=> obj is WasmRuntime other && Equals(other);
5360

5461
public bool Equals(WasmRuntime other)
55-
=> other != null && base.Equals(other) && other.MainJs == MainJs && other.JavaScriptEngine == JavaScriptEngine && other.JavaScriptEngineArguments == JavaScriptEngineArguments;
62+
=> other != null && base.Equals(other) && other.MainJs == MainJs && other.JavaScriptEngine == JavaScriptEngine && other.JavaScriptEngineArguments == JavaScriptEngineArguments && other.Aot == Aot && other.RuntimeSrcDir == RuntimeSrcDir;
5663

5764
public override int GetHashCode()
58-
=> base.GetHashCode() ^ MainJs.GetHashCode() ^ (JavaScriptEngine?.GetHashCode() ?? 0) ^ (JavaScriptEngineArguments?.GetHashCode() ?? 0);
65+
=> base.GetHashCode() ^ MainJs.GetHashCode() ^ (JavaScriptEngine?.GetHashCode() ?? 0) ^ (JavaScriptEngineArguments?.GetHashCode() ?? 0 ^ Aot.GetHashCode() ^ (RuntimeSrcDir?.GetHashCode() ?? 0));
5966
}
6067
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
<Project Sdk="$SDKNAME$" DefaultTargets="publish">
2+
<PropertyGroup>
3+
<OutputType>Exe</OutputType>
4+
<OutputPath>bin</OutputPath>
5+
<RuntimeSrcDir>$RUNTIMESRCDIR$</RuntimeSrcDir>
6+
<RuntimeConfig>Release</RuntimeConfig>
7+
<EnableDefaultCompileItems>false</EnableDefaultCompileItems>
8+
<TargetFramework>$TFM$</TargetFramework>
9+
<AppDir>$(MSBuildThisFileDirectory)\bin\$TFM$\browser-wasm\publish</AppDir>
10+
<AssemblyName>$PROGRAMNAME$</AssemblyName>
11+
<RuntimeIdentifier>browser-wasm</RuntimeIdentifier>
12+
<PublishTrimmed>true</PublishTrimmed>
13+
<RunAOTCompilation>true</RunAOTCompilation>
14+
<WasmMainJSPath>$(RuntimeSrcDir)\src\mono\wasm\runtime-test.js</WasmMainJSPath>
15+
<WasmGenerateRunV8Script>true</WasmGenerateRunV8Script>
16+
$COPIEDSETTINGS$
17+
</PropertyGroup>
18+
19+
<Import Project="$(RuntimeSrcDir)/src/mono/wasm/build/WasmApp.LocalBuild.props" />
20+
<Import Project="$(RuntimeSrcDir)/src/mono/wasm/build/WasmApp.LocalBuild.targets" />
21+
22+
23+
<ItemGroup>
24+
<WasmAssembliesToBundle Include="$(AppDir)/*.dll" />
25+
</ItemGroup>
26+
27+
28+
<ItemGroup>
29+
<Compile Include="$CODEFILENAME$" Exclude="bin\**;obj\**;**\*.xproj;packages\**" />
30+
</ItemGroup>
31+
32+
<ItemGroup>
33+
<ProjectReference Include="$CSPROJPATH$" />
34+
</ItemGroup>
35+
</Project>

src/BenchmarkDotNet/Toolchains/MonoAotLLVM/MonoAotCompilerMode.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
public enum MonoAotCompilerMode
44
{
55
mini = 0, // default
6-
llvm
6+
llvm,
7+
wasm
78
}
89
}

src/BenchmarkDotNet/Toolchains/MonoWasm/WasmBuilder.cs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,11 @@ public BuildResult Build(GenerateResult generateResult, BuildPartition buildPart
2626
{
2727
BuildResult buildResult = dotNetCliBuilder.Build(generateResult, buildPartition, logger);
2828

29-
if (buildResult.IsBuildSuccess)
29+
WasmRuntime runtime = (WasmRuntime)buildPartition.Runtime;
30+
31+
if (buildResult.IsBuildSuccess && !runtime.Aot)
3032
{
31-
BuildApp(buildPartition.ProgramName, generateResult.ArtifactsPaths.BuildArtifactsDirectoryPath, (WasmRuntime)buildPartition.Runtime);
33+
BuildApp(buildPartition.ProgramName, generateResult.ArtifactsPaths.BuildArtifactsDirectoryPath, runtime);
3234
}
3335

3436
return buildResult;

src/BenchmarkDotNet/Toolchains/MonoWasm/WasmGenerator.cs

Lines changed: 53 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
using System.IO;
22
using System.Text;
3+
using BenchmarkDotNet.Environments;
34
using BenchmarkDotNet.Extensions;
45
using BenchmarkDotNet.Helpers;
56
using BenchmarkDotNet.Loggers;
@@ -11,14 +12,55 @@ namespace BenchmarkDotNet.Toolchains.MonoWasm
1112
public class WasmGenerator : CsProjGenerator
1213
{
1314
private readonly string CustomRuntimePack;
15+
private readonly bool Aot;
1416

15-
public WasmGenerator(string targetFrameworkMoniker, string cliPath, string packagesPath, string customRuntimePack)
17+
public WasmGenerator(string targetFrameworkMoniker, string cliPath, string packagesPath, string customRuntimePack, bool aot)
1618
: base(targetFrameworkMoniker, cliPath, packagesPath, runtimeFrameworkVersion: null)
1719
{
20+
Aot = aot;
1821
CustomRuntimePack = customRuntimePack;
1922
}
2023

2124
protected override void GenerateProject(BuildPartition buildPartition, ArtifactsPaths artifactsPaths, ILogger logger)
25+
{
26+
if (((WasmRuntime)buildPartition.Runtime).Aot)
27+
{
28+
GenerateProjectAot(buildPartition, artifactsPaths, logger);
29+
}
30+
else
31+
{
32+
GenerateProjectInterpreter(buildPartition, artifactsPaths, logger);
33+
}
34+
}
35+
36+
protected void GenerateProjectAot(BuildPartition buildPartition, ArtifactsPaths artifactsPaths, ILogger logger)
37+
{
38+
BenchmarkCase benchmark = buildPartition.RepresentativeBenchmarkCase;
39+
var projectFile = GetProjectFilePath(benchmark.Descriptor.Type, logger);
40+
41+
WasmRuntime runtime = (WasmRuntime)buildPartition.Runtime;
42+
43+
using (var file = new StreamReader(File.OpenRead(projectFile.FullName)))
44+
{
45+
var (customProperties, sdkName) = GetSettingsThatNeedsToBeCopied(file, projectFile);
46+
47+
string content = new StringBuilder(ResourceHelper.LoadTemplate("WasmAotCsProj.txt"))
48+
.Replace("$PLATFORM$", buildPartition.Platform.ToConfig())
49+
.Replace("$CODEFILENAME$", Path.GetFileName(artifactsPaths.ProgramCodePath))
50+
.Replace("$CSPROJPATH$", projectFile.FullName)
51+
.Replace("$TFM$", TargetFrameworkMoniker)
52+
.Replace("$PROGRAMNAME$", artifactsPaths.ProgramName)
53+
.Replace("$RUNTIMESRCDIR$", runtime.RuntimeSrcDir.ToString())
54+
.Replace("$COPIEDSETTINGS$", customProperties)
55+
.Replace("$CONFIGURATIONNAME$", buildPartition.BuildConfiguration)
56+
.Replace("$SDKNAME$", sdkName)
57+
.ToString();
58+
59+
File.WriteAllText(artifactsPaths.ProjectFilePath, content);
60+
}
61+
}
62+
63+
protected void GenerateProjectInterpreter(BuildPartition buildPartition, ArtifactsPaths artifactsPaths, ILogger logger)
2264
{
2365
BenchmarkCase benchmark = buildPartition.RepresentativeBenchmarkCase;
2466
var projectFile = GetProjectFilePath(benchmark.Descriptor.Type, logger);
@@ -46,6 +88,15 @@ protected override void GenerateProject(BuildPartition buildPartition, Artifacts
4688
protected override string GetExecutablePath(string binariesDirectoryPath, string programName) => Path.Combine(binariesDirectoryPath, "runtime.js");
4789

4890
protected override string GetBinariesDirectoryPath(string buildArtifactsDirectoryPath, string configuration)
49-
=> Path.Combine(buildArtifactsDirectoryPath, "bin", TargetFrameworkMoniker, "browser-wasm", "publish", "output");
91+
{
92+
if (Aot)
93+
{
94+
return Path.Combine(buildArtifactsDirectoryPath, "bin", TargetFrameworkMoniker, "browser-wasm", "AppBundle");
95+
}
96+
else
97+
{
98+
return Path.Combine(buildArtifactsDirectoryPath, "bin", TargetFrameworkMoniker, "browser-wasm", "publish", "output");
99+
}
100+
}
50101
}
51102
}

src/BenchmarkDotNet/Toolchains/MonoWasm/WasmToolChain.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,8 @@ public static IToolchain From(NetCoreAppSettings netCoreAppSettings)
4040
new WasmGenerator(netCoreAppSettings.TargetFrameworkMoniker,
4141
netCoreAppSettings.CustomDotNetCliPath,
4242
netCoreAppSettings.PackagesPath,
43-
netCoreAppSettings.CustomRuntimePack),
43+
netCoreAppSettings.CustomRuntimePack,
44+
netCoreAppSettings.AOTCompilerMode == MonoAotLLVM.MonoAotCompilerMode.wasm),
4445
new WasmBuilder(netCoreAppSettings.TargetFrameworkMoniker,
4546
netCoreAppSettings.CustomDotNetCliPath,
4647
netCoreAppSettings.Timeout),

0 commit comments

Comments
 (0)