Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Export benchmark results #8

Merged
merged 46 commits into from
May 30, 2024
Merged
Show file tree
Hide file tree
Changes from 38 commits
Commits
Show all changes
46 commits
Select commit Hold shift + click to select a range
d18243d
Add skeleton project structure.
atmoos Mar 24, 2024
82c8c4b
Map the summery to GlassView types.
atmoos Mar 25, 2024
afa106a
Add statistics & gc stats to model.
atmoos Mar 25, 2024
e58e9c9
Complete first version of DTO impls.
atmoos Mar 26, 2024
7b8b9d2
separate types out into dedicated files.
atmoos Mar 26, 2024
aacdfd9
Add exporter.
atmoos Mar 26, 2024
7da20dc
First export attempts.
atmoos Mar 27, 2024
8ac0722
Full serialization of benchmark data.
atmoos Mar 27, 2024
2fb9186
complete serialization
atmoos Mar 27, 2024
29462b8
Minor cleanup
atmoos Mar 27, 2024
4532290
Use map functions to build the benchmark summary export.
atmoos Apr 8, 2024
8591bb2
Apply simple changes from PR.
atmoos May 4, 2024
cc85e04
Move serialization to core.
atmoos May 4, 2024
90add55
Add (failing) test for serialization of benchmarks.
atmoos May 4, 2024
fd9a0f0
Have deserialization succeed.
atmoos May 4, 2024
ea6804b
Change all our models to records.
atmoos May 4, 2024
9c6aafd
Have all models be immutable.
atmoos May 4, 2024
2956804
Enable the use of app settings.
atmoos May 10, 2024
c150840
Fix naming
atmoos May 10, 2024
fe62e68
Optimise directory export impl.
atmoos May 10, 2024
e7110e3
Use buildprops everywhere.
atmoos May 16, 2024
1bd261f
Mention issue in mappings.
atmoos May 16, 2024
37c563b
Use Atmoos prefix for root namespace.
atmoos May 16, 2024
2542b27
Fix failing unit tests that fail due to line endings.
atmoos May 16, 2024
6109c28
Add json formatting to configuration options.
atmoos May 16, 2024
4682927
Fix failing unit test.
atmoos May 16, 2024
f9689c7
sanitize path in glass view tests.
atmoos May 16, 2024
9d37142
Add default export & emit log statements.
atmoos May 16, 2024
f684a70
Fix windows issue.
atmoos May 16, 2024
fa62f0d
Ensure benchmark results are exported to sensible directory.
atmoos May 16, 2024
e37433c
Final touches.
atmoos May 16, 2024
e408147
Add initial design document.
atmoos May 16, 2024
efbaaea
Add hardware intrinsics & parameters.
atmoos May 16, 2024
19b42cf
Clean up handling of json formatting options.
atmoos May 17, 2024
72dede4
Incorporate review findings
atmoos May 17, 2024
3d84e95
Have testable exporters & better log output.
atmoos May 17, 2024
bad339d
Test that configured directory extists.
atmoos May 20, 2024
84ff09d
Update README.md
atmoos May 20, 2024
6a7afbc
Clean-up benchmark scenarios.
atmoos May 21, 2024
579a933
Make the benchmark 'categories' obvious.
atmoos May 21, 2024
903c3b1
Remove last remaining assembly attribute.
atmoos May 24, 2024
e779c6e
Move Parameter into dedicated file.
atmoos May 24, 2024
1cc405a
Greatly simplify the benchmark serializer.
atmoos May 28, 2024
7c99197
Improve readability of serialization tests.
atmoos May 28, 2024
6c826e1
Clarify the record comparison situation.
atmoos May 29, 2024
6c15e4f
Improve wording in README.
atmoos May 29, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
84 changes: 82 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,82 @@
# BenchView
A solution to view and keep track of benchmarking results in C#
# GlassView

A solution to view and keep track of benchmarking results of dotnet projects.

This is still a project very much in it's infancy. But when it matures, it is supposed to export [BenchmarkDotNet](https://github.com/dotnet/BenchmarkDotNet) results such that they can be tracked over time. This should - if all goes according to plans -- allow teams to keep track of the performance characteristics of a project. Just as many teams already do with correctness and quality aspects by keeping trach of test results (coverage) and code quality metrics.
sereneowl marked this conversation as resolved.
Show resolved Hide resolved

## Vision

The end product should be some interactive web interface that can run "anywhere" which enables analysis of your benchmark results.

- [ ] Export benchmark results as json to some local directory.
- [x] Via a library (ToDo #12: nuget pending)
- [ ] Completely decoupled without any dll dependencies
- [ ] Ingestion into some service(?) that creates (static) views.
- [ ] Interactive web interface.
- [ ] IDE integration (Visual Studio Code)?
- [ ] Statistics suite with which,
sereneowl marked this conversation as resolved.
Show resolved Hide resolved
- [ ] simple queries against past runs can be issued.
- [ ] regressions and trends can be detected and visualised
- [ ] Integration into Ci/Cd systems (pipelines)

For a complete and more detailed list, please check out our [issues](https://github.com/atmoos/GlassView/issues).

## Current Set-Up

Reference the nuget package `Atmoos.GlassView.Export` and modify your benchmarking project as follows:

```csharp
/* in: YourProject/Program.cs */
// other usings...
using Atmoos.GlassView.Export;
using Microsoft.Extensions.Configuration;

var configuration = new ConfigurationBuilder().AddJsonFile("appsettings.json").Build();

IGlassView exporter = GlassView.Configure(configuration);

// dotnet run -c Release --project 'YourProject/'
var summary = BenchmarkSwitcher.FromAssembly(typeof(Program).Assembly).Run(args);

await exporter.Export(summary);
```

## Configuration

[Configuration](https://github.com/atmoos/GlassView/blob/main/source/GlassView.Export/Configuration/Configuration.cs) allows for optional configuration of:

- The export directory.
- Json formatting options.

Without any configuration, the benchmark results are exported to `./BenchmarkDotNet.Artifacts/GlassView/`.

A minimal `GlassView` configuration section might look something like this:

```json
{
"GlassView": {
"Export": {
"Directory": {
"Path": "Your/Export/Directory/"
}
}
}
}
```

## Quick Start

If you just want to get going and manually want to check for exported data, you can do so by using a `Program.cs` similar to this:

```csharp
/* in: YourProject/Program.cs */
// other usings...
using Atmoos.GlassView.Export;

IGlassView exporter = GlassView.Default(); // exports to ./BenchmarkDotNet.Artifacts/GlassView/

// dotnet run -c Release --project 'YourProject/'
var summary = BenchmarkSwitcher.FromAssembly(typeof(Program).Assembly).Run(args);

await exporter.Export(summary);
```
35 changes: 34 additions & 1 deletion documentation/Design.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,37 @@
# BenchView Design

**ToDo**
```mermaid
---
title: High Level Dependency Graph
---
classDiagram
Core <.. Services
Core <.. Export
Export <.. Benchmark
Library <.. Benchmark
namespace AtmoosGlassView {
class Core{
+ Models
+Serialization()
}
class Services{
+Run(config)
}
class Export{
+Export(summary, config)
}
}

namespace User {
class Library{
+ Shared
}
class Benchmark{
~RunBenchmark()
}
}
note for Core "Library of shared\ntypes between <b>Export</b>\nand <b>Services</b>"
note for Services "Any service needed\nto realize tracking of\nbenchmarks."
note for Export "User configures how the\nexport of their benchmarks\nis to happen. Configured\nvia appsettings.json"
note for Benchmark "User benchmarking project of <b>Library</b>."
```
35 changes: 35 additions & 0 deletions source/GlassView.Benchmark/GlassView.Benchmark.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="../GlassView.Build.props" />

<PropertyGroup>
<OutputType>Exe</OutputType>
</PropertyGroup>

<PropertyGroup>
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugType>pdbonly</DebugType>
<DebugSymbols>true</DebugSymbols>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<Optimize>true</Optimize>
<Configuration>Release</Configuration>
<IsPackable>false</IsPackable>
<!-- Not bothering about null is handy for benchmarking projects... -->
<Nullable>disable</Nullable>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="BenchmarkDotNet" Version="0.13.12" />
<PackageReference Include="BenchmarkDotNet.Diagnostics.Windows" Version="0.13.12" Condition="'$(OS)' == 'Windows_NT'" />
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="8.0.0" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\GlassView.Export\GlassView.Export.csproj" />
<ProjectReference Include="..\GlassView.Core\GlassView.Core.csproj" />
</ItemGroup>

<ItemGroup>
<None Update="appsettings.json" CopyToOutputDirectory="PreserveNewest" />
</ItemGroup>

</Project>
19 changes: 19 additions & 0 deletions source/GlassView.Benchmark/OtherTestBenchmark.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
using System;
using System.Linq;
using BenchmarkDotNet.Attributes;

namespace Atmoos.GlassView.Benchmark;

[ShortRunJob]
[IterationCount(7)]
[MemoryDiagnoser]
public class OtherTestBenchmark
{
private const Int32 count = 8096;

[Benchmark(Baseline = true), BenchmarkCategory("SomeCat")]
public void SumStrings() => Thread.Sleep(7);
sereneowl marked this conversation as resolved.
Show resolved Hide resolved

[Benchmark, BenchmarkCategory("OtherCat")]
public void SumChars() => Thread.Sleep(9);
}
20 changes: 20 additions & 0 deletions source/GlassView.Benchmark/Program.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
using BenchmarkDotNet.Columns;
using BenchmarkDotNet.Configs;
using BenchmarkDotNet.Running;
using Microsoft.Extensions.Configuration;
using Atmoos.GlassView.Export;

using static BenchmarkDotNet.Columns.StatisticColumn;

var configuration = new ConfigurationBuilder()
.AddJsonFile("appsettings.json", optional: false, reloadOnChange: false)
.Build();

IGlassView exporter = GlassView.Configure(configuration);

// dotnet run -c Release --project GlassView.Benchmark/
var config = DefaultConfig.Instance.HideColumns(StdDev, Median, Kurtosis, BaselineRatioColumn.RatioStdDev);

var summary = BenchmarkSwitcher.FromAssembly(typeof(Program).Assembly).Run(args, config);

await exporter.Export(summary).ConfigureAwait(ConfigureAwaitOptions.None);
22 changes: 22 additions & 0 deletions source/GlassView.Benchmark/TestBenchmark.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
using System;
using System.Linq;
using BenchmarkDotNet.Attributes;

namespace Atmoos.GlassView.Benchmark;

[ShortRunJob]
[IterationCount(7)]
[MemoryDiagnoser]
public class TestBenchmark
{
[Params(54, 42)]
public Int32 Count { get; set; }

[Benchmark(Baseline = true), BenchmarkCategory("SomeCat")]
public Int32 SumIntegers() => Integers(Count).Sum();

[Benchmark, BenchmarkCategory("OtherCat")]
public Double SumDoubles() => Doubles(Count).Sum();
private static Double[] Doubles(Int32 count) => Enumerable.Range(0, count).Select(i => i - count / 2d).ToArray();
private static Int32[] Integers(Int32 count) => Enumerable.Range(0, count).Select(i => i - count / 2).ToArray();
}
12 changes: 12 additions & 0 deletions source/GlassView.Benchmark/appsettings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"GlassView": {
"Export": {
"JsonFormatting": {
"Indented": true
},
"Directory": {
"Path": "BenchmarkDotNet.Artifacts/GlassView/"
}
}
}
}
13 changes: 13 additions & 0 deletions source/GlassView.Build.props
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<Project>

<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>

<ItemGroup Condition="$(IsPackable)">
<InternalsVisibleTo Include="$(AssemblyName).Test" />
</ItemGroup>

</Project>
11 changes: 11 additions & 0 deletions source/GlassView.Core.Test/Convenience.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
using System.Text.Json;

namespace Atmoos.GlassView.Core.Test;

public static class Convenience
{
private static readonly JsonSerializerOptions options = new JsonSerializerOptions() { WriteIndented = true }.EnableGlassView();

public static String Serialize<T>(this T value) => JsonSerializer.Serialize(value, options);
sereneowl marked this conversation as resolved.
Show resolved Hide resolved
public static T Deserialize<T>(this String json) => JsonSerializer.Deserialize<T>(json, options) ?? throw new ArgumentException("Deserialization failed.", nameof(json));
}
17 changes: 17 additions & 0 deletions source/GlassView.Core.Test/GlassView.Core.Test.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="../GlassView.Build.props" />
<Import Project="../GlassView.Test.props" />

<PropertyGroup>
<RootNamespace>Atmoos.GlassView.Core.Test</RootNamespace>
</PropertyGroup>

<ItemGroup>
<ProjectReference Include="..\GlassView.Core\GlassView.Core.csproj" />
</ItemGroup>

<ItemGroup>
<None Update="Resources\TestBenchmark.json" CopyToOutputDirectory="PreserveNewest" />
</ItemGroup>

</Project>
1 change: 1 addition & 0 deletions source/GlassView.Core.Test/GlobalUsings.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
global using Xunit;
Loading