Skip to content

Commit c974fed

Browse files
Added benchmarking and updated readme
1 parent 89928da commit c974fed

File tree

11 files changed

+266
-7
lines changed

11 files changed

+266
-7
lines changed

Hyperbee.Pipeline.sln

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Hyperbee.Pipeline.Auth", "s
4949
EndProject
5050
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Hyperbee.Pipeline.Auth.Tests", "test\Hyperbee.Pipeline.Auth.Tests\Hyperbee.Pipeline.Auth.Tests.csproj", "{3E5F6864-2BAD-4349-8C7A-D199A715FA3C}"
5151
EndProject
52+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Hyperbee.Pipeline.Benchmark", "test\Hyperbee.Pipleline.Benchmark\Hyperbee.Pipeline.Benchmark.csproj", "{4117A842-A068-41DD-AA16-AE158025EA9A}"
53+
EndProject
5254
Global
5355
GlobalSection(SolutionConfigurationPlatforms) = preSolution
5456
Debug|Any CPU = Debug|Any CPU
@@ -79,6 +81,10 @@ Global
7981
{3E5F6864-2BAD-4349-8C7A-D199A715FA3C}.Debug|Any CPU.Build.0 = Debug|Any CPU
8082
{3E5F6864-2BAD-4349-8C7A-D199A715FA3C}.Release|Any CPU.ActiveCfg = Release|Any CPU
8183
{3E5F6864-2BAD-4349-8C7A-D199A715FA3C}.Release|Any CPU.Build.0 = Release|Any CPU
84+
{4117A842-A068-41DD-AA16-AE158025EA9A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
85+
{4117A842-A068-41DD-AA16-AE158025EA9A}.Debug|Any CPU.Build.0 = Debug|Any CPU
86+
{4117A842-A068-41DD-AA16-AE158025EA9A}.Release|Any CPU.ActiveCfg = Release|Any CPU
87+
{4117A842-A068-41DD-AA16-AE158025EA9A}.Release|Any CPU.Build.0 = Release|Any CPU
8288
EndGlobalSection
8389
GlobalSection(SolutionProperties) = preSolution
8490
HideSolutionNode = FALSE
@@ -90,6 +96,7 @@ Global
9096
{884A8242-351E-4363-9B34-E8C202CF7787} = {870D9301-BE3D-44EA-BF9C-FCC2E87FE4CD}
9197
{B7E5FBB3-AF2A-4E48-8E6A-10887DC6C4C0} = {F9B24CD9-E06B-4834-84CB-8C29E5F10BE0}
9298
{3E5F6864-2BAD-4349-8C7A-D199A715FA3C} = {F9B24CD9-E06B-4834-84CB-8C29E5F10BE0}
99+
{4117A842-A068-41DD-AA16-AE158025EA9A} = {F9B24CD9-E06B-4834-84CB-8C29E5F10BE0}
93100
EndGlobalSection
94101
GlobalSection(ExtensibilityGlobals) = postSolution
95102
SolutionGuid = {32874F5B-B467-4F28-A8E2-82C2536FB228}

README.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,10 @@ Classes for building composable async pipelines supporting:
181181
| `main` | [![Build status](https://github.com/Stillpoint-Software/Hyperbee.Pipeline/actions/workflows/publish.yml/badge.svg)](https://github.com/Stillpoint-Software/Hyperbee.Pipeline/actions/workflows/publish.yml) |
182182

183183

184+
185+
# Benchmarks
186+
See [Benchmarks](https://github.com/Stillpoint-Software/Hyperbee.Pipeline/test/Hyperbee.Pipeline.Benchmark/benchmark/results/Hyperbee.Pipeline.Benchmark.PipelineBenchmarks-report-github.md)
187+
184188
# Help
185189
See our list of items [Todo](https://github.com/Stillpoint-Software/Hyperbee.Pipeline/blob/main/docs/todo.md)
186190

src/Hyperbee.Pipeline.Auth/Hyperbee.Pipeline.Auth.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@
3232
<Pack>True</Pack>
3333
<PackagePath>\</PackagePath>
3434
</None>
35-
<PackageReference Include="Microsoft.AspNetCore.Http.Connections.Common" Version="8.0.4" />
35+
<PackageReference Include="Microsoft.AspNetCore.Http.Connections.Common" Version="8.0.6" />
3636
<ProjectReference Include="..\Hyperbee.Pipeline\Hyperbee.Pipeline.csproj" />
3737
<PackageReference Update="Microsoft.SourceLink.GitHub" Version="8.0.0">
3838
<PrivateAssets>all</PrivateAssets>

test/Hyperbee.Pipeline.Auth.Tests/Hyperbee.Pipeline.Auth.Tests.csproj

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,9 @@
1414
<PrivateAssets>all</PrivateAssets>
1515
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
1616
</PackageReference>
17-
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.9.0" />
18-
<PackageReference Include="MSTest.TestAdapter" Version="3.3.1" />
19-
<PackageReference Include="MSTest.TestFramework" Version="3.3.1" />
17+
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.10.0" />
18+
<PackageReference Include="MSTest.TestAdapter" Version="3.4.3" />
19+
<PackageReference Include="MSTest.TestFramework" Version="3.4.3" />
2020
<PackageReference Include="NSubstitute" Version="5.1.0" />
2121
</ItemGroup>
2222

test/Hyperbee.Pipeline.Tests/Hyperbee.Pipeline.Tests.csproj

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,9 @@
44
<IsPackable>false</IsPackable>
55
</PropertyGroup>
66
<ItemGroup>
7-
<PackageReference Include="MSTest.TestAdapter" Version="3.4.1" />
7+
<PackageReference Include="MSTest.TestAdapter" Version="3.4.3" />
88
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.10.0" />
9+
<PackageReference Include="MSTest.TestFramework" Version="3.4.3" />
910
</ItemGroup>
1011
<ItemGroup>
1112
<ProjectReference Include="..\..\src\Hyperbee.Pipeline\Hyperbee.Pipeline.csproj" />

test/Hyperbee.PipelineCaching.Tests/Hyperbee.Pipeline.Caching.Tests.csproj

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,9 @@
1515
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
1616
</PackageReference>
1717
<PackageReference Include="Microsoft.Extensions.Caching.Memory" Version="8.0.0" />
18-
<PackageReference Include="MSTest.TestAdapter" Version="3.4.1" />
18+
<PackageReference Include="MSTest.TestAdapter" Version="3.4.3" />
1919
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.10.0" />
20-
<PackageReference Include="MSTest.TestFramework" Version="3.4.0" />
20+
<PackageReference Include="MSTest.TestFramework" Version="3.4.3" />
2121
<PackageReference Include="NSubstitute" Version="5.1.0" />
2222
</ItemGroup>
2323

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
using BenchmarkDotNet.Columns;
2+
using BenchmarkDotNet.Configs;
3+
using BenchmarkDotNet.Diagnosers;
4+
using BenchmarkDotNet.Exporters;
5+
using BenchmarkDotNet.Jobs;
6+
using BenchmarkDotNet.Loggers;
7+
using BenchmarkDotNet.Order;
8+
using BenchmarkDotNet.Validators;
9+
10+
namespace Hyperbee.Pipeline.Benchmark;
11+
public class BenchmarkConfig
12+
{
13+
public class Config : ManualConfig
14+
{
15+
public Config()
16+
{
17+
AddJob( Job.ShortRun );
18+
AddExporter( MarkdownExporter.GitHub );
19+
AddValidator( JitOptimizationsValidator.DontFailOnError );
20+
AddLogger( ConsoleLogger.Default );
21+
AddColumnProvider(
22+
DefaultColumnProviders.Job,
23+
DefaultColumnProviders.Params,
24+
DefaultColumnProviders.Descriptor,
25+
DefaultColumnProviders.Metrics,
26+
DefaultColumnProviders.Statistics
27+
);
28+
29+
AddDiagnoser( MemoryDiagnoser.Default );
30+
31+
Orderer = new DefaultOrderer( SummaryOrderPolicy.FastestToSlowest );
32+
ArtifactsPath = "benchmark";
33+
}
34+
}
35+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
3+
<PropertyGroup>
4+
<OutputType>Exe</OutputType>
5+
<TargetFramework>net8.0</TargetFramework>
6+
<ImplicitUsings>enable</ImplicitUsings>
7+
<Nullable>enable</Nullable>
8+
</PropertyGroup>
9+
10+
<ItemGroup>
11+
<PackageReference Include="BenchmarkDotNet" Version="0.13.12" />
12+
</ItemGroup>
13+
14+
<ItemGroup>
15+
<ProjectReference Include="..\..\src\Hyperbee.Pipeline.Auth\Hyperbee.Pipeline.Auth.csproj" />
16+
<ProjectReference Include="..\..\src\Hyperbee.Pipeline\Hyperbee.Pipeline.csproj" />
17+
<ProjectReference Include="..\..\src\Hyperbee.Pipline.Caching\Hyperbee.Pipeline.Caching.csproj" />
18+
<ProjectReference Include="..\Hyperbee.Pipeline.Auth.Tests\Hyperbee.Pipeline.Auth.Tests.csproj" />
19+
</ItemGroup>
20+
21+
</Project>
Lines changed: 159 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,159 @@
1+
using System.ComponentModel.Design;
2+
using System.Security.Claims;
3+
using BenchmarkDotNet.Attributes;
4+
using Hyperbee.Pipeline.Auth;
5+
using Hyperbee.Pipeline.Caching;
6+
using Hyperbee.Pipeline.Context;
7+
using Microsoft.Extensions.Caching.Memory;
8+
using Microsoft.Extensions.Internal;
9+
using Microsoft.Extensions.Logging;
10+
11+
namespace Hyperbee.Pipeline.Benchmark;
12+
13+
public class PipelineBenchmarks
14+
{
15+
16+
[Benchmark]
17+
public void PipelineExecution()
18+
{
19+
var command = PipelineFactory
20+
.Start<string>()
21+
.Pipe( ( ctx, arg ) => int.Parse( arg ) )
22+
.Build();
23+
24+
command( new PipelineContext(), "5" );
25+
}
26+
27+
[Benchmark]
28+
public void PipelineMiddleware()
29+
{
30+
31+
var command = PipelineFactory
32+
.Start<string>()
33+
.HookAsync( async ( ctx, arg, next ) => await next( ctx, arg + "{" ) + "}" )
34+
.Pipe( ( ctx, arg ) => arg + "1" )
35+
.Build();
36+
37+
command( new PipelineContext() );
38+
}
39+
40+
[Benchmark]
41+
public void PipelineEnumeration()
42+
{
43+
var count = 0;
44+
45+
var command1 = PipelineFactory
46+
.Start<string>()
47+
.Pipe( ( ctx, arg ) => arg + "!" )
48+
.Pipe( ( ctx, arg ) => count += 10 )
49+
.Build();
50+
51+
var command = PipelineFactory
52+
.Start<string>()
53+
.Pipe( ( ctx, arg ) => arg.Split( ' ' ) )
54+
.PipeAsync( async ( ctx, arg ) =>
55+
{
56+
foreach ( var e in arg )
57+
await command1( ctx, e );
58+
59+
return arg;
60+
} )
61+
.Pipe( ( ctx, arg ) => string.Join( ' ', arg ) )
62+
.Build();
63+
64+
command( new PipelineContext(), "e f" );
65+
}
66+
67+
[Benchmark]
68+
public void PipelineCancellation()
69+
{
70+
var command = PipelineFactory
71+
.Start<int>()
72+
.Pipe( ( ctx, arg ) => 1 )
73+
.Pipe( ( ctx, arg ) =>
74+
{
75+
ctx.CancelAfter();
76+
return 2;
77+
} )
78+
.Pipe( ( ctx, arg ) => 3 )
79+
.Build();
80+
81+
command( new PipelineContext() );
82+
}
83+
84+
[Benchmark]
85+
public void PipelineAuth()
86+
{
87+
var factory = CreateContextFactory();
88+
ILogger<PipelineBenchmarks> logger = null!;
89+
90+
91+
var command = PipelineFactory
92+
.Start<string>()
93+
.PipeIfClaim( new Claim( "Role", "reader" ), b => b.Pipe( Complex ) )
94+
.Build();
95+
96+
command( factory.Create( logger ), "reader" );
97+
}
98+
99+
[Benchmark]
100+
public void PipelineMemoryCache()
101+
{
102+
var command = PipelineFactory
103+
.Start<string>()
104+
.PipeCache( Complex )
105+
.Build();
106+
107+
var factory = CreateContextFactory();
108+
ILogger<PipelineBenchmarks> logger = null!;
109+
110+
command( factory.Create( logger ), "test" );
111+
}
112+
113+
[Benchmark]
114+
public void PipelineDistributedCache()
115+
{
116+
var command = PipelineFactory
117+
.Start<string>()
118+
.PipeDistributedCacheAsync( ComplexAsync )
119+
.Build();
120+
121+
var factory = CreateContextFactory();
122+
ILogger<PipelineBenchmarks> logger = null!;
123+
124+
command( factory.Create( logger ), "test" );
125+
}
126+
127+
128+
private static int Complex( IPipelineContext context, string argument ) => argument.Length;
129+
130+
private static Task<int> ComplexAsync( IPipelineContext context, string argument ) =>
131+
Task.FromResult( argument.Length );
132+
133+
private static IPipelineContextFactory CreateContextFactory( ISystemClock? clock = null )
134+
{
135+
clock ??= new TestSystemClock { UtcNow = DateTimeOffset.UtcNow };
136+
var container = new ServiceContainer();
137+
138+
container.AddService(
139+
typeof( IMemoryCache ),
140+
new MemoryCache( new MemoryCacheOptions
141+
{
142+
Clock = clock,
143+
ExpirationScanFrequency = TimeSpan.FromMilliseconds( 100 ),
144+
TrackLinkedCacheEntries = false
145+
} ) );
146+
147+
container.AddService(
148+
typeof( PipelineMemoryCacheOptions ),
149+
new PipelineMemoryCacheOptions()
150+
);
151+
152+
return PipelineContextFactory.CreateFactory( container, true );
153+
}
154+
155+
public class TestSystemClock : ISystemClock
156+
{
157+
public DateTimeOffset UtcNow { get; set; }
158+
}
159+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
using BenchmarkDotNet.Running;
2+
3+
namespace Hyperbee.Pipeline.Benchmark;
4+
5+
internal class Program
6+
{
7+
static void Main( string[] args )
8+
{
9+
BenchmarkSwitcher.FromAssembly( typeof( Program ).Assembly ).Run( args, new BenchmarkConfig.Config() );
10+
}
11+
}

0 commit comments

Comments
 (0)