Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Execution Benchmarks V10 vs V11 (#2051)
Co-authored-by: Michael Staib <michael@chillicream.com> Co-authored-by: Michael Staib <michael.staib@chillicream.com>
- Loading branch information
1 parent
2e175bc
commit 3b8fab1
Showing
80 changed files
with
2,396 additions
and
154 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,25 +1,30 @@ | ||
{ | ||
// Use IntelliSense to learn about possible attributes. | ||
// Hover to view descriptions of existing attributes. | ||
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 | ||
"version": "0.2.0", | ||
"configurations": [ | ||
{ | ||
"name": ".NET Core Launch (console)", | ||
"type": "coreclr", | ||
"request": "launch", | ||
"preLaunchTask": "build", | ||
"program": "${workspaceFolder}/benchmark/Execution.Benchmarks/bin/Debug/netcoreapp3.1/HotChocolate.Execution.Benchmarks.dll", | ||
"args": [], | ||
"cwd": "${workspaceFolder}/benchmark/Execution.Benchmarks", | ||
"console": "internalConsole", | ||
"stopAtEntry": false | ||
}, | ||
{ | ||
"name": ".NET Core Attach", | ||
"type": "coreclr", | ||
"request": "attach", | ||
"processId": "${command:pickProcess}" | ||
} | ||
] | ||
} | ||
// Use IntelliSense to learn about possible attributes. | ||
// Hover to view descriptions of existing attributes. | ||
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 | ||
"version": "0.2.0", | ||
"configurations": [ | ||
{ | ||
"name": ".NET Core Launch (console)", | ||
"type": "coreclr", | ||
"request": "launch", | ||
"preLaunchTask": "build", | ||
"program": "${workspaceFolder}/benchmark/Execution.Benchmarks/bin/Debug/netcoreapp3.1/HotChocolate.Execution.Benchmarks.dll", | ||
"args": [], | ||
"cwd": "${workspaceFolder}/benchmark/Execution.Benchmarks", | ||
"console": "internalConsole", | ||
"stopAtEntry": false | ||
}, | ||
{ | ||
"name": ".NET Core Attach", | ||
"type": "coreclr", | ||
"request": "attach", | ||
"processId": "${command:pickProcess}" | ||
}, | ||
{ | ||
"name": "Local Process with Kubernetes (Preview)", | ||
"type": "dev-spaces-connect-configuration", | ||
"request": "launch" | ||
} | ||
] | ||
} |
142 changes: 106 additions & 36 deletions
142
src/HotChocolate/Core/benchmark/Execution.Benchmarks/DefaultExecutionPipelineBenchmark.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,74 +1,144 @@ | ||
using BenchmarkDotNet.Attributes; | ||
using System.Collections.Generic; | ||
using System.Buffers; | ||
using Microsoft.Extensions.DependencyInjection; | ||
using HotChocolate.StarWars; | ||
using System.Threading.Tasks; | ||
using System; | ||
using HotChocolate.Language; | ||
using System.Text; | ||
using System.Threading.Tasks; | ||
using BenchmarkDotNet.Attributes; | ||
using HotChocolate.Language; | ||
using HotChocolate.StarWars; | ||
using Microsoft.Extensions.DependencyInjection; | ||
|
||
namespace HotChocolate.Execution.Benchmarks | ||
{ | ||
[RPlotExporter, CategoriesColumn, RankColumn, MeanColumn, MedianColumn, MemoryDiagnoser] | ||
public class DefaultExecutionPipelineBenchmark | ||
{ | ||
private readonly IRequestExecutor _executor; | ||
private readonly IReadOnlyQueryRequest _request; | ||
private readonly IReadOnlyQueryRequest _getHeroRequest; | ||
private readonly IReadOnlyQueryRequest _getHeroWithFriendsRequest; | ||
private readonly IReadOnlyQueryRequest _getTwoHerosWithFriendsRequest; | ||
private readonly IReadOnlyQueryRequest _introspectionRequest; | ||
|
||
public DefaultExecutionPipelineBenchmark() | ||
{ | ||
var md5 = new MD5DocumentHashProvider(); | ||
var resources = new ResourceHelper(); | ||
var services = new ServiceCollection() | ||
.AddStarWarsRepositories() | ||
.AddGraphQL() | ||
.ConfigureSchema(b => b.AddStarWarsTypes()) | ||
.Services.BuildServiceProvider(); | ||
.AddStarWarsTypes() | ||
.Services | ||
.BuildServiceProvider(); | ||
|
||
_executor = services | ||
.GetRequiredService<IRequestExecutorResolver>() | ||
.GetRequestExecutorAsync().Result; | ||
.GetRequestExecutorAsync() | ||
.Result; | ||
_getHeroRequest = CreateRequest(md5, resources, "GetHeroQuery.graphql"); | ||
_getHeroWithFriendsRequest = CreateRequest(md5, resources, "GetHeroWithFriendsQuery.graphql"); | ||
_getTwoHerosWithFriendsRequest = CreateRequest(md5, resources, "GetTwoHerosWithFriendsQuery.graphql"); | ||
_introspectionRequest = CreateRequest(md5, resources, "IntrospectionQuery.graphql"); | ||
} | ||
|
||
var md5 = new MD5DocumentHashProvider(); | ||
var resources = new ResourceHelper(); | ||
string introspectionQuery = resources.GetResourceString("IntrospectionQuery.graphql"); | ||
string hash = md5.ComputeHash(Encoding.UTF8.GetBytes(introspectionQuery).AsSpan()); | ||
DocumentNode document = Utf8GraphQLParser.Parse(introspectionQuery); | ||
_request = QueryRequestBuilder.New() | ||
private static IReadOnlyQueryRequest CreateRequest( | ||
MD5DocumentHashProvider md5, | ||
ResourceHelper resources, | ||
string resourceName) | ||
{ | ||
string query = resources.GetResourceString(resourceName); | ||
string hash = md5.ComputeHash(Encoding.UTF8.GetBytes(query).AsSpan()); | ||
DocumentNode document = Utf8GraphQLParser.Parse(query); | ||
|
||
return QueryRequestBuilder.New() | ||
.SetQuery(document) | ||
.SetQueryHash(hash) | ||
.SetQueryName(hash) | ||
.Create(); | ||
} | ||
|
||
SchemaIntrospection().Wait(); | ||
// note : all sync | ||
[Benchmark] | ||
public Task SchemaIntrospection() | ||
{ | ||
return OneRequest(_executor, _introspectionRequest); | ||
} | ||
|
||
[Benchmark] | ||
public async Task SchemaIntrospection() | ||
public Task SchemaIntrospectionFiveParallelRequests() | ||
{ | ||
IExecutionResult result = await _executor.ExecuteAsync(_request); | ||
return FiveRequestsInParallel(_executor, _introspectionRequest); | ||
} | ||
|
||
// note : 1 data fetch | ||
[Benchmark] | ||
public Task GetHero() | ||
{ | ||
return OneRequest(_executor, _getHeroRequest); | ||
} | ||
|
||
[Benchmark] | ||
public Task GetHeroFiveParallelRequests() | ||
{ | ||
return FiveRequestsInParallel(_executor, _getHeroRequest); | ||
} | ||
|
||
// note : 2 cascading data fetches | ||
[Benchmark] | ||
public Task GetHeroWithFriends() | ||
{ | ||
return OneRequest(_executor, _getHeroWithFriendsRequest); | ||
} | ||
|
||
[Benchmark] | ||
public Task GetHeroWithFriendsFiveParallelRequests() | ||
{ | ||
return FiveRequestsInParallel(_executor, _getHeroWithFriendsRequest); | ||
} | ||
|
||
// note : 4 data fetches (2 parallel 2 cascading) | ||
[Benchmark] | ||
public Task GetTwoHerosWithFriends() | ||
{ | ||
return OneRequest(_executor, _getTwoHerosWithFriendsRequest); | ||
} | ||
|
||
[Benchmark] | ||
public Task GetTwoHerosWithFriendsFiveParallelRequests() | ||
{ | ||
return FiveRequestsInParallel(_executor, _getTwoHerosWithFriendsRequest); | ||
} | ||
|
||
private static async Task OneRequest( | ||
IRequestExecutor executer, | ||
IReadOnlyQueryRequest request) | ||
{ | ||
IExecutionResult result = await executer.ExecuteAsync(request); | ||
// var jsonWriter = new HotChocolate.Execution.Serialization.JsonQueryResultSerializer(true); | ||
// Console.WriteLine(jsonWriter.Serialize((IReadOnlyQueryResult)result)); | ||
((IDisposable)result).Dispose(); | ||
} | ||
|
||
[Benchmark] | ||
public async Task SchemaIntrospectionMultiple() | ||
private static async Task FiveRequestsInParallel( | ||
IRequestExecutor executer, | ||
IReadOnlyQueryRequest request) | ||
{ | ||
Task<IExecutionResult> task1 = _executor.ExecuteAsync(_request); | ||
Task<IExecutionResult> task2 = _executor.ExecuteAsync(_request); | ||
Task<IExecutionResult> task3 = _executor.ExecuteAsync(_request); | ||
Task<IExecutionResult> task4 = _executor.ExecuteAsync(_request); | ||
Task<IExecutionResult> task5 = _executor.ExecuteAsync(_request); | ||
Task task1 = OneRequest(executer, request); | ||
Task task2 = OneRequest(executer, request); | ||
Task task3 = OneRequest(executer, request); | ||
Task task4 = OneRequest(executer, request); | ||
Task task5 = OneRequest(executer, request); | ||
|
||
((IDisposable)(await task1)).Dispose(); | ||
((IDisposable)(await task2)).Dispose(); | ||
task1 = _executor.ExecuteAsync(_request); | ||
((IDisposable)(await task3)).Dispose(); | ||
task2 = _executor.ExecuteAsync(_request); | ||
((IDisposable)(await task4)).Dispose(); | ||
((IDisposable)(await task5)).Dispose(); | ||
((IDisposable)(await task1)).Dispose(); | ||
((IDisposable)(await task2)).Dispose(); | ||
await WaitForTask(task1); | ||
await WaitForTask(task2); | ||
await WaitForTask(task3); | ||
await WaitForTask(task4); | ||
await WaitForTask(task5); | ||
} | ||
|
||
private static async Task WaitForTask(Task task) | ||
{ | ||
if (!task.IsCompleted) | ||
{ | ||
await task; | ||
} | ||
} | ||
} | ||
} |
1 change: 0 additions & 1 deletion
1
src/HotChocolate/Core/benchmark/Execution.Benchmarks/FieldCollectorBenchmarks.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
5 changes: 5 additions & 0 deletions
5
src/HotChocolate/Core/benchmark/Execution.Benchmarks/Resources/GetHeroQuery.graphql
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
query getHero { | ||
hero(episode: NEWHOPE) { | ||
name | ||
} | ||
} |
43 changes: 43 additions & 0 deletions
43
...otChocolate/Core/benchmark/Execution.Benchmarks/Resources/GetHeroWithFriendsQuery.graphql
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
query getHero { | ||
hero(episode: NEWHOPE) { | ||
...Hero | ||
} | ||
} | ||
|
||
fragment Hero on Character { | ||
...Human | ||
...Droid | ||
} | ||
|
||
fragment Human on Human { | ||
...HasName | ||
...HasFriends | ||
height | ||
} | ||
|
||
fragment Droid on Droid { | ||
...HasName | ||
...HasFriends | ||
height | ||
} | ||
|
||
fragment Friend on CharacterConnection { | ||
nodes { | ||
...HasName | ||
friends { | ||
nodes { | ||
...HasName | ||
} | ||
} | ||
} | ||
} | ||
|
||
fragment HasName on Character { | ||
name | ||
} | ||
|
||
fragment HasFriends on Character { | ||
friends { | ||
...Friend | ||
} | ||
} |
46 changes: 46 additions & 0 deletions
46
...ocolate/Core/benchmark/Execution.Benchmarks/Resources/GetTwoHerosWithFriendsQuery.graphql
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
query getHero { | ||
a: hero(episode: EMPIRE) { | ||
...Hero | ||
} | ||
b: hero(episode: NEWHOPE) { | ||
...Hero | ||
} | ||
} | ||
|
||
fragment Hero on Character { | ||
...Human | ||
...Droid | ||
} | ||
|
||
fragment Human on Human { | ||
...HasName | ||
...HasFriends | ||
height | ||
} | ||
|
||
fragment Droid on Droid { | ||
...HasName | ||
...HasFriends | ||
height | ||
} | ||
|
||
fragment Friend on CharacterConnection { | ||
nodes { | ||
...HasName | ||
friends { | ||
nodes { | ||
...HasName | ||
} | ||
} | ||
} | ||
} | ||
|
||
fragment HasName on Character { | ||
name | ||
} | ||
|
||
fragment HasFriends on Character { | ||
friends { | ||
...Friend | ||
} | ||
} |
Oops, something went wrong.