Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for MonoVM to MemoryDiagnoser #2227

Merged
merged 3 commits into from
Dec 9, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/BenchmarkDotNet/Engines/Engine.cs
Original file line number Diff line number Diff line change
Expand Up @@ -267,7 +267,7 @@ private static void ForceGcCollect()

private static void EnableMonitoring()
{
if (RuntimeInformation.IsMono) // Monitoring is not available in Mono, see http://stackoverflow.com/questions/40234948/how-to-get-the-number-of-allocated-bytes-in-mono
if (RuntimeInformation.IsOldMono) // Monitoring is not available in Mono, see http://stackoverflow.com/questions/40234948/how-to-get-the-number-of-allocated-bytes-in-mono
return;

if (RuntimeInformation.IsFullFramework)
Expand Down
6 changes: 5 additions & 1 deletion src/BenchmarkDotNet/Engines/GcStats.cs
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,11 @@ public static GcStats FromForced(int forcedFullGarbageCollections)

private static long GetAllocatedBytes()
{
if (RuntimeInformation.IsMono) // Monitoring is not available in Mono, see http://stackoverflow.com/questions/40234948/how-to-get-the-number-of-allocated-bytes-
if (RuntimeInformation.IsOldMono) // Monitoring is not available in Mono, see http://stackoverflow.com/questions/40234948/how-to-get-the-number-of-allocated-bytes-
return 0;

// we have no tests for WASM and don't want to risk introducing a new bug (https://github.com/dotnet/BenchmarkDotNet/issues/2226)
if (RuntimeInformation.IsWasm)
return 0;

// "This instance Int64 property returns the number of bytes that have been allocated by a specific
Expand Down
45 changes: 26 additions & 19 deletions src/BenchmarkDotNet/Portability/RuntimeInformation.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,15 @@ internal static class RuntimeInformation
internal const string ReleaseConfigurationName = "RELEASE";
internal const string Unknown = "?";

/// <summary>
/// returns true for both the old (implementation of .NET Framework) and new Mono (.NET 6+ flavour)
/// </summary>
public static bool IsMono { get; } = Type.GetType("Mono.RuntimeStructs") != null; // it allocates a lot of memory, we need to check it once in order to keep Engine non-allocating!

public static bool IsOldMono { get; } = Type.GetType("Mono.Runtime") != null;

public static bool IsNewMono { get; } = IsMono && !IsOldMono;

public static bool IsFullFramework =>
#if NET6_0_OR_GREATER
false;
Expand Down Expand Up @@ -200,7 +207,24 @@ internal static CpuInfo GetCpuInfo()

internal static string GetRuntimeVersion()
{
if (IsMono && !IsWasm)
if (IsWasm)
{
// code copied from https://github.com/dotnet/runtime/blob/2c573b59aaaf3fd17e2ecab95ad3769f195d2dbc/src/libraries/System.Runtime.InteropServices.RuntimeInformation/src/System/Runtime/InteropServices/RuntimeInformation/RuntimeInformation.cs#L20-L30
string versionString = typeof(object).Assembly.GetCustomAttribute<AssemblyInformationalVersionAttribute>()?.InformationalVersion;

// Strip the git hash if there is one
if (versionString != null)
{
int plusIndex = versionString.IndexOf('+');
if (plusIndex != -1)
{
versionString = versionString.Substring(0, plusIndex);
}
}

return $".NET Core (Mono) {versionString}";
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this really supposed to be mono in the string from IsWasm?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Currently WASM is supported only by Mono VM.

}
else if (IsMono)
{
var monoRuntimeType = Type.GetType("Mono.Runtime");
var monoDisplayName = monoRuntimeType?.GetMethod("GetDisplayName", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static);
Expand All @@ -221,7 +245,7 @@ internal static string GetRuntimeVersion()

return "Mono " + version;
}
else
else if (IsNewMono)
{
return $"{GetNetCoreVersion()} using MonoVM";
}
Expand All @@ -230,23 +254,6 @@ internal static string GetRuntimeVersion()
{
return FrameworkVersionHelper.GetFrameworkDescription();
}
else if (IsWasm)
{
// code copied from https://github.com/dotnet/runtime/blob/2c573b59aaaf3fd17e2ecab95ad3769f195d2dbc/src/libraries/System.Runtime.InteropServices.RuntimeInformation/src/System/Runtime/InteropServices/RuntimeInformation/RuntimeInformation.cs#L20-L30
string versionString = typeof(object).Assembly.GetCustomAttribute<AssemblyInformationalVersionAttribute>()?.InformationalVersion;

// Strip the git hash if there is one
if (versionString != null)
{
int plusIndex = versionString.IndexOf('+');
if (plusIndex != -1)
{
versionString = versionString.Substring(0, plusIndex);
}
}

return $".NET Core (Mono) {versionString}";
}
else if (IsNetCore)
{
return GetNetCoreVersion();
Expand Down
17 changes: 16 additions & 1 deletion tests/BenchmarkDotNet.IntegrationTests/MemoryDiagnoserTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
using BenchmarkDotNet.Toolchains.InProcess.Emit;
using Xunit;
using Xunit.Abstractions;
using BenchmarkDotNet.Toolchains.Mono;

namespace BenchmarkDotNet.IntegrationTests
{
Expand All @@ -34,7 +35,7 @@ public class MemoryDiagnoserTests

public static IEnumerable<object[]> GetToolchains()
{
if (RuntimeInformation.IsMono) // https://github.com/mono/mono/issues/8397
if (RuntimeInformation.IsOldMono) // https://github.com/mono/mono/issues/8397
yield break;

yield return new object[] { Job.Default.GetToolchain() };
Expand All @@ -56,6 +57,11 @@ public void MemoryDiagnoserIsAccurate(IToolchain toolchain)
long objectAllocationOverhead = IntPtr.Size * 2; // pointer to method table + object header word
long arraySizeOverhead = IntPtr.Size; // array length

if (toolchain is MonoToolchain)
{
objectAllocationOverhead += IntPtr.Size;
}

AssertAllocations(toolchain, typeof(AccurateAllocations), new Dictionary<string, long>
{
{ nameof(AccurateAllocations.EightBytesArray), 8 + objectAllocationOverhead + arraySizeOverhead },
Expand All @@ -78,6 +84,15 @@ public void MemoryDiagnoserSupportsNativeAOT()
.ToToolchain());
}

[FactDotNetCoreOnly("We don't want to test MonoVM twice (for .NET Framework 4.6.2 and .NET 7.0)")]
public void MemoryDiagnoserSupportsModernMono()
{
if (ContinuousIntegration.IsAppVeyorOnWindows())
return; // timeouts

MemoryDiagnoserIsAccurate(MonoToolchain.Mono70);
}

public class AllocatingGlobalSetupAndCleanup
{
private List<int> list;
Expand Down