Skip to content

Commit

Permalink
Add support for .NET SDK that uses Mono instead CLR as a default VM (#…
Browse files Browse the repository at this point in the history
…2230)

* add a failing test

* fix current runtime detection for Mono SDK

unify the order of runtime checks with other helper methods

* delay the creation to avoid exceptions at DisassemblyDiagnoser ctor

* use different toolchain when current .NET SDK uses MonoVM
  • Loading branch information
adamsitnik authored Dec 16, 2022
1 parent bf8b531 commit 82f03f4
Show file tree
Hide file tree
Showing 6 changed files with 58 additions and 23 deletions.
Original file line number Diff line number Diff line change
@@ -1,24 +1,21 @@
using BenchmarkDotNet.Diagnosers;
using BenchmarkDotNet.Environments;
using BenchmarkDotNet.Portability;
using BenchmarkDotNet.Toolchains;
using System;

namespace BenchmarkDotNet.Disassemblers
{
internal class SameArchitectureDisassembler
{
private readonly DisassemblyDiagnoserConfig config;
private readonly ClrMdV2Disassembler clrMdV2Disassembler;
private ClrMdV2Disassembler? clrMdV2Disassembler;

internal SameArchitectureDisassembler(DisassemblyDiagnoserConfig config)
{
this.config = config;
clrMdV2Disassembler = CreateDisassemblerForCurrentArchitecture();
}
internal SameArchitectureDisassembler(DisassemblyDiagnoserConfig config) => this.config = config;

internal DisassemblyResult Disassemble(DiagnoserActionParameters parameters)
=> clrMdV2Disassembler.AttachAndDisassemble(BuildDisassemblerSettings(parameters));
// delay the creation to avoid exceptions at DisassemblyDiagnoser ctor
=> (clrMdV2Disassembler ??= CreateDisassemblerForCurrentArchitecture())
.AttachAndDisassemble(BuildDisassemblerSettings(parameters));

private static ClrMdV2Disassembler CreateDisassemblerForCurrentArchitecture()
=> RuntimeInformation.GetCurrentPlatform() switch
Expand Down
4 changes: 2 additions & 2 deletions src/BenchmarkDotNet/Environments/Runtimes/CoreRuntime.cs
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,9 @@ private CoreRuntime(RuntimeMoniker runtimeMoniker, string msBuildMoniker, string
public bool IsPlatformSpecific => MsBuildMoniker.IndexOf('-') > 0;

/// <summary>
/// use this method if you want to target .NET Core version not supported by current version of BenchmarkDotNet. Example: .NET Core 10
/// use this method if you want to target .NET version not supported by current version of BenchmarkDotNet. Example: .NET 10
/// </summary>
/// <param name="msBuildMoniker">msbuild moniker, example: netcoreapp10.0</param>
/// <param name="msBuildMoniker">msbuild moniker, example: net10.0</param>
/// <param name="displayName">display name used by BDN to print the results</param>
/// <returns>new runtime information</returns>
public static CoreRuntime CreateForNewVersion(string msBuildMoniker, string displayName)
Expand Down
20 changes: 16 additions & 4 deletions src/BenchmarkDotNet/Environments/Runtimes/MonoRuntime.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@ namespace BenchmarkDotNet.Environments
{
public class MonoRuntime : Runtime, IEquatable<MonoRuntime>
{
public static readonly MonoRuntime Default = new MonoRuntime("Mono");
public static readonly MonoRuntime Mono60 = new MonoRuntime("Mono with .NET 6.0", RuntimeMoniker.Mono60, "net6.0", isDotNetBuiltIn: true);
public static readonly MonoRuntime Mono70 = new MonoRuntime("Mono with .NET 7.0", RuntimeMoniker.Mono70, "net7.0", isDotNetBuiltIn: true);
public static readonly MonoRuntime Mono80 = new MonoRuntime("Mono with .NET 8.0", RuntimeMoniker.Mono80, "net8.0", isDotNetBuiltIn: true);
public static readonly MonoRuntime Default = new ("Mono");
public static readonly MonoRuntime Mono60 = new ("Mono with .NET 6.0", RuntimeMoniker.Mono60, "net6.0", isDotNetBuiltIn: true);
public static readonly MonoRuntime Mono70 = new ("Mono with .NET 7.0", RuntimeMoniker.Mono70, "net7.0", isDotNetBuiltIn: true);
public static readonly MonoRuntime Mono80 = new ("Mono with .NET 8.0", RuntimeMoniker.Mono80, "net8.0", isDotNetBuiltIn: true);

public string CustomPath { get; }

Expand Down Expand Up @@ -43,5 +43,17 @@ public bool Equals(MonoRuntime other)

public override int GetHashCode()
=> HashCode.Combine(base.GetHashCode(), Name, CustomPath, AotArgs, MonoBclPath);

internal static Runtime GetCurrentVersion()
{
Version version = Environment.Version;
return version.Major switch
{
6 => Mono60,
7 => Mono70,
8 => Mono80,
_ => new MonoRuntime($"Mono with .NET {version.Major}.{version.Minor}", RuntimeMoniker.NotRecognized, $"net{version.Major}.{version.Minor}", isDotNetBuiltIn: true)
};
}
}
}
18 changes: 10 additions & 8 deletions src/BenchmarkDotNet/Portability/RuntimeInformation.cs
Original file line number Diff line number Diff line change
Expand Up @@ -234,7 +234,7 @@ internal static string GetRuntimeVersion()

return $".NET Core (Mono) {versionString}";
}
else if (IsMono)
else if (IsOldMono)
{
var monoRuntimeType = Type.GetType("Mono.Runtime");
var monoDisplayName = monoRuntimeType?.GetMethod("GetDisplayName", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static);
Expand All @@ -255,10 +255,10 @@ internal static string GetRuntimeVersion()

return "Mono " + version;
}
else if (IsNewMono)
{
return $"{GetNetCoreVersion()} using MonoVM";
}
}
else if (IsNewMono)
{
return $"{GetNetCoreVersion()} using MonoVM";
}
else if (IsFullFramework)
{
Expand Down Expand Up @@ -301,12 +301,14 @@ internal static Runtime GetCurrentRuntime()
//do not change the order of conditions because it may cause incorrect determination of runtime
if (IsAot && IsMono)
return MonoAotLLVMRuntime.Default;
if (IsMono)
if (IsWasm)
return WasmRuntime.Default;
if (IsNewMono)
return MonoRuntime.GetCurrentVersion();
if (IsOldMono)
return MonoRuntime.Default;
if (IsFullFramework)
return ClrRuntime.GetCurrentVersion();
if (IsWasm)
return WasmRuntime.Default;
if (IsNetCore)
return CoreRuntime.GetCurrentVersion();
if (IsNativeAOT)
Expand Down
20 changes: 19 additions & 1 deletion src/BenchmarkDotNet/Toolchains/ToolchainExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,25 @@ internal static IToolchain GetToolchain(this Runtime runtime, Descriptor descrip
if (!string.IsNullOrEmpty(mono.AotArgs))
return MonoAotToolchain.Instance;
if (mono.IsDotNetBuiltIn)
return MonoToolchain.From(new NetCoreAppSettings(targetFrameworkMoniker: mono.MsBuildMoniker, runtimeFrameworkVersion: null, name: mono.Name));
if (RuntimeInformation.IsNewMono)
{
// It's a .NET SDK with Mono as default VM.
// Publishing self-contained apps might not work like in https://github.com/dotnet/performance/issues/2787.
// In such case, we are going to use default .NET toolchain that is just going to perform dotnet build,
// which internally will result in creating Mono-based app.
return mono.RuntimeMoniker switch
{
RuntimeMoniker.Mono60 => GetToolchain(RuntimeMoniker.Net60),
RuntimeMoniker.Mono70 => GetToolchain(RuntimeMoniker.Net70),
RuntimeMoniker.Mono80 => GetToolchain(RuntimeMoniker.Net80),
_ => CsProjCoreToolchain.From(new NetCoreAppSettings(mono.MsBuildMoniker, null, mono.Name))
};
}
else
{
return MonoToolchain.From(
new NetCoreAppSettings(targetFrameworkMoniker: mono.MsBuildMoniker, runtimeFrameworkVersion: null, name: mono.Name));
}

return RoslynToolchain.Instance;

Expand Down
6 changes: 6 additions & 0 deletions tests/BenchmarkDotNet.IntegrationTests/MonoTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
using BenchmarkDotNet.Configs;
using BenchmarkDotNet.Environments;
using BenchmarkDotNet.Jobs;
using BenchmarkDotNet.Portability;
using BenchmarkDotNet.Tests.XUnit;

namespace BenchmarkDotNet.IntegrationTests
Expand All @@ -28,6 +29,11 @@ public void Check()
{
throw new Exception("This is not Mono runtime");
}

if (RuntimeInformation.GetCurrentRuntime() != MonoRuntime.Mono70)
{
throw new Exception("Incorrect runtime detection");
}
}
}
}
Expand Down

0 comments on commit 82f03f4

Please sign in to comment.