diff --git a/BenchmarkDotNet.sln.DotSettings b/BenchmarkDotNet.sln.DotSettings
index d2f6784607..fe4359db34 100644
--- a/BenchmarkDotNet.sln.DotSettings
+++ b/BenchmarkDotNet.sln.DotSettings
@@ -195,6 +195,7 @@
True
True
True
+ True
True
True
True
diff --git a/samples/BenchmarkDotNet.Samples/nuget.config b/samples/BenchmarkDotNet.Samples/nuget.config
deleted file mode 100644
index df7045f7e2..0000000000
--- a/samples/BenchmarkDotNet.Samples/nuget.config
+++ /dev/null
@@ -1,5 +0,0 @@
-
-
-
-
-
diff --git a/src/BenchmarkDotNet/ConsoleArguments/CommandLineOptions.cs b/src/BenchmarkDotNet/ConsoleArguments/CommandLineOptions.cs
index ce1b3200b4..d3c50b4c93 100644
--- a/src/BenchmarkDotNet/ConsoleArguments/CommandLineOptions.cs
+++ b/src/BenchmarkDotNet/ConsoleArguments/CommandLineOptions.cs
@@ -168,13 +168,13 @@ public class CommandLineOptions
[Option("envVars", Required = false, HelpText = "Colon separated environment variables (key:value)")]
public IEnumerable EnvironmentVariables { get; set; }
- [Option("wasmJavascriptEnginePath", Required = false, Default = "v8", HelpText = "Full path to a java script engine used to run the benchmarks, if using the WASM runtime.")]
- public string WasmJavascriptEnginePath { get; set; }
+ [Option("wasmEngine", Required = false, HelpText = "Full path to a java script engine used to run the benchmarks, used by WASM toolchain.")]
+ public FileInfo WasmJavascriptEngine { get; set; }
- [Option("wasmMainJS", Required = false, HelpText = "Path to the main.js file used for wasm apps.")]
- public string WasmMainJS { get; set; }
+ [Option("wasmMainJS", Required = false, HelpText = "Path to the main.js file used by WASM toolchain. Mandatory when using \"--runtimes wasm\"")]
+ public FileInfo WasmMainJs { get; set; }
- [Option("wasmJavaScriptEngineArguments", Required = false, Default = "--expose_wasm", HelpText = "Arguments for the javascript engine used by wasm.")]
+ [Option("wasmArgs", Required = false, Default = "--expose_wasm", HelpText = "Arguments for the javascript engine used by WASM toolchain.")]
public string WasmJavaScriptEngineArguments { get; set; }
internal bool UserProvidedFilters => Filters.Any() || AttributeNames.Any() || AllCategories.Any() || AnyCategories.Any();
diff --git a/src/BenchmarkDotNet/ConsoleArguments/ConfigParser.cs b/src/BenchmarkDotNet/ConsoleArguments/ConfigParser.cs
index 506b1e644d..68a9a84294 100644
--- a/src/BenchmarkDotNet/ConsoleArguments/ConfigParser.cs
+++ b/src/BenchmarkDotNet/ConsoleArguments/ConfigParser.cs
@@ -105,11 +105,18 @@ private static bool Validate(CommandLineOptions options, ILogger logger)
}
foreach (string runtime in options.Runtimes)
- if (!Enum.TryParse(runtime.Replace(".", string.Empty), ignoreCase: true, out _))
+ {
+ if (!Enum.TryParse(runtime.Replace(".", string.Empty), ignoreCase: true, out var parsed))
{
logger.WriteLineError($"The provided runtime \"{runtime}\" is invalid. Available options are: {string.Join(", ", Enum.GetNames(typeof(RuntimeMoniker)).Select(name => name.ToLower()))}.");
return false;
}
+ else if (parsed == RuntimeMoniker.Wasm && (options.WasmMainJs == null || options.WasmMainJs.IsNotNullButDoesNotExist()))
+ {
+ logger.WriteLineError($"The provided {nameof(options.WasmMainJs)} \"{options.WasmMainJs}\" does NOT exist. It MUST be provided.");
+ return false;
+ }
+ }
foreach (string exporter in options.Exporters)
if (!AvailableExporters.ContainsKey(exporter))
@@ -137,6 +144,12 @@ private static bool Validate(CommandLineOptions options, ILogger logger)
return false;
}
+ if (options.WasmJavascriptEngine.IsNotNullButDoesNotExist())
+ {
+ logger.WriteLineError($"The provided {nameof(options.WasmJavascriptEngine)} \"{options.WasmJavascriptEngine}\" does NOT exist.");
+ return false;
+ }
+
if (options.CoreRtPath.IsNotNullButDoesNotExist())
{
logger.WriteLineError($"The provided {nameof(options.CoreRtPath)} \"{options.CoreRtPath}\" does NOT exist.");
@@ -361,18 +374,19 @@ private static Job CreateJobForGivenRuntime(Job baseJob, string runtimeId, Comma
return baseJob.WithRuntime(runtime).WithToolchain(builder.ToToolchain());
case RuntimeMoniker.Wasm:
- var wasmRuntime = runtimeMoniker.GetRuntime();
-
- WasmSettings wasmSettings = new WasmSettings(wasmMainJS: options.WasmMainJS,
- wasmJavaScriptEngine: options.WasmJavascriptEnginePath,
- wasmjavaScriptEngineArguments: options.WasmJavaScriptEngineArguments);
-
- IToolchain toolChain = new WasmToolChain(name: "Wasm",
- targetFrameworkMoniker: wasmRuntime.MsBuildMoniker,
- cliPath: options.CliPath.FullName,
- packagesPath: options.RestorePath?.FullName,
- wasmSettings: wasmSettings,
- timeout: timeOut ?? NetCoreAppSettings.DefaultBuildTimeout);
+ var wasmRuntime = new WasmRuntime(
+ mainJs: options.WasmMainJs,
+ msBuildMoniker: "net5.0",
+ javaScriptEngine: options.WasmJavascriptEngine?.FullName ?? "v8",
+ javaScriptEngineArguments: options.WasmJavaScriptEngineArguments);
+
+ var toolChain = WasmToolChain.From(new NetCoreAppSettings(
+ targetFrameworkMoniker: wasmRuntime.MsBuildMoniker,
+ runtimeFrameworkVersion: null,
+ name: wasmRuntime.Name,
+ customDotNetCliPath: options.CliPath?.FullName,
+ packagesPath: options.RestorePath?.FullName,
+ timeout: timeOut ?? NetCoreAppSettings.DefaultBuildTimeout));
return baseJob.WithRuntime(wasmRuntime).WithToolchain(toolChain);
default:
diff --git a/src/BenchmarkDotNet/Environments/Runtimes/WasmRuntime.cs b/src/BenchmarkDotNet/Environments/Runtimes/WasmRuntime.cs
index 43401e0220..f906726da9 100644
--- a/src/BenchmarkDotNet/Environments/Runtimes/WasmRuntime.cs
+++ b/src/BenchmarkDotNet/Environments/Runtimes/WasmRuntime.cs
@@ -1,22 +1,60 @@
using System;
+using System.ComponentModel;
+using System.IO;
+using BenchmarkDotNet.Extensions;
using BenchmarkDotNet.Jobs;
namespace BenchmarkDotNet.Environments
{
public class WasmRuntime : Runtime, IEquatable
{
- public static readonly WasmRuntime Default = new WasmRuntime("Wasm");
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ internal static readonly WasmRuntime Default = new WasmRuntime();
- public WasmRuntime(string name) : base(RuntimeMoniker.Wasm, "net5.0", name)
+ public FileInfo MainJs { get; }
+
+ public string JavaScriptEngine { get; }
+
+ public string JavaScriptEngineArguments { get; }
+
+ ///
+ /// creates new instance of WasmRuntime
+ ///
+ /// MANDATORY path to the main.js file.
+ /// Full path to a java script engine used to run the benchmarks. "v8" by default
+ /// Arguments for the javascript engine. "--expose_wasm" by default
+ /// moniker, default: "net5.0"
+ /// default: "WASM"
+ /// path to mainJs MUST be provided
+ public WasmRuntime(FileInfo mainJs, string msBuildMoniker = "net5.0", string displayName = "WASM", string javaScriptEngine = "v8", string javaScriptEngineArguments = "--expose_wasm") : base(RuntimeMoniker.Wasm, msBuildMoniker, displayName)
{
+ if (mainJs == null)
+ throw new ArgumentNullException(paramName: nameof(mainJs));
+ if (mainJs.IsNotNullButDoesNotExist())
+ throw new FileNotFoundException($"Provided {nameof(mainJs)} file: \"{mainJs.FullName}\" doest NOT exist");
+ if (!string.IsNullOrEmpty(javaScriptEngine) && javaScriptEngine != "v8" && !File.Exists(javaScriptEngine))
+ throw new FileNotFoundException($"Provided {nameof(javaScriptEngine)} file: \"{javaScriptEngine}\" doest NOT exist");
+
+ MainJs = mainJs;
+ JavaScriptEngine = javaScriptEngine;
+ JavaScriptEngineArguments = javaScriptEngineArguments;
}
-
- public WasmRuntime(string name, string msBuildMoniker) : base(RuntimeMoniker.Wasm, msBuildMoniker, name)
+
+ // this ctor exists only for the purpose of having .Default property that returns something consumable by RuntimeInformation.GetCurrentRuntime()
+ private WasmRuntime(string msBuildMoniker = "net5.0", string displayName = "WASM", string javaScriptEngine = "v8", string javaScriptEngineArguments = "--expose_wasm") : base(RuntimeMoniker.Wasm, msBuildMoniker, displayName)
{
+ MainJs = new FileInfo("fake");
+ JavaScriptEngine = javaScriptEngine;
+ JavaScriptEngineArguments = javaScriptEngineArguments;
}
- public override bool Equals(object obj) => obj is WasmRuntime other && Equals(other);
+ public override bool Equals(object obj)
+ => obj is WasmRuntime other && Equals(other);
+
+ public bool Equals(WasmRuntime other)
+ => other != null && base.Equals(other) && other.MainJs == MainJs && other.JavaScriptEngine == JavaScriptEngine && other.JavaScriptEngineArguments == JavaScriptEngineArguments;
- public bool Equals(WasmRuntime other) => base.Equals(other);
+ public override int GetHashCode()
+ => base.GetHashCode() ^ MainJs.GetHashCode() ^ (JavaScriptEngine?.GetHashCode() ?? 0) ^ (JavaScriptEngineArguments?.GetHashCode() ?? 0);
}
}
diff --git a/src/BenchmarkDotNet/Extensions/RuntimeMonikerExtensions.cs b/src/BenchmarkDotNet/Extensions/RuntimeMonikerExtensions.cs
index 81937ea8e7..2916b6ef3a 100644
--- a/src/BenchmarkDotNet/Extensions/RuntimeMonikerExtensions.cs
+++ b/src/BenchmarkDotNet/Extensions/RuntimeMonikerExtensions.cs
@@ -48,8 +48,6 @@ internal static Runtime GetRuntime(this RuntimeMoniker runtimeMoniker)
return CoreRtRuntime.CoreRt31;
case RuntimeMoniker.CoreRt50:
return CoreRtRuntime.CoreRt50;
- case RuntimeMoniker.Wasm:
- return WasmRuntime.Default;
default:
throw new ArgumentOutOfRangeException(nameof(runtimeMoniker), runtimeMoniker, "Runtime Moniker not supported");
}
diff --git a/src/BenchmarkDotNet/Toolchains/DotNetCli/DotNetCliBuilder.cs b/src/BenchmarkDotNet/Toolchains/DotNetCli/DotNetCliBuilder.cs
index 465955bd34..3af73e4e81 100644
--- a/src/BenchmarkDotNet/Toolchains/DotNetCli/DotNetCliBuilder.cs
+++ b/src/BenchmarkDotNet/Toolchains/DotNetCli/DotNetCliBuilder.cs
@@ -24,7 +24,7 @@ public DotNetCliBuilder(string targetFrameworkMoniker, string customDotNetCliPat
Timeout = timeout ?? NetCoreAppSettings.DefaultBuildTimeout;
}
- public virtual BuildResult Build(GenerateResult generateResult, BuildPartition buildPartition, ILogger logger)
+ public BuildResult Build(GenerateResult generateResult, BuildPartition buildPartition, ILogger logger)
=> new DotNetCliCommand(
CustomDotNetCliPath,
string.Empty,
diff --git a/src/BenchmarkDotNet/Toolchains/Executor.cs b/src/BenchmarkDotNet/Toolchains/Executor.cs
index 5aaa89ef8c..34d2afc6c8 100644
--- a/src/BenchmarkDotNet/Toolchains/Executor.cs
+++ b/src/BenchmarkDotNet/Toolchains/Executor.cs
@@ -25,6 +25,7 @@ public class Executor : IExecutor
public ExecuteResult Execute(ExecuteParameters executeParameters)
{
string exePath = executeParameters.BuildResult.ArtifactsPaths.ExecutablePath;
+ string programName = executeParameters.BuildResult.ArtifactsPaths.ProgramName;
string args = executeParameters.BenchmarkId.ToArguments();
if (!File.Exists(exePath))
@@ -32,14 +33,14 @@ public ExecuteResult Execute(ExecuteParameters executeParameters)
return new ExecuteResult(false, -1, default, Array.Empty(), Array.Empty());
}
- return Execute(executeParameters.BenchmarkCase, executeParameters.BenchmarkId, executeParameters.Logger, exePath, null, args, executeParameters.Diagnoser, executeParameters.Resolver);
+ return Execute(executeParameters.BenchmarkCase, executeParameters.BenchmarkId, executeParameters.Logger, exePath, null, args, executeParameters.Diagnoser, executeParameters.Resolver, programName);
}
- private ExecuteResult Execute(BenchmarkCase benchmarkCase, BenchmarkId benchmarkId, ILogger logger, string exePath, string workingDirectory, string args, IDiagnoser diagnoser, IResolver resolver)
+ private ExecuteResult Execute(BenchmarkCase benchmarkCase, BenchmarkId benchmarkId, ILogger logger, string exePath, string workingDirectory, string args, IDiagnoser diagnoser, IResolver resolver, string programName)
{
try
{
- using (var process = new Process { StartInfo = CreateStartInfo(benchmarkCase, exePath, args, workingDirectory, resolver) })
+ using (var process = new Process { StartInfo = CreateStartInfo(benchmarkCase, exePath, args, workingDirectory, resolver, programName) })
using (new ConsoleExitHandler(process, logger))
{
var loggerWithDiagnoser = new SynchronousProcessOutputLoggerWithDiagnoser(logger, process, diagnoser, benchmarkCase, benchmarkId);
@@ -82,7 +83,7 @@ private ExecuteResult Execute(Process process, BenchmarkCase benchmarkCase, Sync
return new ExecuteResult(true, process.ExitCode, process.Id, Array.Empty(), Array.Empty());
}
- private ProcessStartInfo CreateStartInfo(BenchmarkCase benchmarkCase, string exePath, string args, string workingDirectory, IResolver resolver)
+ private ProcessStartInfo CreateStartInfo(BenchmarkCase benchmarkCase, string exePath, string args, string workingDirectory, IResolver resolver, string programName)
{
var start = new ProcessStartInfo
{
@@ -113,6 +114,10 @@ private ProcessStartInfo CreateStartInfo(BenchmarkCase benchmarkCase, string exe
start.FileName = mono.CustomPath ?? "mono";
start.Arguments = GetMonoArguments(benchmarkCase.Job, exePath, args, resolver);
break;
+ case WasmRuntime wasm:
+ start.FileName = wasm.JavaScriptEngine;
+ start.Arguments = $"{wasm.JavaScriptEngineArguments} runtime.js -- --run {programName}.dll {args} ";
+ break;
default:
throw new NotSupportedException("Runtime = " + runtime);
}
diff --git a/src/BenchmarkDotNet/Toolchains/MonoWasm/WasmAppBuilder.cs b/src/BenchmarkDotNet/Toolchains/MonoWasm/WasmAppBuilder.cs
deleted file mode 100644
index 707b8a5bc9..0000000000
--- a/src/BenchmarkDotNet/Toolchains/MonoWasm/WasmAppBuilder.cs
+++ /dev/null
@@ -1,73 +0,0 @@
-// 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.Collections.Immutable;
-using System.Diagnostics;
-using System.IO;
-using System.Linq;
-using System.Text;
-using System.Reflection;
-using BenchmarkDotNet.Toolchains.MonoWasm;
-
-public class WasmAppBuilder
-{
- private readonly WasmSettings WasmSettings;
- private readonly string TargetFrameworkMoniker;
-
- public WasmAppBuilder(WasmSettings wasmSettings, string targetFrameworkMoniker)
- {
- WasmSettings = wasmSettings;
- TargetFrameworkMoniker = targetFrameworkMoniker;
- }
-
- public bool BuildApp (string programName, string projectRoot)
- {
- string[] assemblies;
- string appDir = Path.Combine(projectRoot, $"bin", TargetFrameworkMoniker, "browser-wasm", "publish");
- string outputDir = Path.Combine(appDir, "output");
-
- string mainAssemblyPath = Path.Combine(appDir, $"{programName}.dll");
-
- if (!File.Exists(mainAssemblyPath))
- throw new ArgumentException($"File MainAssembly='{mainAssemblyPath}' doesn't exist.");
- if (!File.Exists(WasmSettings.WasmMainJS))
- throw new ArgumentException($"File MainJS='{WasmSettings.WasmMainJS}' doesn't exist.");
-
- var paths = new List();
- assemblies = Directory.GetFiles(appDir, "*.dll");
-
- // Create app
- Directory.CreateDirectory(outputDir);
- Directory.CreateDirectory(Path.Combine(outputDir, "managed"));
- foreach (var assembly in assemblies)
- File.Copy(assembly, Path.Combine(outputDir, "managed", Path.GetFileName(assembly)), true);
-
- foreach (var f in new string[] { "dotnet.wasm", "dotnet.js" })
- File.Copy(Path.Combine(appDir, f), Path.Combine(outputDir, f), true);
-
- File.Copy(WasmSettings.WasmMainJS, Path.Combine(outputDir, "runtime.js"), true);
-
- using (var sw = File.CreateText(Path.Combine(outputDir, "mono-config.js")))
- {
- sw.WriteLine("config = {");
- sw.WriteLine("\tvfs_prefix: \"managed\",");
- sw.WriteLine("\tdeploy_prefix: \"managed\",");
- sw.WriteLine("\tenable_debugging: 0,");
- sw.WriteLine("\tassembly_list: [");
- foreach (var assembly in assemblies)
- {
- sw.Write("\t\t\"" + Path.GetFileName(assembly) + "\"");
- sw.WriteLine(",");
- }
- sw.WriteLine ("\t],");
- sw.WriteLine("\tfiles_to_map: [],");
-
- sw.WriteLine ("}");
- }
-
- return true;
- }
-}
diff --git a/src/BenchmarkDotNet/Toolchains/MonoWasm/WasmBuilder.cs b/src/BenchmarkDotNet/Toolchains/MonoWasm/WasmBuilder.cs
index 5e17b9de0a..bd28ba7601 100644
--- a/src/BenchmarkDotNet/Toolchains/MonoWasm/WasmBuilder.cs
+++ b/src/BenchmarkDotNet/Toolchains/MonoWasm/WasmBuilder.cs
@@ -6,25 +6,74 @@
using BenchmarkDotNet.Toolchains.Results;
using BenchmarkDotNet.Toolchains.DotNetCli;
using System.IO;
+using BenchmarkDotNet.Environments;
namespace BenchmarkDotNet.Toolchains.MonoWasm
{
- public class WasmBuilder : DotNetCliBuilder
+ public class WasmBuilder : IBuilder
{
- private WasmAppBuilder WasmAppBuilder;
+ private readonly DotNetCliBuilder dotNetCliBuilder;
+ private readonly string targetFrameworkMoniker;
- public WasmBuilder(string targetFrameworkMoniker, WasmSettings wasmSettings, string customDotNetCliPath = null, TimeSpan? timeout = null)
- :base (targetFrameworkMoniker, customDotNetCliPath, timeout)
+ public WasmBuilder(string targetFrameworkMoniker, string customDotNetCliPath = null, TimeSpan? timeout = null)
{
- WasmAppBuilder = new WasmAppBuilder(wasmSettings, targetFrameworkMoniker);
+ this.targetFrameworkMoniker = targetFrameworkMoniker;
+
+ dotNetCliBuilder = new DotNetCliBuilder(targetFrameworkMoniker, customDotNetCliPath, timeout);
}
- public override BuildResult Build(GenerateResult generateResult, BuildPartition buildPartition, ILogger logger)
+ public BuildResult Build(GenerateResult generateResult, BuildPartition buildPartition, ILogger logger)
{
- BuildResult buildResult = base.Build(generateResult, buildPartition, logger);
- WasmAppBuilder.BuildApp(buildPartition.ProgramName, generateResult.ArtifactsPaths.BuildArtifactsDirectoryPath);
+ BuildResult buildResult = dotNetCliBuilder.Build(generateResult, buildPartition, logger);
+
+ if (buildResult.IsBuildSuccess)
+ {
+ BuildApp(buildPartition.ProgramName, generateResult.ArtifactsPaths.BuildArtifactsDirectoryPath, (WasmRuntime)buildPartition.Runtime);
+ }
return buildResult;
}
+
+ private void BuildApp(string programName, string projectRoot, WasmRuntime runtime)
+ {
+ string appDir = Path.Combine(projectRoot, $"bin", targetFrameworkMoniker, "browser-wasm", "publish");
+ string outputDir = Path.Combine(appDir, "output");
+
+ string mainAssemblyPath = Path.Combine(appDir, $"{programName}.dll");
+
+ if (!File.Exists(mainAssemblyPath))
+ throw new ArgumentException($"File MainAssembly='{mainAssemblyPath}' doesn't exist.");
+
+ var assemblies = Directory.GetFiles(appDir, "*.dll");
+
+ // Create app
+ Directory.CreateDirectory(outputDir);
+ Directory.CreateDirectory(Path.Combine(outputDir, "managed"));
+ foreach (var assembly in assemblies)
+ File.Copy(assembly, Path.Combine(outputDir, "managed", Path.GetFileName(assembly)), true);
+
+ foreach (var f in new string[] { "dotnet.wasm", "dotnet.js" })
+ File.Copy(Path.Combine(appDir, f), Path.Combine(outputDir, f), true);
+
+ File.Copy(runtime.MainJs.FullName, Path.Combine(outputDir, "runtime.js"), true);
+
+ using (var sw = File.CreateText(Path.Combine(outputDir, "mono-config.js")))
+ {
+ sw.WriteLine("config = {");
+ sw.WriteLine("\tvfs_prefix: \"managed\",");
+ sw.WriteLine("\tdeploy_prefix: \"managed\",");
+ sw.WriteLine("\tenable_debugging: 0,");
+ sw.WriteLine("\tassembly_list: [");
+ foreach (var assembly in assemblies)
+ {
+ sw.Write("\t\t\"" + Path.GetFileName(assembly) + "\"");
+ sw.WriteLine(",");
+ }
+ sw.WriteLine ("\t],");
+ sw.WriteLine("\tfiles_to_map: [],");
+
+ sw.WriteLine ("}");
+ }
+ }
}
}
diff --git a/src/BenchmarkDotNet/Toolchains/MonoWasm/WasmExecutor.cs b/src/BenchmarkDotNet/Toolchains/MonoWasm/WasmExecutor.cs
deleted file mode 100644
index ea9e941f8e..0000000000
--- a/src/BenchmarkDotNet/Toolchains/MonoWasm/WasmExecutor.cs
+++ /dev/null
@@ -1,166 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Diagnostics;
-using System.IO;
-using System.Linq;
-using BenchmarkDotNet.Characteristics;
-using BenchmarkDotNet.Diagnosers;
-using BenchmarkDotNet.Engines;
-using BenchmarkDotNet.Extensions;
-using BenchmarkDotNet.Helpers;
-using BenchmarkDotNet.Jobs;
-using BenchmarkDotNet.Loggers;
-using BenchmarkDotNet.Running;
-using BenchmarkDotNet.Toolchains.Parameters;
-using BenchmarkDotNet.Toolchains.Results;
-using JetBrains.Annotations;
-
-namespace BenchmarkDotNet.Toolchains.MonoWasm
-{
- [PublicAPI]
- public class WasmExecutor : IExecutor
- {
- public WasmExecutor(string customDotNetCliPath, string javaScriptEngine, string javaScriptEngineArguments)
- {
- CustomDotNetCliPath = customDotNetCliPath;
- JavaScriptEngine = javaScriptEngine;
- JavaScriptEngineArguments = javaScriptEngineArguments;
- RuntimeJavaScriptName = "runtime.js";
- ExtraRuntimeArguments = "";
- }
-
- private string CustomDotNetCliPath { get; }
-
- private string JavaScriptEngine { get; set; }
-
- private string JavaScriptEngineArguments { get; set; }
-
- private string RuntimeJavaScriptName { get; set; }
-
- private string ExtraRuntimeArguments { get; set; }
-
- public ExecuteResult Execute(ExecuteParameters executeParameters)
- {
- if (!File.Exists(executeParameters.BuildResult.ArtifactsPaths.ExecutablePath))
- {
- executeParameters.Logger.WriteLineError($"Did not find {executeParameters.BuildResult.ArtifactsPaths.ExecutablePath}, but the folder contained:");
- foreach (var file in new DirectoryInfo(executeParameters.BuildResult.ArtifactsPaths.BinariesDirectoryPath).GetFiles("*.*"))
- executeParameters.Logger.WriteLineError(file.Name);
-
- return new ExecuteResult(false, -1, default, Array.Empty(), Array.Empty());
- }
-
- try
- {
- return Execute(
- executeParameters.BenchmarkCase,
- executeParameters.BenchmarkId,
- executeParameters.Logger,
- executeParameters.BuildResult.ArtifactsPaths,
- executeParameters.Diagnoser,
- Path.GetFileName(executeParameters.BuildResult.ArtifactsPaths.ExecutablePath),
- executeParameters.Resolver);
- }
- finally
- {
- executeParameters.Diagnoser?.Handle(
- HostSignal.AfterProcessExit,
- new DiagnoserActionParameters(null, executeParameters.BenchmarkCase, executeParameters.BenchmarkId));
- }
- }
-
- private ExecuteResult Execute(BenchmarkCase benchmarkCase,
- BenchmarkId benchmarkId,
- ILogger logger,
- ArtifactsPaths artifactsPaths,
- IDiagnoser diagnoser,
- string executableName,
- IResolver resolver)
- {
- ProcessStartInfo startInfo = WasmExecutor.BuildStartInfo(
- customDotNetCliPath: CustomDotNetCliPath,
- workingDirectory: artifactsPaths.BinariesDirectoryPath,
- programName: artifactsPaths.ProgramName,
- benchmarkId: benchmarkId.ToArguments(),
- javaScriptEngine: JavaScriptEngine,
- runtimeJavaScriptName: RuntimeJavaScriptName,
- javaScriptEngineArguments: JavaScriptEngineArguments,
- extraRuntimeArguments: ExtraRuntimeArguments,
- redirectStandardInput: true);
-
-
- startInfo.SetEnvironmentVariables(benchmarkCase, resolver);
-
- using (var process = new Process { StartInfo = startInfo })
- using (new ConsoleExitHandler(process, logger))
- {
- var loggerWithDiagnoser = new SynchronousProcessOutputLoggerWithDiagnoser(logger, process, diagnoser, benchmarkCase, benchmarkId);
-
- logger.WriteLineInfo($"// Execute: {process.StartInfo.FileName} {process.StartInfo.Arguments} in {process.StartInfo.WorkingDirectory}");
-
- diagnoser?.Handle(HostSignal.BeforeProcessStart, new DiagnoserActionParameters(process, benchmarkCase, benchmarkId));
-
- process.Start();
-
- process.EnsureHighPriority(logger);
- if (benchmarkCase.Job.Environment.HasValue(EnvironmentMode.AffinityCharacteristic))
- {
- process.TrySetAffinity(benchmarkCase.Job.Environment.Affinity, logger);
- }
-
- loggerWithDiagnoser.ProcessInput();
- string standardError = process.StandardError.ReadToEnd();
-
- process.WaitForExit(); // should we add timeout here?
-
- if (process.ExitCode == 0)
- {
- return new ExecuteResult(true, process.ExitCode, process.Id, loggerWithDiagnoser.LinesWithResults, loggerWithDiagnoser.LinesWithExtraOutput);
- }
-
- if (!string.IsNullOrEmpty(standardError))
- {
- logger.WriteError(standardError);
- }
-
- return new ExecuteResult(true, process.ExitCode, process.Id, Array.Empty(), Array.Empty());
- }
- }
-
-
- internal static ProcessStartInfo BuildStartInfo(string customDotNetCliPath,
- string workingDirectory,
- string programName,
- string benchmarkId,
- string javaScriptEngine,
- string runtimeJavaScriptName,
- string javaScriptEngineArguments,
- string extraRuntimeArguments,
- IReadOnlyList environmentVariables = null,
- bool redirectStandardInput = false)
- {
- const string dotnetMultiLevelLookupEnvVarName = "DOTNET_MULTILEVEL_LOOKUP";
-
- ProcessStartInfo startInfo = new ProcessStartInfo
- {
- FileName = javaScriptEngine,
- WorkingDirectory = workingDirectory,
- Arguments = $"{javaScriptEngineArguments} {runtimeJavaScriptName} -- {extraRuntimeArguments} --run {programName}.dll {benchmarkId} ",
- UseShellExecute = false,
- CreateNoWindow = true,
- RedirectStandardOutput = true,
- RedirectStandardError = true,
- RedirectStandardInput = redirectStandardInput
- };
-
- if (environmentVariables != null)
- foreach (var environmentVariable in environmentVariables)
- startInfo.EnvironmentVariables[environmentVariable.Key] = environmentVariable.Value;
-
- if (!string.IsNullOrEmpty(customDotNetCliPath) && (environmentVariables == null || environmentVariables.All(envVar => envVar.Key != dotnetMultiLevelLookupEnvVarName)))
- startInfo.EnvironmentVariables[dotnetMultiLevelLookupEnvVarName] = "0";
-
- return startInfo;
- }
- }
-}
\ No newline at end of file
diff --git a/src/BenchmarkDotNet/Toolchains/MonoWasm/WasmGenerator.cs b/src/BenchmarkDotNet/Toolchains/MonoWasm/WasmGenerator.cs
index b92b403aeb..7cddc3e567 100644
--- a/src/BenchmarkDotNet/Toolchains/MonoWasm/WasmGenerator.cs
+++ b/src/BenchmarkDotNet/Toolchains/MonoWasm/WasmGenerator.cs
@@ -1,35 +1,17 @@
-using System;
-using System.Collections.Generic;
-using System.Diagnostics.CodeAnalysis;
-using System.IO;
-using System.Linq;
+using System.IO;
using System.Text;
using BenchmarkDotNet.Extensions;
using BenchmarkDotNet.Helpers;
using BenchmarkDotNet.Loggers;
-using BenchmarkDotNet.Portability;
using BenchmarkDotNet.Running;
using BenchmarkDotNet.Toolchains.CsProj;
-using BenchmarkDotNet.Toolchains.DotNetCli;
namespace BenchmarkDotNet.Toolchains.MonoWasm
{
public class WasmGenerator : CsProjGenerator
{
- private string MainJS;
-
- public WasmGenerator(string targetFrameworkMoniker,
- string cliPath,
- string packagesPath,
- string mainJS
- )
- : base(targetFrameworkMoniker,
- cliPath,
- packagesPath,
- null)
- {
- MainJS = mainJS;
- }
+ public WasmGenerator(string targetFrameworkMoniker, string cliPath, string packagesPath)
+ : base(targetFrameworkMoniker, cliPath, packagesPath, runtimeFrameworkVersion: null) { }
protected override void GenerateProject(BuildPartition buildPartition, ArtifactsPaths artifactsPaths, ILogger logger)
{
@@ -40,23 +22,23 @@ protected override void GenerateProject(BuildPartition buildPartition, Artifacts
var (customProperties, sdkName) = GetSettingsThatNeedsToBeCopied(file, projectFile);
string content = new StringBuilder(ResourceHelper.LoadTemplate("WasmCsProj.txt"))
- .Replace("$PLATFORM$", buildPartition.Platform.ToConfig())
- .Replace("$CODEFILENAME$", Path.GetFileName(artifactsPaths.ProgramCodePath))
- .Replace("$CSPROJPATH$", projectFile.FullName)
- .Replace("$TFM$", TargetFrameworkMoniker)
- .Replace("$PROGRAMNAME$", artifactsPaths.ProgramName)
- .Replace("$COPIEDSETTINGS$", customProperties)
- .Replace("$CONFIGURATIONNAME$", buildPartition.BuildConfiguration)
- .Replace("$SDKNAME$", sdkName)
- .ToString();
+ .Replace("$PLATFORM$", buildPartition.Platform.ToConfig())
+ .Replace("$CODEFILENAME$", Path.GetFileName(artifactsPaths.ProgramCodePath))
+ .Replace("$CSPROJPATH$", projectFile.FullName)
+ .Replace("$TFM$", TargetFrameworkMoniker)
+ .Replace("$PROGRAMNAME$", artifactsPaths.ProgramName)
+ .Replace("$COPIEDSETTINGS$", customProperties)
+ .Replace("$CONFIGURATIONNAME$", buildPartition.BuildConfiguration)
+ .Replace("$SDKNAME$", sdkName)
+ .ToString();
File.WriteAllText(artifactsPaths.ProjectFilePath, content);
}
}
- protected override string GetExecutablePath(string binariesDirectoryPath, string programName) => Path.Combine(binariesDirectoryPath, "runtime.js");
+ protected override string GetExecutablePath(string binariesDirectoryPath, string programName) => Path.Combine(binariesDirectoryPath, "runtime.js");
protected override string GetBinariesDirectoryPath(string buildArtifactsDirectoryPath, string configuration)
=> Path.Combine(buildArtifactsDirectoryPath, "bin", TargetFrameworkMoniker, "browser-wasm", "publish", "output");
}
-}
+}
\ No newline at end of file
diff --git a/src/BenchmarkDotNet/Toolchains/MonoWasm/WasmSettings.cs b/src/BenchmarkDotNet/Toolchains/MonoWasm/WasmSettings.cs
deleted file mode 100644
index b58e5f93ac..0000000000
--- a/src/BenchmarkDotNet/Toolchains/MonoWasm/WasmSettings.cs
+++ /dev/null
@@ -1,19 +0,0 @@
-using System;
-namespace BenchmarkDotNet.Toolchains.MonoWasm
-{
- public class WasmSettings
- {
- public string WasmMainJS { get; }
-
- public string WasmJavaScriptEngine { get; }
-
- public string WasmJavaScriptEngineArguments { get; }
-
- public WasmSettings(string wasmMainJS, string wasmJavaScriptEngine, string wasmjavaScriptEngineArguments)
- {
- WasmMainJS = wasmMainJS;
- WasmJavaScriptEngine = wasmJavaScriptEngine;
- WasmJavaScriptEngineArguments = wasmjavaScriptEngineArguments;
- }
- }
-}
diff --git a/src/BenchmarkDotNet/Toolchains/MonoWasm/WasmToolChain.cs b/src/BenchmarkDotNet/Toolchains/MonoWasm/WasmToolChain.cs
index 78f8101da4..3ec306ebe3 100644
--- a/src/BenchmarkDotNet/Toolchains/MonoWasm/WasmToolChain.cs
+++ b/src/BenchmarkDotNet/Toolchains/MonoWasm/WasmToolChain.cs
@@ -1,58 +1,49 @@
-using System;
-using System.Runtime.InteropServices;
-using BenchmarkDotNet.Toolchains.DotNetCli;
+using BenchmarkDotNet.Toolchains.DotNetCli;
using JetBrains.Annotations;
using BenchmarkDotNet.Characteristics;
using BenchmarkDotNet.Running;
using BenchmarkDotNet.Loggers;
+using BenchmarkDotNet.Portability;
namespace BenchmarkDotNet.Toolchains.MonoWasm
{
[PublicAPI]
public class WasmToolChain : Toolchain
{
- [PublicAPI] public static readonly IToolchain NetCoreApp50Wasm = From(NetCoreAppSettings.NetCoreApp50, new WasmSettings(null, null, null));
+ private string CustomDotNetCliPath { get; }
- private WasmToolChain(string name, IGenerator generator, IBuilder builder, IExecutor executor, string runtimeJavaScriptPath)
+ private WasmToolChain(string name, IGenerator generator, IBuilder builder, IExecutor executor, string customDotNetCliPath)
: base(name, generator, builder, executor)
{
- }
-
- public WasmToolChain(string name,
- string targetFrameworkMoniker,
- string cliPath,
- string packagesPath,
- WasmSettings wasmSettings,
- TimeSpan timeout)
- : base(name,
- new WasmGenerator(targetFrameworkMoniker,
- cliPath,
- packagesPath,
- wasmSettings.WasmMainJS),
- new WasmBuilder(targetFrameworkMoniker, wasmSettings, cliPath, timeout),
- new WasmExecutor(wasmSettings.WasmMainJS, wasmSettings.WasmJavaScriptEngine, wasmSettings.WasmJavaScriptEngineArguments)
- )
- {
+ CustomDotNetCliPath = customDotNetCliPath;
}
public override bool IsSupported(BenchmarkCase benchmarkCase, ILogger logger, IResolver resolver)
{
- return !System.Runtime.InteropServices.RuntimeInformation.IsOSPlatform(OSPlatform.Windows);
+ if (!base.IsSupported(benchmarkCase, logger, resolver))
+ return false;
+
+ if (InvalidCliPath(CustomDotNetCliPath, benchmarkCase, logger))
+ return false;
+
+ if (RuntimeInformation.IsWindows())
+ {
+ logger.WriteLineError($"{nameof(WasmToolChain)} is supported only on Unix, benchmark '{benchmarkCase.DisplayInfo}' will not be executed");
+ return false;
+ }
+ return true;
}
[PublicAPI]
- public static IToolchain From(NetCoreAppSettings netCoreAppSettings, WasmSettings wasmSettings)
- {
- return new WasmToolChain(netCoreAppSettings.Name,
- new WasmGenerator(netCoreAppSettings.TargetFrameworkMoniker,
- netCoreAppSettings.CustomDotNetCliPath,
- netCoreAppSettings.PackagesPath,
- wasmSettings.WasmMainJS),
- new DotNetCliBuilder(netCoreAppSettings.TargetFrameworkMoniker,
- netCoreAppSettings.CustomDotNetCliPath,
- netCoreAppSettings.Timeout),
- new WasmExecutor(wasmSettings.WasmMainJS, wasmSettings.WasmJavaScriptEngine, wasmSettings.WasmJavaScriptEngineArguments),
- netCoreAppSettings.CustomDotNetCliPath);
- }
+ public static IToolchain From(NetCoreAppSettings netCoreAppSettings)
+ => new WasmToolChain(netCoreAppSettings.Name,
+ new WasmGenerator(netCoreAppSettings.TargetFrameworkMoniker,
+ netCoreAppSettings.CustomDotNetCliPath,
+ netCoreAppSettings.PackagesPath),
+ new WasmBuilder(netCoreAppSettings.TargetFrameworkMoniker,
+ netCoreAppSettings.CustomDotNetCliPath,
+ netCoreAppSettings.Timeout),
+ new Executor(),
+ netCoreAppSettings.CustomDotNetCliPath);
}
}
diff --git a/src/BenchmarkDotNet/Toolchains/ToolchainExtensions.cs b/src/BenchmarkDotNet/Toolchains/ToolchainExtensions.cs
index a6fdf7f237..591af97b0e 100644
--- a/src/BenchmarkDotNet/Toolchains/ToolchainExtensions.cs
+++ b/src/BenchmarkDotNet/Toolchains/ToolchainExtensions.cs
@@ -6,6 +6,7 @@
using BenchmarkDotNet.Running;
using BenchmarkDotNet.Toolchains.CoreRt;
using BenchmarkDotNet.Toolchains.CsProj;
+using BenchmarkDotNet.Toolchains.DotNetCli;
using BenchmarkDotNet.Toolchains.InProcess;
using BenchmarkDotNet.Toolchains.InProcess.Emit;
using BenchmarkDotNet.Toolchains.InProcess.NoEmit;
@@ -65,7 +66,7 @@ internal static IToolchain GetToolchain(this Runtime runtime, Descriptor descrip
: CoreRtToolchain.CreateBuilder().UseCoreRtNuGet().TargetFrameworkMoniker(coreRtRuntime.MsBuildMoniker).ToToolchain();
case WasmRuntime wasmRuntime:
- return WasmToolChain.NetCoreApp50Wasm;
+ return WasmToolChain.From(new NetCoreAppSettings(targetFrameworkMoniker: wasmRuntime.MsBuildMoniker, name: wasmRuntime.Name, runtimeFrameworkVersion: null));
default:
throw new ArgumentOutOfRangeException(nameof(runtime), runtime, "Runtime not supported");