-
-
Notifications
You must be signed in to change notification settings - Fork 958
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* implement tests * implement the diagnoser * make the tests pass * make it work for CoreRT * add console line argument and new attribute * make it a warning, not error (to support -f netcoreapp2.x --runtimes netcoreapp3.0) * add docs * update release docs * avoid "No data found" exception for dotnet test -f netcoreapp2.1 * code review fixes
- Loading branch information
1 parent
ea0468f
commit 4080abd
Showing
31 changed files
with
485 additions
and
22 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
--- | ||
uid: BenchmarkDotNet.Samples.IntroThreadingDiagnoser | ||
--- | ||
|
||
## Sample: IntroThreadingDiagnoser | ||
|
||
The `ThreadingDiagnoser` uses new APIs [exposed](https://github.com/dotnet/corefx/issues/35500) in .NET Core 3.0 to report: | ||
|
||
* Completed Work Items: The number of work items that have been processed in ThreadPool (per single operation) | ||
* Lock Contentions: The number of times there **was contention** upon trying to take a Monitor's lock (per single operation) | ||
|
||
### Source code | ||
|
||
[!code-csharp[IntroThreadingDiagnoser.cs](../../../samples/BenchmarkDotNet.Samples/IntroThreadingDiagnoser.cs)] | ||
|
||
### Output | ||
|
||
| Method | Mean | StdDev | Median | Completed Work Items | Lock Contentions | | ||
|-------------------- |--------------:|-----------:|--------------:|---------------------:|-----------------:| | ||
| CompleteOneWorkItem | 8,073.5519 ns | 69.7261 ns | 8,111.6074 ns | 1.0000 | - | | ||
|
||
### Links | ||
|
||
* @docs.diagnosers | ||
* The permanent link to this sample: @BenchmarkDotNet.Samples.IntroThreadingDiagnoser | ||
|
||
--- |
19 changes: 19 additions & 0 deletions
19
samples/BenchmarkDotNet.Samples/IntroThreadingDiagnoser.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
using BenchmarkDotNet.Attributes; | ||
using System.Threading; | ||
|
||
namespace BenchmarkDotNet.Samples | ||
{ | ||
[ThreadingDiagnoser] // ENABLE the diagnoser | ||
public class IntroThreadingDiagnoser | ||
{ | ||
[Benchmark] | ||
public void CompleteOneWorkItem() | ||
{ | ||
ManualResetEvent done = new ManualResetEvent(initialState: false); | ||
|
||
ThreadPool.QueueUserWorkItem(m => (m as ManualResetEvent).Set(), done); | ||
|
||
done.WaitOne(); | ||
} | ||
} | ||
} |
14 changes: 14 additions & 0 deletions
14
src/BenchmarkDotNet/Attributes/ThreadingDiagnoserAttribute.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
using System; | ||
using BenchmarkDotNet.Configs; | ||
using BenchmarkDotNet.Diagnosers; | ||
|
||
namespace BenchmarkDotNet.Attributes | ||
{ | ||
[AttributeUsage(AttributeTargets.Class)] | ||
public class ThreadingDiagnoserAttribute : Attribute, IConfigSource | ||
{ | ||
public IConfig Config { get; } | ||
|
||
public ThreadingDiagnoserAttribute() => Config = ManualConfig.CreateEmpty().With(ThreadingDiagnoser.Default); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using BenchmarkDotNet.Analysers; | ||
using BenchmarkDotNet.Columns; | ||
using BenchmarkDotNet.Engines; | ||
using BenchmarkDotNet.Exporters; | ||
using BenchmarkDotNet.Jobs; | ||
using BenchmarkDotNet.Loggers; | ||
using BenchmarkDotNet.Portability; | ||
using BenchmarkDotNet.Reports; | ||
using BenchmarkDotNet.Running; | ||
using BenchmarkDotNet.Toolchains.DotNetCli; | ||
using BenchmarkDotNet.Validators; | ||
|
||
namespace BenchmarkDotNet.Diagnosers | ||
{ | ||
public class ThreadingDiagnoser : IDiagnoser | ||
{ | ||
public static readonly ThreadingDiagnoser Default = new ThreadingDiagnoser(); | ||
|
||
private ThreadingDiagnoser() { } | ||
|
||
public IEnumerable<string> Ids => new[] { nameof(ThreadingDiagnoser) }; | ||
|
||
public IEnumerable<IExporter> Exporters => Array.Empty<IExporter>(); | ||
|
||
public IEnumerable<IAnalyser> Analysers => Array.Empty<IAnalyser>(); | ||
|
||
public void DisplayResults(ILogger logger) { } | ||
|
||
public RunMode GetRunMode(BenchmarkCase benchmarkCase) => RunMode.NoOverhead; | ||
|
||
public void Handle(HostSignal signal, DiagnoserActionParameters parameters) { } | ||
|
||
public IEnumerable<Metric> ProcessResults(DiagnoserResults results) | ||
{ | ||
yield return new Metric(CompletedWorkItemCountMetricDescriptor.Instance, results.ThreadingStats.CompletedWorkItemCount / (double)results.ThreadingStats.TotalOperations); | ||
yield return new Metric(LockContentionCountMetricDescriptor.Instance, results.ThreadingStats.LockContentionCount / (double)results.ThreadingStats.TotalOperations); | ||
} | ||
|
||
public IEnumerable<ValidationError> Validate(ValidationParameters validationParameters) | ||
{ | ||
if (!RuntimeInformation.IsNetCore || NetCoreAppSettings.Current.Value.IsOlderThan(TargetFrameworkMoniker.NetCoreApp30)) | ||
{ | ||
yield return new ValidationError(false, $"{nameof(ThreadingDiagnoser)} supports only .NET Core 3.0+"); | ||
} | ||
} | ||
|
||
private class CompletedWorkItemCountMetricDescriptor : IMetricDescriptor | ||
{ | ||
internal static readonly IMetricDescriptor Instance = new CompletedWorkItemCountMetricDescriptor(); | ||
|
||
public string Id => "CompletedWorkItemCount"; | ||
public string DisplayName => "Completed Work Items"; | ||
public string Legend => "The number of work items that have been processed in ThreadPool (per single operation)"; | ||
public string NumberFormat => "#0.0000"; | ||
public UnitType UnitType => UnitType.Dimensionless; | ||
public string Unit => "Count"; | ||
public bool TheGreaterTheBetter => false; | ||
} | ||
|
||
private class LockContentionCountMetricDescriptor : IMetricDescriptor | ||
{ | ||
internal static readonly IMetricDescriptor Instance = new LockContentionCountMetricDescriptor(); | ||
|
||
public string Id => "LockContentionCount"; | ||
public string DisplayName => "Lock Contentions"; | ||
public string Legend => "The number of times there was contention upon trying to take a Monitor's lock (per single operation)"; | ||
public string NumberFormat => "#0.0000"; | ||
public UnitType UnitType => UnitType.Dimensionless; | ||
public string Unit => "Count"; | ||
public bool TheGreaterTheBetter => false; | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.