diff --git a/CHANGELOG.md b/CHANGELOG.md
index 92599bc..01c5d38 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -4,16 +4,18 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](http://keepachangelog.com/)
and this project adheres to [Semantic Versioning](http://semver.org/).
-## vNext
+## v2.2.0
### Added
- ThreadBehaviour to define how a thread is created
- Allow benchmarks to be run on the MainThread
+- OnExecuted to run a delegate after each task run
+- Trace - Edit TraceOptions as delegate
### Changed
- Added IDisposable to IThreadSessionHandler
### Fixed
--
+- Markdowntracer traced all data when using DetailPerThread
## v2.1.0
### Added
diff --git a/MeasureMap.sln b/MeasureMap.sln
index 456ca42..ad4829f 100644
--- a/MeasureMap.sln
+++ b/MeasureMap.sln
@@ -11,7 +11,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{C302527D
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{3BE4645D-C5EB-4675-AEE2-68BFE6AC84EB}"
ProjectSection(SolutionItems) = preProject
- .travis.yml = .travis.yml
appveyor.yml = appveyor.yml
.github\workflows\build.yml = .github\workflows\build.yml
CHANGELOG.md = CHANGELOG.md
@@ -21,7 +20,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "_build", "build\_build.csproj", "{364A83BE-EC1F-42DA-ACCB-69DE17631CF3}"
EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MeasureMap.Benchmark", "src\Tests\MeasureMap.Benchmark\MeasureMap.Benchmark.csproj", "{5BA1A434-30F8-4233-B4C1-A668AB50BC4B}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MeasureMap.Benchmark", "src\Tests\MeasureMap.Benchmark\MeasureMap.Benchmark.csproj", "{5BA1A434-30F8-4233-B4C1-A668AB50BC4B}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
diff --git a/README.md b/README.md
index b483718..e29aca7 100644
--- a/README.md
+++ b/README.md
@@ -1,9 +1,9 @@
# MeasureMap
.NET Benchmarking made simple
-[![Build Status](https://img.shields.io/travis/com/WickedFlame/MeasureMap/master.svg?label=Travis-CI&style=for-the-badge)](https://app.travis-ci.com/github/WickedFlame/MeasureMap)
[![Build status](https://img.shields.io/appveyor/build/chriswalpen/measuremap/master?label=Master&logo=appveyor&style=for-the-badge)](https://ci.appveyor.com/project/chriswalpen/measuremap/branch/master)
[![Build status](https://img.shields.io/appveyor/build/chriswalpen/measuremap/dev?label=Dev&logo=appveyor&style=for-the-badge)](https://ci.appveyor.com/project/chriswalpen/measuremap/branch/dev)
+
[![NuGet Version](https://img.shields.io/nuget/v/measuremap.svg?style=for-the-badge&label=Latest)](https://www.nuget.org/packages/measuremap/)
[![NuGet Version](https://img.shields.io/nuget/vpre/measuremap.svg?style=for-the-badge&label=RC)](https://www.nuget.org/packages/measuremap/)
@@ -11,11 +11,15 @@
[![Quality Gate Status](https://sonarcloud.io/api/project_badges/measure?project=WickedFlame_MeasureMap&metric=alert_status)](https://sonarcloud.io/summary/new_code?id=WickedFlame_MeasureMap)
[![Coverage](https://sonarcloud.io/api/project_badges/measure?project=WickedFlame_MeasureMap&metric=coverage)](https://sonarcloud.io/summary/new_code?id=WickedFlame_MeasureMap)
-Measuremap is a lightweight assembly that allows profiling and benchmarking code.
+Measuremap allows profiling and benchmarking from simple code fragmets to full applications.
Visit [https://wickedflame.github.io/MeasureMap/](https://wickedflame.github.io/MeasureMap/) for the full documentation.
-
+
+MeasureMap uses the builder pattern and a fluent API to make benchmarking as simple as possible.
+
## Profiling
+Profiles are initiated with ProfilerSession.StartSession().
+
```csharp
var result = ProfilerSession.StartSession()
.Task(() =>
@@ -34,6 +38,9 @@ Assert.IsTrue(result.AverageMilliseconds < 20);
## Benchmarking
+Benchmarks are a collection of ProfilerSessions.
+These are initiated and started with the BenchmarkRunner.
+
```csharp
var sha256 = SHA256.Create();
var md5 = MD5.Create();
diff --git a/appveyor.yml b/appveyor.yml
index 30f3492..18a8d5c 100644
--- a/appveyor.yml
+++ b/appveyor.yml
@@ -1,7 +1,7 @@
# http://www.appveyor.com/docs/appveyor-yml
environment:
- base_version: 2.1.0
+ base_version: 2.2.0
# version format
version: $(base_version).{build}
@@ -27,7 +27,7 @@ for:
- dotnet restore ./build/_build.csproj
build_script:
- - nuke Release --isrc true --version "%base_version%" --buildno "%APPVEYOR_BUILD_NUMBER%"
+ - nuke Release --isrc true --buildno "%APPVEYOR_BUILD_NUMBER%"
test: off
@@ -48,7 +48,7 @@ for:
- dotnet restore ./build/_build.csproj
build_script:
- - nuke Release --isrc false --version "%base_version%" --buildno "%APPVEYOR_BUILD_NUMBER%"
+ - nuke Release --isrc false --buildno "%APPVEYOR_BUILD_NUMBER%" --version $(base_version)
test: off
diff --git a/build/Build.cs b/build/Build.cs
index 7e8c8c2..cb1a621 100644
--- a/build/Build.cs
+++ b/build/Build.cs
@@ -38,7 +38,7 @@ class Build : NukeBuild
[GitRepository] readonly GitRepository GitRepository;
[Parameter("Version to be injected in the Build")]
- public string Version { get; set; } = $"2.1.0";
+ public string Version { get; set; } = $"2.1.1";
[Parameter("The Buildnumber provided by the CI")]
public int BuildNo = 6;
diff --git a/src/MeasureMap/ProfilerResultExtensions.cs b/src/MeasureMap/ProfilerResultExtensions.cs
index 0271af8..5f5c9e2 100644
--- a/src/MeasureMap/ProfilerResultExtensions.cs
+++ b/src/MeasureMap/ProfilerResultExtensions.cs
@@ -95,6 +95,19 @@ public static void Trace(this IProfilerResult result, TraceOptions options)
result.Trace(options.Tracer, options.ResultWriter, options);
}
+ ///
+ /// Trace the output of a Profiler
+ ///
+ ///
+ ///
+ public static void Trace(this IProfilerResult result, Action factory)
+ {
+ var options = TraceOptions.Default.Clone();
+ factory.Invoke(options);
+
+ result.Trace(options);
+ }
+
///
/// Trace the output of a Profiler
///
diff --git a/src/MeasureMap/ProfilerSessionExtensions.cs b/src/MeasureMap/ProfilerSessionExtensions.cs
index 01cd946..3fc464b 100644
--- a/src/MeasureMap/ProfilerSessionExtensions.cs
+++ b/src/MeasureMap/ProfilerSessionExtensions.cs
@@ -1,6 +1,7 @@
using System;
using MeasureMap.Diagnostics;
using MeasureMap.Runners;
+using MeasureMap.TaskHandlers;
namespace MeasureMap
{
@@ -298,6 +299,18 @@ public static ProfilerSession SetMinLogLevel(this ProfilerSession session, LogLe
return session;
}
+ ///
+ /// Add a delegate that is run after the task is executed. It is possible to add multiple delegates by calling this method multiple times
+ ///
+ ///
+ ///
+ ///
+ public static ProfilerSession OnExecuted(this ProfilerSession session, Action execution)
+ {
+ session.ProcessingPipeline.SetNext(new OnExecutedTaskHandler(execution));
+ return session;
+ }
+
internal static ProfilerSession AppendSettings(this ProfilerSession session, ProfilerSettings settings)
{
session.SetMinLogLevel(settings.Logger.MinLogLevel);
diff --git a/src/MeasureMap/TaskHandlers/OnExecutedTaskHandler.cs b/src/MeasureMap/TaskHandlers/OnExecutedTaskHandler.cs
new file mode 100644
index 0000000..590ed61
--- /dev/null
+++ b/src/MeasureMap/TaskHandlers/OnExecutedTaskHandler.cs
@@ -0,0 +1,35 @@
+using System;
+
+namespace MeasureMap.TaskHandlers
+{
+ ///
+ /// TaskHandler that executes a delegate after the taskrun
+ ///
+ public class OnExecutedTaskHandler : TaskHandler
+ {
+ private readonly Action _execution;
+
+ ///
+ ///
+ ///
+ ///
+ public OnExecutedTaskHandler(Action execution)
+ {
+ _execution = execution;
+ }
+
+ ///
+ /// Executes the task
+ ///
+ /// The current execution context
+ /// The resulting collection of the executions
+ public override IIterationResult Run(IExecutionContext context)
+ {
+ var result = base.Run(context);
+
+ System.Threading.Tasks.Task.Run(() => _execution.Invoke(result));
+
+ return result;
+ }
+ }
+}
diff --git a/src/MeasureMap/Tracers/MarkDownTracer.cs b/src/MeasureMap/Tracers/MarkDownTracer.cs
index 272ecb3..965180d 100644
--- a/src/MeasureMap/Tracers/MarkDownTracer.cs
+++ b/src/MeasureMap/Tracers/MarkDownTracer.cs
@@ -75,7 +75,7 @@ public void Trace(IProfilerResult result, IResultWriter writer, TraceOptions opt
}
}
- if (options.TraceDetail >= TraceDetail.DetailPerThread)
+ if (options.TraceDetail > TraceDetail.DetailPerThread)
{
writer.WriteLine(string.Empty);
writer.WriteLine("## Details per Iteration and Thread");
diff --git a/src/Tests/MeasureMap.UnitTest/ProfileSessionTests.cs b/src/Tests/MeasureMap.UnitTest/ProfileSessionTests.cs
index 6f947c6..501ab28 100644
--- a/src/Tests/MeasureMap.UnitTest/ProfileSessionTests.cs
+++ b/src/Tests/MeasureMap.UnitTest/ProfileSessionTests.cs
@@ -656,6 +656,59 @@ public void ProfileSession_SetExecutionHandler()
mock.Verify(x => x.Execute(It.IsAny(), It.IsAny()));
}
+ [Test]
+ public void ProfileSession_OnExecuted()
+ {
+ var calls = 0;
+
+ ProfilerSession.StartSession()
+ .SetIterations(5)
+ .RunWarmup(false)
+ .OnExecuted(r => calls++)
+ .Task(() => { })
+ .RunSession();
+
+ calls.Should().Be(5);
+ }
+
+ [Test]
+ public void ProfileSession_OnExecuted_Warmup()
+ {
+ var calls = 0;
+
+ ProfilerSession.StartSession()
+ .OnExecuted(r => calls++)
+ .Task(() => { })
+ .RunSession();
+
+ calls.Should().Be(2);
+ }
+
+ [Test]
+ public void ProfileSession_OnExecuted_IIterationResult()
+ {
+ ProfilerSession.StartSession()
+ .OnExecuted(r => r.Should().BeAssignableTo())
+ .Task(() => { })
+ .RunSession();
+ }
+
+ [Test]
+ public void ProfileSession_OnExecuted_MultipleRegistrations()
+ {
+ var first = 0;
+ var second = 0;
+
+ ProfilerSession.StartSession()
+ .OnExecuted(r => first++)
+ .OnExecuted(r => second++)
+ .Task(() => { })
+ .RunSession();
+
+ first.Should().Be(2);
+ second.Should().Be(2);
+ }
+
private void Task()
{
System.Threading.Thread.Sleep(TimeSpan.FromSeconds(0.002));
diff --git a/src/Tests/MeasureMap.UnitTest/Tracers/TracerTests.cs b/src/Tests/MeasureMap.UnitTest/Tracers/TracerTests.cs
index 2c38e8a..153c811 100644
--- a/src/Tests/MeasureMap.UnitTest/Tracers/TracerTests.cs
+++ b/src/Tests/MeasureMap.UnitTest/Tracers/TracerTests.cs
@@ -1,4 +1,6 @@
-using System.Text;
+using System;
+using System.Text;
+using FluentAssertions;
using MeasureMap.Tracers;
using NUnit.Framework;
using Polaroider;
@@ -122,6 +124,33 @@ public void Tracer_Profiler_Options()
((StringResultWriter)options.ResultWriter).Value.MatchSnapshot();
}
+
+ [Test]
+ public void Tracer_Profiler_Options_Delegate()
+ {
+ TraceOptions options = null;
+
+ var result = ResultFactory.CreateResult();
+
+ result.Trace(o =>
+ {
+ o.ResultWriter = new StringResultWriter();
+ o.Tracer = new MarkDownTracer();
+ options = o;
+ });
+
+ ((StringResultWriter)options.ResultWriter).Value.MatchSnapshot();
+ }
+
+ [Test]
+ public void Tracer_Profiler_Options_Delegate_Simple()
+ {
+ var result = ResultFactory.CreateResult();
+
+ Action action = () => result.Trace(o => o.TraceDetail = TraceDetail.DetailPerThread);
+
+ action.Should().NotThrow();
+ }
}
public class StringResultWriter : IResultWriter
diff --git a/src/Tests/MeasureMap.UnitTest/Tracers/_Snapshots/MarkDownTracerTests_MarkDownTracer_ProfilerResult_DetailPerThread.snapshot b/src/Tests/MeasureMap.UnitTest/Tracers/_Snapshots/MarkDownTracerTests_MarkDownTracer_ProfilerResult_DetailPerThread.snapshot
index 15c6dcd..460d6a5 100644
--- a/src/Tests/MeasureMap.UnitTest/Tracers/_Snapshots/MarkDownTracerTests_MarkDownTracer_ProfilerResult_DetailPerThread.snapshot
+++ b/src/Tests/MeasureMap.UnitTest/Tracers/_Snapshots/MarkDownTracerTests_MarkDownTracer_ProfilerResult_DetailPerThread.snapshot
@@ -23,27 +23,3 @@
| 1 | 10 | 00:00:00.0000013 | 00:00:00.0000018 | 00:00:00.0000009 | 740740.74074/s |
| 2 | 10 | 00:00:00.0000013 | 00:00:00.0000018 | 00:00:00.0000009 | 740740.74074/s |
-## Details per Iteration and Thread
-| ThreadId | Iteration | TimeStamp | Milliseconds |
-| -------- | --------- | --------------------------- | -----------: |
-| 1 | 1 | 2012-12-21T01:01:01.0010001 | 0.0018 ms |
-| 2 | 1 | 2012-12-21T01:01:01.0010001 | 0.0018 ms |
-| 1 | 2 | 2012-12-21T01:01:01.0010002 | 0.0017 ms |
-| 2 | 2 | 2012-12-21T01:01:01.0010002 | 0.0017 ms |
-| 1 | 3 | 2012-12-21T01:01:01.0010003 | 0.0016 ms |
-| 2 | 3 | 2012-12-21T01:01:01.0010003 | 0.0016 ms |
-| 1 | 4 | 2012-12-21T01:01:01.0010004 | 0.0015 ms |
-| 2 | 4 | 2012-12-21T01:01:01.0010004 | 0.0015 ms |
-| 1 | 5 | 2012-12-21T01:01:01.0010005 | 0.0014 ms |
-| 2 | 5 | 2012-12-21T01:01:01.0010005 | 0.0014 ms |
-| 1 | 6 | 2012-12-21T01:01:01.0010006 | 0.0013 ms |
-| 2 | 6 | 2012-12-21T01:01:01.0010006 | 0.0013 ms |
-| 1 | 7 | 2012-12-21T01:01:01.0010007 | 0.0012 ms |
-| 2 | 7 | 2012-12-21T01:01:01.0010007 | 0.0012 ms |
-| 1 | 8 | 2012-12-21T01:01:01.0010008 | 0.0011 ms |
-| 2 | 8 | 2012-12-21T01:01:01.0010008 | 0.0011 ms |
-| 1 | 9 | 2012-12-21T01:01:01.0010009 | 0.001 ms |
-| 2 | 9 | 2012-12-21T01:01:01.0010009 | 0.001 ms |
-| 1 | 10 | 2012-12-21T01:01:01.0010010 | 0.0009 ms |
-| 2 | 10 | 2012-12-21T01:01:01.0010010 | 0.0009 ms |
-
diff --git a/src/Tests/MeasureMap.UnitTest/Tracers/_Snapshots/MetricsTests_Metrics_Profiler_Detailed.snapshot b/src/Tests/MeasureMap.UnitTest/Tracers/_Snapshots/MetricsTests_Metrics_Profiler_Detailed.snapshot
index 15c6dcd..460d6a5 100644
--- a/src/Tests/MeasureMap.UnitTest/Tracers/_Snapshots/MetricsTests_Metrics_Profiler_Detailed.snapshot
+++ b/src/Tests/MeasureMap.UnitTest/Tracers/_Snapshots/MetricsTests_Metrics_Profiler_Detailed.snapshot
@@ -23,27 +23,3 @@
| 1 | 10 | 00:00:00.0000013 | 00:00:00.0000018 | 00:00:00.0000009 | 740740.74074/s |
| 2 | 10 | 00:00:00.0000013 | 00:00:00.0000018 | 00:00:00.0000009 | 740740.74074/s |
-## Details per Iteration and Thread
-| ThreadId | Iteration | TimeStamp | Milliseconds |
-| -------- | --------- | --------------------------- | -----------: |
-| 1 | 1 | 2012-12-21T01:01:01.0010001 | 0.0018 ms |
-| 2 | 1 | 2012-12-21T01:01:01.0010001 | 0.0018 ms |
-| 1 | 2 | 2012-12-21T01:01:01.0010002 | 0.0017 ms |
-| 2 | 2 | 2012-12-21T01:01:01.0010002 | 0.0017 ms |
-| 1 | 3 | 2012-12-21T01:01:01.0010003 | 0.0016 ms |
-| 2 | 3 | 2012-12-21T01:01:01.0010003 | 0.0016 ms |
-| 1 | 4 | 2012-12-21T01:01:01.0010004 | 0.0015 ms |
-| 2 | 4 | 2012-12-21T01:01:01.0010004 | 0.0015 ms |
-| 1 | 5 | 2012-12-21T01:01:01.0010005 | 0.0014 ms |
-| 2 | 5 | 2012-12-21T01:01:01.0010005 | 0.0014 ms |
-| 1 | 6 | 2012-12-21T01:01:01.0010006 | 0.0013 ms |
-| 2 | 6 | 2012-12-21T01:01:01.0010006 | 0.0013 ms |
-| 1 | 7 | 2012-12-21T01:01:01.0010007 | 0.0012 ms |
-| 2 | 7 | 2012-12-21T01:01:01.0010007 | 0.0012 ms |
-| 1 | 8 | 2012-12-21T01:01:01.0010008 | 0.0011 ms |
-| 2 | 8 | 2012-12-21T01:01:01.0010008 | 0.0011 ms |
-| 1 | 9 | 2012-12-21T01:01:01.0010009 | 0.001 ms |
-| 2 | 9 | 2012-12-21T01:01:01.0010009 | 0.001 ms |
-| 1 | 10 | 2012-12-21T01:01:01.0010010 | 0.0009 ms |
-| 2 | 10 | 2012-12-21T01:01:01.0010010 | 0.0009 ms |
-
diff --git a/src/Tests/MeasureMap.UnitTest/Tracers/_Snapshots/TracerTests_Tracer_Profiler_Options_Delegate.snapshot b/src/Tests/MeasureMap.UnitTest/Tracers/_Snapshots/TracerTests_Tracer_Profiler_Options_Delegate.snapshot
new file mode 100644
index 0000000..a98efd7
--- /dev/null
+++ b/src/Tests/MeasureMap.UnitTest/Tracers/_Snapshots/TracerTests_Tracer_Profiler_Options_Delegate.snapshot
@@ -0,0 +1,19 @@
+---data
+# MeasureMap - Profiler result
+## Summary
+| Category | Metric | Value |
+| :------- | :---------------- | ---------------: |
+| Warmup | Duration Warmup | 00:00:00 |
+| Setup | Threads | 2 |
+| | Iterations | 20 |
+| Duration | Duration | 00:00:00.0000270 |
+| | Total Time | 00:00:00.0000270 |
+| | Avg. Time | 00:00:00.0000013 |
+| | Avg. Milliseconds | 0.0013 ms |
+| | Throughput | 740740.74074/s |
+| | Fastest | 00:00:00.0000009 |
+| | Slowest | 00:00:00.0000018 |
+| Memory | Memory init size | 0 |
+| | Memory end size | 0 |
+| | Memory increase | 0 |
+