Skip to content

Commit

Permalink
Continuous benchmarking (#152)
Browse files Browse the repository at this point in the history
  • Loading branch information
sungam3r authored Jan 9, 2024
1 parent ef85d3e commit 8d92080
Show file tree
Hide file tree
Showing 7 changed files with 170 additions and 0 deletions.
45 changes: 45 additions & 0 deletions .github/workflows/benchmarks.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
name: Continuous benchmarking
on:
pull_request:
branches:
- master
push:
branches:
- master

permissions:
contents: write
deployments: write

jobs:
benchmark:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- name: Setup .NET SDK
uses: actions/setup-dotnet@v4
with:
dotnet-version: 8.0.x

- name: Run benchmarks
working-directory: src/Benchmarks
run: dotnet run -c Release --exporters json --filter '*'

- name: Combine benchmarks results
working-directory: src/Benchmarks
run: dotnet tool install -g dotnet-script && dotnet script combine-bechmarks.csx

- name: Store benchmarks results
uses: benchmark-action/github-action-benchmark@v1
with:
name: SteroidsDI Benchmarks
tool: 'benchmarkdotnet'
output-file-path: src/Benchmarks/BenchmarkDotNet.Artifacts/results/Combined.Benchmarks.json
github-token: ${{ secrets.GITHUB_TOKEN }}
alert-threshold: '101%'
comment-on-alert: true
fail-on-alert: true
- name: Push benchmarks results
if: github.event_name != 'pull_request'
run: git push 'https://sungam3r:${{ secrets.GITHUB_TOKEN }}@github.com/sungam3r/SteroidsDI.git' gh-pages:gh-pages
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -430,3 +430,7 @@ await using (new Scoped<SomeClass>(scopeFactory)) // Scoped class supports IAsyn

Also see [ScopedTestBase](src/SteroidsDI.Tests/Cases/ScopedTestBase.cs) and [ScopedTestDerived](src/SteroidsDI.Tests/Cases/ScopedTestDerived.cs)
for more info. This example shows how you can add scope support to all unit tests.

## Benchmarks

The results are available [here](https://sungam3r.github.io/SteroidsDI/dev/bench/).
20 changes: 20 additions & 0 deletions src/Benchmarks/Benchmarks.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<NoWarn>$(NoWarn);1591</NoWarn>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="BenchmarkDotNet" Version="0.13.12" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\SteroidsDI.AspNetCore\SteroidsDI.AspNetCore.csproj" />
<ProjectReference Include="..\SteroidsDI\SteroidsDI.csproj" />
</ItemGroup>

</Project>
40 changes: 40 additions & 0 deletions src/Benchmarks/DeferBenchmarks.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
using BenchmarkDotNet.Attributes;
using Microsoft.Extensions.DependencyInjection;
using SteroidsDI;

namespace Benchmarks;

public class DeferBenchmarks
{
private sealed class Dependency
{
}

private IServiceProvider _provider = null!;

[GlobalSetup]
public void Setup()
{
var services = new ServiceCollection();
services
.Configure<ServiceProviderAdvancedOptions>(opt => opt.AllowRootProviderResolve = true)
.AddSingleton<Dependency>()
.AddDefer();

_provider = services.BuildServiceProvider();
}

[Benchmark]
public void ResolveDefer()
{
var defer = _provider.GetRequiredService<Defer<Dependency>>();
_ = defer.Value;
}

[Benchmark]
public void ResolveIDefer()
{
var defer = _provider.GetRequiredService<IDefer<Dependency>>();
_ = defer.Value;
}
}
11 changes: 11 additions & 0 deletions src/Benchmarks/Program.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
using BenchmarkDotNet.Configs;
using BenchmarkDotNet.Diagnosers;
using BenchmarkDotNet.Running;
using Benchmarks;

new DeferBenchmarks().Setup();
var config = ManualConfig
.Create(DefaultConfig.Instance)
.AddDiagnoser(MemoryDiagnoser.Default);

BenchmarkSwitcher.FromAssembly(typeof(Program).Assembly).Run(args, config);
43 changes: 43 additions & 0 deletions src/Benchmarks/combine-bechmarks.csx
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
using System.IO;
using System.Linq;
using System.Text.Json.Nodes;

string resultsDir = "./BenchmarkDotNet.Artifacts/results";
string resultsFile = "Combined.Benchmarks";
string searchPattern = "*-report-full-compressed.json";

var resultsPath = Path.Combine(resultsDir, resultsFile + ".json");

if (!Directory.Exists(resultsDir))
{
throw new DirectoryNotFoundException($"Directory not found '{resultsDir}'");
}

if (File.Exists(resultsPath))
{
File.Delete(resultsPath);
}

var reports = Directory.GetFiles(resultsDir, searchPattern, SearchOption.TopDirectoryOnly).ToArray();
if (!reports.Any())
{
throw new FileNotFoundException($"Reports not found '{searchPattern}'");
}

var combinedReport = JsonNode.Parse(File.ReadAllText(reports.First()))!;
var title = combinedReport["Title"]!;
var benchmarks = combinedReport["Benchmarks"]!.AsArray();
// Rename title whilst keeping original timestamp
combinedReport["Title"] = $"{resultsFile}{title.GetValue<string>()[^16..]}";

foreach (var report in reports.Skip(1))
{
var array = JsonNode.Parse(File.ReadAllText(report))!["Benchmarks"]!.AsArray();
foreach (var benchmark in array)
{
// Double parse avoids "The node already has a parent" exception
benchmarks.Add(JsonNode.Parse(benchmark!.ToJsonString())!);
}
}

File.WriteAllText(resultsPath, combinedReport.ToString());
7 changes: 7 additions & 0 deletions src/SteroidsDI.sln
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "ISSUE_TEMPLATE", "ISSUE_TEM
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "workflows", "workflows", "{0D490189-8C58-4B71-AB8D-5FBE973D0429}"
ProjectSection(SolutionItems) = preProject
..\.github\workflows\benchmarks.yml = ..\.github\workflows\benchmarks.yml
..\.github\workflows\codeql-analysis.yml = ..\.github\workflows\codeql-analysis.yml
..\.github\workflows\label.yml = ..\.github\workflows\label.yml
..\.github\workflows\publish-preview.yml = ..\.github\workflows\publish-preview.yml
Expand All @@ -48,6 +49,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "workflows", "workflows", "{
..\.github\workflows\test.yml = ..\.github\workflows\test.yml
EndProjectSection
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Benchmarks", "Benchmarks\Benchmarks.csproj", "{3A3F37A4-27BB-4A35-80A3-1973DDE6586B}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand All @@ -74,6 +77,10 @@ Global
{AAF4F983-A2CF-4E5F-9862-CAB7EC942850}.Debug|Any CPU.Build.0 = Debug|Any CPU
{AAF4F983-A2CF-4E5F-9862-CAB7EC942850}.Release|Any CPU.ActiveCfg = Release|Any CPU
{AAF4F983-A2CF-4E5F-9862-CAB7EC942850}.Release|Any CPU.Build.0 = Release|Any CPU
{3A3F37A4-27BB-4A35-80A3-1973DDE6586B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{3A3F37A4-27BB-4A35-80A3-1973DDE6586B}.Debug|Any CPU.Build.0 = Debug|Any CPU
{3A3F37A4-27BB-4A35-80A3-1973DDE6586B}.Release|Any CPU.ActiveCfg = Release|Any CPU
{3A3F37A4-27BB-4A35-80A3-1973DDE6586B}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand Down

0 comments on commit 8d92080

Please sign in to comment.