Skip to content

Commit b79282e

Browse files
authored
use ClrMd2Disassembler on Windows whenever possible (#2071)
1 parent 0f457d1 commit b79282e

File tree

3 files changed

+45
-33
lines changed

3 files changed

+45
-33
lines changed

src/BenchmarkDotNet/Disassemblers/DisassemblyDiagnoser.cs

Lines changed: 31 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@
1515
using BenchmarkDotNet.Reports;
1616
using BenchmarkDotNet.Running;
1717
using BenchmarkDotNet.Toolchains.InProcess.NoEmit;
18-
using BenchmarkDotNet.Toolchains.NativeAot;
1918
using BenchmarkDotNet.Validators;
2019

2120
namespace BenchmarkDotNet.Diagnosers
@@ -24,16 +23,16 @@ public class DisassemblyDiagnoser : IDiagnoser
2423
{
2524
private static readonly Lazy<string> ptrace_scope = new Lazy<string>(() => ProcessHelper.RunAndReadOutput("cat", "/proc/sys/kernel/yama/ptrace_scope").Trim());
2625

27-
private readonly WindowsDisassembler windowsDisassembler;
28-
private readonly LinuxDisassembler linuxDisassembler;
26+
private readonly WindowsDisassembler windowsDifferentArchitectureDisassembler;
27+
private readonly SameArchitectureDisassembler sameArchitectureDisassembler;
2928
private readonly MonoDisassembler monoDisassembler;
3029
private readonly Dictionary<BenchmarkCase, DisassemblyResult> results;
3130

3231
public DisassemblyDiagnoser(DisassemblyDiagnoserConfig config)
3332
{
3433
Config = config;
35-
windowsDisassembler = new WindowsDisassembler(config);
36-
linuxDisassembler = new LinuxDisassembler(config);
34+
windowsDifferentArchitectureDisassembler = new WindowsDisassembler(config);
35+
sameArchitectureDisassembler = new SameArchitectureDisassembler(config);
3736
monoDisassembler = new MonoDisassembler(config);
3837

3938
results = new Dictionary<BenchmarkCase, DisassemblyResult>();
@@ -58,9 +57,9 @@ public IEnumerable<Metric> ProcessResults(DiagnoserResults diagnoserResults)
5857

5958
public RunMode GetRunMode(BenchmarkCase benchmarkCase)
6059
{
61-
if (ShouldUseWindowsDisassembler(benchmarkCase) || ShouldUseLinuxDisassembler(benchmarkCase))
60+
if (ShouldUseClrMdDisassembler(benchmarkCase))
6261
return RunMode.NoOverhead;
63-
if (ShouldUseMonoDisassembler(benchmarkCase))
62+
else if (ShouldUseMonoDisassembler(benchmarkCase))
6463
return RunMode.SeparateLogic;
6564

6665
return RunMode.None;
@@ -74,11 +73,11 @@ public void Handle(HostSignal signal, DiagnoserActionParameters parameters)
7473

7574
switch (signal)
7675
{
77-
case HostSignal.AfterAll when ShouldUseWindowsDisassembler(benchmark):
78-
results.Add(benchmark, windowsDisassembler.Disassemble(parameters));
76+
case HostSignal.AfterAll when ShouldUseSameArchitectureDisassembler(benchmark, parameters):
77+
results.Add(benchmark, sameArchitectureDisassembler.Disassemble(parameters));
7978
break;
80-
case HostSignal.AfterAll when ShouldUseLinuxDisassembler(benchmark):
81-
results.Add(benchmark, linuxDisassembler.Disassemble(parameters));
79+
case HostSignal.AfterAll when RuntimeInformation.IsWindows() && !ShouldUseMonoDisassembler(benchmark):
80+
results.Add(benchmark, windowsDifferentArchitectureDisassembler.Disassemble(parameters));
8281
break;
8382
case HostSignal.SeparateLogic when ShouldUseMonoDisassembler(benchmark):
8483
results.Add(benchmark, monoDisassembler.Disassemble(benchmark, benchmark.Job.Environment.Runtime as MonoRuntime));
@@ -112,7 +111,7 @@ public IEnumerable<ValidationError> Validate(ValidationParameters validationPara
112111
yield return new ValidationError(true, "Currently NativeAOT has no DisassemblyDiagnoser support", benchmark);
113112
}
114113

115-
if (ShouldUseLinuxDisassembler(benchmark))
114+
if (RuntimeInformation.IsLinux() && ShouldUseClrMdDisassembler(benchmark))
116115
{
117116
var runtime = benchmark.Job.ResolveValue(EnvironmentMode.RuntimeCharacteristic, EnvironmentResolver.Instance);
118117

@@ -136,11 +135,27 @@ public IEnumerable<ValidationError> Validate(ValidationParameters validationPara
136135
private static bool ShouldUseMonoDisassembler(BenchmarkCase benchmarkCase)
137136
=> benchmarkCase.Job.Environment.Runtime is MonoRuntime || RuntimeInformation.IsMono;
138137

139-
private static bool ShouldUseWindowsDisassembler(BenchmarkCase benchmarkCase)
140-
=> !(benchmarkCase.Job.Environment.Runtime is MonoRuntime) && RuntimeInformation.IsWindows();
138+
// when we add macOS support, RuntimeInformation.IsMacOSX() needs to be added here
139+
private static bool ShouldUseClrMdDisassembler(BenchmarkCase benchmarkCase)
140+
=> !ShouldUseMonoDisassembler(benchmarkCase) && (RuntimeInformation.IsWindows() || RuntimeInformation.IsLinux());
141141

142-
private static bool ShouldUseLinuxDisassembler(BenchmarkCase benchmarkCase)
143-
=> !(benchmarkCase.Job.Environment.Runtime is MonoRuntime) && RuntimeInformation.IsLinux();
142+
private static bool ShouldUseSameArchitectureDisassembler(BenchmarkCase benchmarkCase, DiagnoserActionParameters parameters)
143+
{
144+
if (ShouldUseClrMdDisassembler(benchmarkCase))
145+
{
146+
if (RuntimeInformation.IsWindows())
147+
{
148+
return WindowsDisassembler.GetDisassemblerArchitecture(parameters.Process, benchmarkCase.Job.Environment.Platform)
149+
== RuntimeInformation.GetCurrentPlatform();
150+
}
151+
152+
// on Unix currently host process architecture is always the same as benchmark process architecture
153+
// (no official x86 support)
154+
return true;
155+
}
156+
157+
return false;
158+
}
144159

145160
private static IEnumerable<IExporter> GetExporters(Dictionary<BenchmarkCase, DisassemblyResult> results, DisassemblyDiagnoserConfig config)
146161
{

src/BenchmarkDotNet/Disassemblers/LinuxDisassembler.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,11 @@
22

33
namespace BenchmarkDotNet.Disassemblers
44
{
5-
internal class LinuxDisassembler
5+
internal class SameArchitectureDisassembler
66
{
77
private readonly DisassemblyDiagnoserConfig config;
88

9-
internal LinuxDisassembler(DisassemblyDiagnoserConfig config) => this.config = config;
9+
internal SameArchitectureDisassembler(DisassemblyDiagnoserConfig config) => this.config = config;
1010

1111
internal DisassemblyResult Disassemble(DiagnoserActionParameters parameters)
1212
=> ClrMdV2Disassembler.AttachAndDisassemble(BuildDisassemblerSettings(parameters));

src/BenchmarkDotNet/Disassemblers/WindowsDisassembler.cs

Lines changed: 12 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -61,23 +61,20 @@ public DisassemblyResult Disassemble(DiagnoserActionParameters parameters)
6161
}
6262
}
6363

64+
internal static Platform GetDisassemblerArchitecture(Process process, Platform platform)
65+
=> platform switch
66+
{
67+
Platform.AnyCpu => NativeMethods.Is64Bit(process) ? Platform.X64 : Platform.X86, // currently ARM is not supported
68+
_ => platform
69+
};
70+
6471
private static string GetDisassemblerPath(Process process, Platform platform)
65-
{
66-
switch (platform)
72+
=> GetDisassemblerArchitecture(process, platform) switch
6773
{
68-
case Platform.AnyCpu:
69-
return GetDisassemblerPath(process,
70-
NativeMethods.Is64Bit(process)
71-
? Platform.X64
72-
: Platform.X86);
73-
case Platform.X86:
74-
return GetDisassemblerPath("x86");
75-
case Platform.X64:
76-
return GetDisassemblerPath("x64");
77-
default:
78-
throw new NotSupportedException($"Platform {platform} not supported!");
79-
}
80-
}
74+
Platform.X86 => GetDisassemblerPath("x86"),
75+
Platform.X64 => GetDisassemblerPath("x64"),
76+
_ => throw new NotSupportedException($"Platform {platform} not supported!")
77+
};
8178

8279
private static string GetDisassemblerPath(string architectureName)
8380
{

0 commit comments

Comments
 (0)