Skip to content

Commit 63a8a34

Browse files
authored
ci/performance testing (microsoft#2304)
* ci: performance project scaffolding * chore: moves benchmark to dedicated directory * chore: commits initial benchmark results * ci: adds a comparison project for benchmark results * ci: adds benchmark runs and comparison * ci: renames empty models tests * chore: refactors to a command structure * chore: moves models to a dedicated source file * chore: uses STJ attribute based serialization * ci: fixes missing project argument * ci: fixes reports path * chore: moves policies to own directory * chore: no warn on static method for perf test project * chore: linting * chore: reduces run time for empty performance tests * chore: linting * fix: a bug where the input stream would be disposed not matter what * ci: fixes working directory for benchmark run * ci: adds basic infrastructure for descriptions based performance tests * chore: refresh empty object tests * ci: adds comparison run for descriptions comparisons * ci: adds percentage based comparisons * ci: adds large description to performance tests * ci: adds yaml descriptions perf tests to compare * ci: adds truncation in percentage difference to reduce noise --------- Signed-off-by: Vincent Biret <vibiret@microsoft.com>
1 parent 28e4a75 commit 63a8a34

28 files changed

+1248
-15
lines changed

.github/workflows/ci-cd.yml

Lines changed: 38 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ jobs:
1616
- name: Setup .NET
1717
uses: actions/setup-dotnet@v4
1818
with:
19-
dotnet-version: 8.0.x
19+
dotnet-version: 8.x
2020

2121
- name: Checkout repository
2222
id: checkout_repo
@@ -51,3 +51,40 @@ jobs:
5151
- name: Validate Trimming warnings
5252
run: dotnet publish -c Release -r win-x64 /p:TreatWarningsAsErrors=true /warnaserror -f net8.0
5353
working-directory: ./test/Microsoft.OpenApi.Trimming.Tests
54+
55+
validate-performance:
56+
name: Validate performance of the library
57+
runs-on: ubuntu-latest
58+
needs: [ci]
59+
steps:
60+
- name: Checkout repository
61+
uses: actions/checkout@v4
62+
63+
- name: Setup .NET
64+
uses: actions/setup-dotnet@v4
65+
with:
66+
dotnet-version: 8.x
67+
68+
- name: Copy committed results
69+
run: |
70+
mkdir -p ./performanceResults
71+
cp -r ./performance/benchmark/BenchmarkDotNet.Artifacts/results/* ./performanceResults
72+
73+
- name: Run performance tests
74+
run: |
75+
dotnet run -c Release
76+
working-directory: ./performance/benchmark
77+
78+
- name: Run comparison tool for empty models
79+
run: dotnet run -c Release --project ./performance/resultsComparer/resultsComparer.csproj -- compare $OLD_REPORT $NEW_REPORT -p IdenticalMemoryUsage
80+
shell: bash
81+
env:
82+
NEW_REPORT: "${{ github.workspace }}/performance/benchmark/BenchmarkDotNet.Artifacts/results/performance.EmptyModels-report.json"
83+
OLD_REPORT: "${{ github.workspace }}/performanceResults/performance.EmptyModels-report.json"
84+
85+
- name: Run comparison tool for descriptions
86+
run: dotnet run -c Release --project ./performance/resultsComparer/resultsComparer.csproj -- compare $OLD_REPORT $NEW_REPORT -p ZeroPointTwoPercentDifferenceMemoryUsage
87+
shell: bash
88+
env:
89+
NEW_REPORT: "${{ github.workspace }}/performance/benchmark/BenchmarkDotNet.Artifacts/results/performance.Descriptions-report.json"
90+
OLD_REPORT: "${{ github.workspace }}/performanceResults/performance.Descriptions-report.json"

.vscode/launch.json

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,37 @@
1919
"console": "internalConsole",
2020
"stopAtEntry": false
2121
},
22+
{
23+
// Use IntelliSense to find out which attributes exist for C# debugging
24+
// Use hover for the description of the existing attributes
25+
// For further information visit https://github.com/OmniSharp/omnisharp-vscode/blob/main/debugger-launchjson.md
26+
"name": "Launch Benchmark",
27+
"type": "coreclr",
28+
"request": "launch",
29+
"preLaunchTask": "build",
30+
// If you have changed target frameworks, make sure to update the program path.
31+
"program": "${workspaceFolder}/performance/benchmark/bin/Release/net8.0/PerformanceTests.dll",
32+
// For more information about the 'console' field, see https://aka.ms/VSCode-CS-LaunchJson-Console
33+
"console": "internalConsole",
34+
"stopAtEntry": false,
35+
},
36+
{
37+
// Use IntelliSense to find out which attributes exist for C# debugging
38+
// Use hover for the description of the existing attributes
39+
// For further information visit https://github.com/OmniSharp/omnisharp-vscode/blob/main/debugger-launchjson.md
40+
"name": "Launch Results comparer",
41+
"type": "coreclr",
42+
"request": "launch",
43+
"preLaunchTask": "build",
44+
// If you have changed target frameworks, make sure to update the program path.
45+
"program": "${workspaceFolder}/performance/resultsComparer/bin/Debug/net8.0/resultsComparer.dll",
46+
"cwd": "${workspaceFolder}/performance/resultsComparer",
47+
"args": ["compare"],
48+
// For more information about the 'console' field, see https://aka.ms/VSCode-CS-LaunchJson-Console
49+
"console": "internalConsole",
50+
"stopAtEntry": false,
51+
"requireExactSource": false,
52+
},
2253
{
2354
// Use IntelliSense to find out which attributes exist for C# debugging
2455
// Use hover for the description of the existing attributes

.vscode/tasks.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
"group": "build",
1111
"args": [
1212
"build",
13-
"${workspaceFolder}/src/Microsoft.OpenApi.Hidi/Microsoft.OpenApi.Hidi.csproj",
13+
"${workspaceFolder}/Microsoft.OpenApi.sln",
1414
"/property:GenerateFullPaths=true",
1515
"/consoleloggerparameters:NoSummary"
1616
],

Microsoft.OpenApi.sln

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,12 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.OpenApi.Hidi", "s
3030
EndProject
3131
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.OpenApi.Hidi.Tests", "test\Microsoft.OpenApi.Hidi.Tests\Microsoft.OpenApi.Hidi.Tests.csproj", "{6ADC5D41-EDD2-4206-B815-5DFF739C6832}"
3232
EndProject
33+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PerformanceTests", "performance\benchmark\PerformanceTests.csproj", "{537E49E3-325E-40EE-A90E-7556D4D333AA}"
34+
EndProject
35+
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "performance", "performance", "{4BB7E3F7-CA7E-45D3-B5AC-5DBB510FD528}"
36+
EndProject
37+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "resultsComparer", "performance\resultsComparer\resultsComparer.csproj", "{5EEA836B-3E08-4BE1-82B8-5236D031B497}"
38+
EndProject
3339
Global
3440
GlobalSection(SolutionConfigurationPlatforms) = preSolution
3541
Debug|Any CPU = Debug|Any CPU
@@ -68,6 +74,14 @@ Global
6874
{6ADC5D41-EDD2-4206-B815-5DFF739C6832}.Debug|Any CPU.Build.0 = Debug|Any CPU
6975
{6ADC5D41-EDD2-4206-B815-5DFF739C6832}.Release|Any CPU.ActiveCfg = Release|Any CPU
7076
{6ADC5D41-EDD2-4206-B815-5DFF739C6832}.Release|Any CPU.Build.0 = Release|Any CPU
77+
{537E49E3-325E-40EE-A90E-7556D4D333AA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
78+
{537E49E3-325E-40EE-A90E-7556D4D333AA}.Debug|Any CPU.Build.0 = Debug|Any CPU
79+
{537E49E3-325E-40EE-A90E-7556D4D333AA}.Release|Any CPU.ActiveCfg = Release|Any CPU
80+
{537E49E3-325E-40EE-A90E-7556D4D333AA}.Release|Any CPU.Build.0 = Release|Any CPU
81+
{5EEA836B-3E08-4BE1-82B8-5236D031B497}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
82+
{5EEA836B-3E08-4BE1-82B8-5236D031B497}.Debug|Any CPU.Build.0 = Debug|Any CPU
83+
{5EEA836B-3E08-4BE1-82B8-5236D031B497}.Release|Any CPU.ActiveCfg = Release|Any CPU
84+
{5EEA836B-3E08-4BE1-82B8-5236D031B497}.Release|Any CPU.Build.0 = Release|Any CPU
7185
EndGlobalSection
7286
GlobalSection(SolutionProperties) = preSolution
7387
HideSolutionNode = FALSE
@@ -81,6 +95,7 @@ Global
8195
{1D2E0C6E-B103-4CB6-912E-D56FA1501296} = {6357D7FD-2DE4-4900-ADB9-ABC37052040A}
8296
{538936B4-5E14-4EA3-9FD0-F43E2DD014FB} = {E546B92F-20A8-49C3-8323-4B25BB78F3E1}
8397
{6ADC5D41-EDD2-4206-B815-5DFF739C6832} = {6357D7FD-2DE4-4900-ADB9-ABC37052040A}
98+
{5EEA836B-3E08-4BE1-82B8-5236D031B497} = {4BB7E3F7-CA7E-45D3-B5AC-5DBB510FD528}
8499
EndGlobalSection
85100
GlobalSection(ExtensibilityGlobals) = postSolution
86101
SolutionGuid = {9F171EFC-0DB5-4B10-ABFA-AF48D52CC565}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
```
2+
3+
BenchmarkDotNet v0.14.0, Windows 11 (10.0.26100.3476)
4+
11th Gen Intel Core i7-1185G7 3.00GHz, 1 CPU, 8 logical and 4 physical cores
5+
.NET SDK 8.0.408
6+
[Host] : .NET 8.0.15 (8.0.1525.16413), X64 RyuJIT AVX-512F+CD+BW+DQ+VL+VBMI
7+
ShortRun : .NET 8.0.15 (8.0.1525.16413), X64 RyuJIT AVX-512F+CD+BW+DQ+VL+VBMI
8+
9+
Job=ShortRun IterationCount=3 LaunchCount=1
10+
WarmupCount=3
11+
12+
```
13+
| Method | Mean | Error | StdDev | Gen0 | Gen1 | Gen2 | Allocated |
14+
|------------- |-------------:|--------------:|-------------:|-----------:|-----------:|----------:|-------------:|
15+
| PetStoreYaml | 450.5 μs | 59.26 μs | 3.25 μs | 58.5938 | 11.7188 | - | 377.15 KB |
16+
| PetStoreJson | 172.8 μs | 123.46 μs | 6.77 μs | 39.0625 | 7.8125 | - | 239.29 KB |
17+
| GHESYaml | 943,452.7 μs | 137,685.49 μs | 7,547.01 μs | 66000.0000 | 21000.0000 | 3000.0000 | 389463.91 KB |
18+
| GHESJson | 468,401.8 μs | 300,711.80 μs | 16,483.03 μs | 41000.0000 | 15000.0000 | 3000.0000 | 250934.62 KB |
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
Method,Job,AnalyzeLaunchVariance,EvaluateOverhead,MaxAbsoluteError,MaxRelativeError,MinInvokeCount,MinIterationTime,OutlierMode,Affinity,EnvironmentVariables,Jit,LargeAddressAware,Platform,PowerPlanMode,Runtime,AllowVeryLargeObjects,Concurrent,CpuGroups,Force,HeapAffinitizeMask,HeapCount,NoAffinitize,RetainVm,Server,Arguments,BuildConfiguration,Clock,EngineFactory,NuGetReferences,Toolchain,IsMutator,InvocationCount,IterationCount,IterationTime,LaunchCount,MaxIterationCount,MaxWarmupIterationCount,MemoryRandomization,MinIterationCount,MinWarmupIterationCount,RunStrategy,UnrollFactor,WarmupCount,Mean,Error,StdDev,Gen0,Gen1,Gen2,Allocated
2+
PetStoreYaml,ShortRun,False,Default,Default,Default,Default,Default,Default,11111111,Empty,RyuJit,Default,X64,8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c,.NET 8.0,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,Default,3,Default,1,Default,Default,Default,Default,Default,Default,16,3,450.5 μs,59.26 μs,3.25 μs,58.5938,11.7188,0.0000,377.15 KB
3+
PetStoreJson,ShortRun,False,Default,Default,Default,Default,Default,Default,11111111,Empty,RyuJit,Default,X64,8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c,.NET 8.0,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,Default,3,Default,1,Default,Default,Default,Default,Default,Default,16,3,172.8 μs,123.46 μs,6.77 μs,39.0625,7.8125,0.0000,239.29 KB
4+
GHESYaml,ShortRun,False,Default,Default,Default,Default,Default,Default,11111111,Empty,RyuJit,Default,X64,8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c,.NET 8.0,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,Default,3,Default,1,Default,Default,Default,Default,Default,Default,16,3,"943,452.7 μs","137,685.49 μs","7,547.01 μs",66000.0000,21000.0000,3000.0000,389463.91 KB
5+
GHESJson,ShortRun,False,Default,Default,Default,Default,Default,Default,11111111,Empty,RyuJit,Default,X64,8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c,.NET 8.0,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,Default,3,Default,1,Default,Default,Default,Default,Default,Default,16,3,"468,401.8 μs","300,711.80 μs","16,483.03 μs",41000.0000,15000.0000,3000.0000,250934.62 KB
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
<!DOCTYPE html>
2+
<html lang='en'>
3+
<head>
4+
<meta charset='utf-8' />
5+
<title>performance.Descriptions-20250409-150544</title>
6+
7+
<style type="text/css">
8+
table { border-collapse: collapse; display: block; width: 100%; overflow: auto; }
9+
td, th { padding: 6px 13px; border: 1px solid #ddd; text-align: right; }
10+
tr { background-color: #fff; border-top: 1px solid #ccc; }
11+
tr:nth-child(even) { background: #f8f8f8; }
12+
</style>
13+
</head>
14+
<body>
15+
<pre><code>
16+
BenchmarkDotNet v0.14.0, Windows 11 (10.0.26100.3476)
17+
11th Gen Intel Core i7-1185G7 3.00GHz, 1 CPU, 8 logical and 4 physical cores
18+
.NET SDK 8.0.408
19+
[Host] : .NET 8.0.15 (8.0.1525.16413), X64 RyuJIT AVX-512F+CD+BW+DQ+VL+VBMI
20+
ShortRun : .NET 8.0.15 (8.0.1525.16413), X64 RyuJIT AVX-512F+CD+BW+DQ+VL+VBMI
21+
</code></pre>
22+
<pre><code>Job=ShortRun IterationCount=3 LaunchCount=1
23+
WarmupCount=3
24+
</code></pre>
25+
26+
<table>
27+
<thead><tr><th>Method</th><th>Mean </th><th>Error </th><th>StdDev</th><th>Gen0</th><th>Gen1</th><th>Gen2</th><th>Allocated</th>
28+
</tr>
29+
</thead><tbody><tr><td>PetStoreYaml</td><td>450.5 &mu;s</td><td>59.26 &mu;s</td><td>3.25 &mu;s</td><td>58.5938</td><td>11.7188</td><td>-</td><td>377.15 KB</td>
30+
</tr><tr><td>PetStoreJson</td><td>172.8 &mu;s</td><td>123.46 &mu;s</td><td>6.77 &mu;s</td><td>39.0625</td><td>7.8125</td><td>-</td><td>239.29 KB</td>
31+
</tr><tr><td>GHESYaml</td><td>943,452.7 &mu;s</td><td>137,685.49 &mu;s</td><td>7,547.01 &mu;s</td><td>66000.0000</td><td>21000.0000</td><td>3000.0000</td><td>389463.91 KB</td>
32+
</tr><tr><td>GHESJson</td><td>468,401.8 &mu;s</td><td>300,711.80 &mu;s</td><td>16,483.03 &mu;s</td><td>41000.0000</td><td>15000.0000</td><td>3000.0000</td><td>250934.62 KB</td>
33+
</tr></tbody></table>
34+
</body>
35+
</html>

performance/benchmark/BenchmarkDotNet.Artifacts/results/performance.Descriptions-report.json

Lines changed: 1 addition & 0 deletions
Large diffs are not rendered by default.
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
```
2+
3+
BenchmarkDotNet v0.14.0, Windows 11 (10.0.26100.3476)
4+
11th Gen Intel Core i7-1185G7 3.00GHz, 1 CPU, 8 logical and 4 physical cores
5+
.NET SDK 8.0.408
6+
[Host] : .NET 8.0.15 (8.0.1525.16413), X64 RyuJIT AVX-512F+CD+BW+DQ+VL+VBMI
7+
ShortRun : .NET 8.0.15 (8.0.1525.16413), X64 RyuJIT AVX-512F+CD+BW+DQ+VL+VBMI
8+
9+
Job=ShortRun IterationCount=3 LaunchCount=1
10+
WarmupCount=3
11+
12+
```
13+
| Method | Mean | Error | StdDev | Gen0 | Gen1 | Allocated |
14+
|---------------------------- |-----------:|------------:|-----------:|-------:|-------:|----------:|
15+
| EmptyApiCallback | 4.557 ns | 2.2807 ns | 0.1250 ns | 0.0051 | - | 32 B |
16+
| EmptyApiComponents | 5.116 ns | 0.6915 ns | 0.0379 ns | 0.0166 | - | 104 B |
17+
| EmptyApiContact | 3.759 ns | 3.1240 ns | 0.1712 ns | 0.0076 | - | 48 B |
18+
| EmptyApiDiscriminator | 3.442 ns | 2.3747 ns | 0.1302 ns | 0.0064 | - | 40 B |
19+
| EmptyDocument | 397.830 ns | 46.9921 ns | 2.5758 ns | 0.1807 | 0.0005 | 1136 B |
20+
| EmptyApiEncoding | 3.879 ns | 3.0270 ns | 0.1659 ns | 0.0089 | - | 56 B |
21+
| EmptyApiExample | 4.045 ns | 6.0543 ns | 0.3319 ns | 0.0089 | - | 56 B |
22+
| EmptyApiExternalDocs | 3.455 ns | 2.1233 ns | 0.1164 ns | 0.0064 | - | 40 B |
23+
| EmptyApiHeader | 4.633 ns | 3.8933 ns | 0.2134 ns | 0.0127 | - | 80 B |
24+
| EmptyApiInfo | 4.462 ns | 4.0279 ns | 0.2208 ns | 0.0127 | - | 80 B |
25+
| EmptyApiLicense | 3.670 ns | 1.6839 ns | 0.0923 ns | 0.0076 | - | 48 B |
26+
| EmptyApiLink | 4.388 ns | 1.9826 ns | 0.1087 ns | 0.0115 | - | 72 B |
27+
| EmptyApiMediaType | 3.857 ns | 1.4731 ns | 0.0807 ns | 0.0089 | - | 56 B |
28+
| EmptyApiOAuthFlow | 3.810 ns | 1.1359 ns | 0.0623 ns | 0.0089 | - | 56 B |
29+
| EmptyApiOAuthFlows | 3.979 ns | 5.5181 ns | 0.3025 ns | 0.0089 | - | 56 B |
30+
| EmptyApiOperation | 72.530 ns | 230.3314 ns | 12.6252 ns | 0.0599 | 0.0001 | 376 B |
31+
| EmptyApiParameter | 4.919 ns | 3.2142 ns | 0.1762 ns | 0.0153 | - | 96 B |
32+
| EmptyApiPathItem | 3.966 ns | 0.7140 ns | 0.0391 ns | 0.0102 | - | 64 B |
33+
| EmptyApiPaths | 56.222 ns | 32.3248 ns | 1.7718 ns | 0.0395 | - | 248 B |
34+
| EmptyApiRequestBody | 3.683 ns | 2.3246 ns | 0.1274 ns | 0.0076 | - | 48 B |
35+
| EmptyApiResponse | 3.864 ns | 0.9334 ns | 0.0512 ns | 0.0089 | - | 56 B |
36+
| EmptyApiResponses | 49.325 ns | 7.2131 ns | 0.3954 ns | 0.0395 | - | 248 B |
37+
| EmptyApiSchema | 12.565 ns | 2.0834 ns | 0.1142 ns | 0.0650 | - | 408 B |
38+
| EmptyApiSecurityRequirement | 8.411 ns | 1.5393 ns | 0.0844 ns | 0.0166 | - | 104 B |
39+
| EmptyApiSecurityScheme | 4.719 ns | 3.8028 ns | 0.2084 ns | 0.0140 | - | 88 B |
40+
| EmptyApiServer | 3.626 ns | 0.4928 ns | 0.0270 ns | 0.0076 | - | 48 B |
41+
| EmptyApiServerVariable | 3.589 ns | 0.2983 ns | 0.0164 ns | 0.0076 | - | 48 B |
42+
| EmptyApiTag | 3.889 ns | 7.4113 ns | 0.4062 ns | 0.0076 | - | 48 B |

0 commit comments

Comments
 (0)