Skip to content

Commit 152414b

Browse files
authored
Bring instruction pointer exporter back to live (#1550)
* make sure that TraceLogParser populates IP to hardware counter dictionary * make EtwProfiler implement the property required by InstructionPointerExporter * improve the exported file name so it contains runtime ID and arch info
1 parent fbd52c0 commit 152414b

File tree

3 files changed

+70
-6
lines changed

3 files changed

+70
-6
lines changed

src/BenchmarkDotNet.Diagnostics.Windows/EtwProfiler.cs

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ public EtwProfiler(EtwProfilerConfig config)
4949

5050
public IEnumerable<IAnalyser> Analysers => Array.Empty<IAnalyser>();
5151

52-
public IReadOnlyDictionary<BenchmarkCase, PmcStats> Results => ImmutableDictionary<BenchmarkCase, PmcStats>.Empty;
52+
public IReadOnlyDictionary<BenchmarkCase, PmcStats> Results => BuildPmcStats();
5353

5454
internal IReadOnlyDictionary<BenchmarkCase, string> BenchmarkToEtlFile => benchmarkToEtlFile;
5555

@@ -149,5 +149,24 @@ private void Stop(DiagnoserActionParameters parameters)
149149
/// This increases the likelihood that all relevant events are processed by the collection thread by the time we are done with the benchmark.
150150
/// </summary>
151151
private static void WaitForDelayedEvents() => Thread.Sleep(TimeSpan.FromMilliseconds(500));
152+
153+
private IReadOnlyDictionary<BenchmarkCase, PmcStats> BuildPmcStats()
154+
{
155+
var builder = ImmutableDictionary.CreateBuilder<BenchmarkCase, PmcStats>();
156+
157+
foreach (var benchmarkToCounter in benchmarkToCounters)
158+
{
159+
var uniqueCounters = benchmarkToCounter.Value.Select(x => x.Counter).Distinct().ToImmutableArray();
160+
161+
var pmcStats = new PmcStats(
162+
uniqueCounters,
163+
counter => benchmarkToCounter.Value.Single(pmc => pmc.Counter == counter)
164+
);
165+
166+
builder.Add(benchmarkToCounter.Key, pmcStats);
167+
}
168+
169+
return builder.ToImmutable();
170+
}
152171
}
153172
}

src/BenchmarkDotNet.Diagnostics.Windows/Tracing/TraceLogParser.cs

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,7 @@ public IEnumerable<Metric> CalculateMetrics(Dictionary<int, int> profileSourceId
133133
var overheadIterations = CreateIterationData(overheadTimestamps);
134134
var workloadIterations = CreateIterationData(workloadTimestamps);
135135

136-
SumCountersPerIterations(profileSourceIdToInterval, workloadIterations, overheadIterations);
136+
SumCountersPerIterations(profileSourceIdToInterval, workloadIterations, overheadIterations, counters);
137137

138138
var workloadTotalPerCounter = Sum(workloadIterations);
139139
var overheadTotalPerCounter = Sum(overheadIterations);
@@ -172,15 +172,22 @@ private IterationData[] CreateIterationData(List<double> startStopTimeStamps)
172172
return iterations;
173173
}
174174

175-
private void SumCountersPerIterations(Dictionary<int, int> profileSourceIdToInterval, IterationData[] workloadIterations, IterationData[] overheadIterations)
175+
private void SumCountersPerIterations(Dictionary<int, int> profileSourceIdToInterval, IterationData[] workloadIterations, IterationData[] overheadIterations,
176+
PreciseMachineCounter[] counters)
176177
{
178+
var profileSourceIdToCounter = counters.ToDictionary(counter => counter.ProfileSourceId);
179+
177180
foreach (var sample in samples)
178181
{
179182
var interval = profileSourceIdToInterval[sample.profileSource];
180183

181184
foreach (var workloadIteration in workloadIterations)
182185
if (workloadIteration.TryHandle(sample.timeStamp, sample.profileSource, interval))
186+
{
187+
profileSourceIdToCounter[sample.profileSource].OnSample(sample.instructionPointer);
188+
183189
goto next;
190+
}
184191

185192
foreach (var overheadIteration in overheadIterations)
186193
if (overheadIteration.TryHandle(sample.timeStamp, sample.profileSource, interval))

src/BenchmarkDotNet/Exporters/InstructionPointerExporter.cs

Lines changed: 41 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
11
using System.Collections.Generic;
22
using System.IO;
33
using System.Linq;
4+
using System.Text;
45
using BenchmarkDotNet.Diagnosers;
56
using BenchmarkDotNet.Disassemblers;
7+
using BenchmarkDotNet.Extensions;
8+
using BenchmarkDotNet.Helpers;
69
using BenchmarkDotNet.Loggers;
710
using BenchmarkDotNet.Reports;
811
using BenchmarkDotNet.Running;
@@ -46,9 +49,12 @@ public IEnumerable<string> ExportToFiles(Summary summary, ILogger consoleLogger)
4649

4750
private string Export(Summary summary, BenchmarkCase benchmarkCase, DisassemblyResult disassemblyResult, PmcStats pmcStats)
4851
{
49-
string filePath = $"{Path.Combine(summary.ResultsDirectoryPath, benchmarkCase.Descriptor.WorkloadMethod.Name)}-{benchmarkCase.Job.Environment.Jit}-{benchmarkCase.Job.Environment.Platform}-instructionPointer.html";
50-
if (File.Exists(filePath))
51-
File.Delete(filePath);
52+
string filePath = Path.Combine(summary.ResultsDirectoryPath,
53+
$"{FolderNameHelper.ToFolderName(benchmarkCase.Descriptor.Type)}." +
54+
$"{benchmarkCase.Descriptor.WorkloadMethod.Name}." +
55+
$"{GetShortRuntimeInfo(summary[benchmarkCase].GetRuntimeInfo())}.counters.html");
56+
57+
filePath.DeleteFileIfExists();
5258

5359
var totals = SumHardwareCountersStatsOfBenchmarkedCode(disassemblyResult, pmcStats);
5460
var perMethod = SumHardwareCountersPerMethod(disassemblyResult, pmcStats);
@@ -251,6 +257,38 @@ private void Export(ILogger logger, BenchmarkCase benchmarkCase, Dictionary<Hard
251257
logger.WriteLine("</tbody></table></body></html>");
252258
}
253259

260+
// fullInfo is sth like ".NET Core 2.1.21 (CoreCLR 4.6.29130.01, CoreFX 4.6.29130.02), X64 RyuJIT"
261+
private static string GetShortRuntimeInfo(string fullInfo)
262+
{
263+
var builder = new StringBuilder();
264+
265+
for (int i = 0; i < fullInfo.IndexOf('(') - 1; i++)
266+
{
267+
if (fullInfo[i] != ' ')
268+
{
269+
builder.Append(fullInfo[i]);
270+
}
271+
else
272+
{
273+
builder.Append('_');
274+
}
275+
}
276+
277+
for (int i = fullInfo.LastIndexOf(',') + 1; i < fullInfo.Length; i++)
278+
{
279+
if (fullInfo[i] != ' ')
280+
{
281+
builder.Append(fullInfo[i]);
282+
}
283+
else
284+
{
285+
builder.Append('_');
286+
}
287+
}
288+
289+
return builder.ToString();
290+
}
291+
254292
private class CodeWithCounters
255293
{
256294
internal SourceCode Code { get; set; }

0 commit comments

Comments
 (0)