Skip to content

Commit 32bb2de

Browse files
authored
Improve failure handling and finish time estimation (#1921)
* don't use global chronometer for providing the estimated finish time, as it includes build time which skews the estimation * don't use global chronometer for providing the total time in joined summary, use runsChronometer which does not include build time * the time logged for sequential build should not include failed parallel build * move all the logic responsible for handling execution result status to ExecuteResult * benchmark can fail after few Workload Actual iterations, that is why we search for Workload Results as they are produced at the end
1 parent 80f45ce commit 32bb2de

File tree

19 files changed

+222
-222
lines changed

19 files changed

+222
-222
lines changed

src/BenchmarkDotNet/Analysers/RuntimeErrorAnalyser.cs

+1-7
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
using System.Collections.Generic;
22
using System.Linq;
33
using BenchmarkDotNet.Reports;
4-
using BenchmarkDotNet.Validators;
54

65
namespace BenchmarkDotNet.Analysers
76
{
@@ -16,12 +15,7 @@ private RuntimeErrorAnalyser()
1615

1716
protected override IEnumerable<Conclusion> AnalyseReport(BenchmarkReport report, Summary summary)
1817
{
19-
var errors = report.ExecuteResults.SelectMany(r => r.Data)
20-
.Union(report.ExecuteResults.SelectMany(r => r.ExtraOutput))
21-
.Where(line => line.Contains(ValidationErrorReporter.ConsoleErrorPrefix))
22-
.Select(line => line.Substring(ValidationErrorReporter.ConsoleErrorPrefix.Length).Trim());
23-
24-
foreach (string error in errors)
18+
foreach (string error in report.ExecuteResults.SelectMany(r => r.Errors))
2519
yield return CreateError(error, report);
2620
}
2721
}

src/BenchmarkDotNet/Diagnosers/DiagnoserResults.cs

+6-5
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,19 @@
11
using BenchmarkDotNet.Engines;
2+
using BenchmarkDotNet.Reports;
23
using BenchmarkDotNet.Running;
34
using BenchmarkDotNet.Toolchains.Results;
5+
using System.Linq;
46

57
namespace BenchmarkDotNet.Diagnosers
68
{
79
public class DiagnoserResults
810
{
9-
public DiagnoserResults(BenchmarkCase benchmarkCase, long totalOperations, GcStats gcStats,
10-
ThreadingStats threadingStats, BuildResult buildResult)
11+
public DiagnoserResults(BenchmarkCase benchmarkCase, ExecuteResult executeResult, BuildResult buildResult)
1112
{
1213
BenchmarkCase = benchmarkCase;
13-
TotalOperations = totalOperations;
14-
GcStats = gcStats;
15-
ThreadingStats = threadingStats;
14+
TotalOperations = executeResult.Measurements.Where(measurement => measurement.IsWorkload()).Sum(m => m.Operations);
15+
GcStats = executeResult.GcStats;
16+
ThreadingStats = executeResult.ThreadingStats;
1617
BuildResult = buildResult;
1718
}
1819

src/BenchmarkDotNet/Reports/BenchmarkReport.cs

+2-4
Original file line numberDiff line numberDiff line change
@@ -36,17 +36,15 @@ public BenchmarkReport(
3636
GenerateResult generateResult,
3737
BuildResult buildResult,
3838
IReadOnlyList<ExecuteResult> executeResults,
39-
IReadOnlyList<Measurement> allMeasurements,
40-
GcStats gcStats,
4139
IReadOnlyList<Metric> metrics)
4240
{
4341
Success = success;
4442
BenchmarkCase = benchmarkCase;
4543
GenerateResult = generateResult;
4644
BuildResult = buildResult;
4745
ExecuteResults = executeResults ?? Array.Empty<ExecuteResult>();
48-
AllMeasurements = allMeasurements ?? Array.Empty<Measurement>();
49-
GcStats = gcStats;
46+
AllMeasurements = ExecuteResults.SelectMany((results, index) => results.Measurements).ToArray();
47+
GcStats = ExecuteResults.Count > 0 ? executeResults[executeResults.Count -1].GcStats : default;
5048
Metrics = metrics?.ToDictionary(metric => metric.Descriptor.Id)
5149
?? (IReadOnlyDictionary<string, Metric>)ImmutableDictionary<string, Metric>.Empty;
5250
}

src/BenchmarkDotNet/Reports/Measurement.cs

+5-5
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using System;
2+
using System.Diagnostics;
23
using System.Globalization;
34
using System.Linq;
45
using System.Text;
@@ -111,12 +112,11 @@ public override string ToString()
111112
/// Will extract the number of <see cref="Operations"/> performed and the
112113
/// total number of <see cref="Nanoseconds"/> it took to perform them.
113114
/// </summary>
114-
/// <param name="logger">The logger to write any diagnostic messages to.</param>
115115
/// <param name="line">The line to parse.</param>
116-
/// <param name="processIndex"></param>
116+
/// <param name="processIndex">Process launch index, indexed from one.</param>
117117
/// <returns>An instance of <see cref="Measurement"/> if parsed successfully. <c>Null</c> in case of any trouble.</returns>
118118
// ReSharper disable once UnusedParameter.Global
119-
public static Measurement Parse(ILogger logger, string line, int processIndex)
119+
public static Measurement Parse(string line, int processIndex)
120120
{
121121
if (string.IsNullOrWhiteSpace(line) || line.StartsWith(GcStats.ResultsLinePrefix))
122122
return Error();
@@ -166,8 +166,8 @@ public static Measurement Parse(ILogger logger, string line, int processIndex)
166166
catch (Exception)
167167
{
168168
#if DEBUG // some benchmarks need to write to console and when we display this error it's confusing
169-
logger.WriteLineError("Parse error in the following line:");
170-
logger.WriteLineError(line);
169+
Debug.WriteLine("Parse error in the following line:");
170+
Debug.WriteLine(line);
171171
#endif
172172
return Error();
173173
}

0 commit comments

Comments
 (0)