Skip to content

Commit bfa082b

Browse files
authored
Add benchmark2 based Mvc json benchmarks (#1516)
1 parent 1e57a08 commit bfa082b

16 files changed

+712
-15
lines changed

benchmarks.sln

+15
Original file line numberDiff line numberDiff line change
@@ -266,6 +266,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "servicebus-controller", "se
266266
docker\servicebus-controller\stop.sh = docker\servicebus-controller\stop.sh
267267
EndProjectSection
268268
EndProject
269+
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Mvc", "src\BenchmarksApps\Mvc\Mvc.csproj", "{E82AA66D-270B-4041-9D8B-364E54D4E962}"
270+
EndProject
269271
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "H2LoadClient", "src\H2LoadClient\H2LoadClient.csproj", "{7AFACAC0-EFD1-4736-B512-06E8282BB222}"
270272
EndProject
271273
Global
@@ -662,6 +664,18 @@ Global
662664
{7AFACAC0-EFD1-4736-B512-06E8282BB222}.Release|x64.Build.0 = Release|Any CPU
663665
{7AFACAC0-EFD1-4736-B512-06E8282BB222}.Release|x86.ActiveCfg = Release|Any CPU
664666
{7AFACAC0-EFD1-4736-B512-06E8282BB222}.Release|x86.Build.0 = Release|Any CPU
667+
{E82AA66D-270B-4041-9D8B-364E54D4E962}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
668+
{E82AA66D-270B-4041-9D8B-364E54D4E962}.Debug|Any CPU.Build.0 = Debug|Any CPU
669+
{E82AA66D-270B-4041-9D8B-364E54D4E962}.Debug|x64.ActiveCfg = Debug|Any CPU
670+
{E82AA66D-270B-4041-9D8B-364E54D4E962}.Debug|x64.Build.0 = Debug|Any CPU
671+
{E82AA66D-270B-4041-9D8B-364E54D4E962}.Debug|x86.ActiveCfg = Debug|Any CPU
672+
{E82AA66D-270B-4041-9D8B-364E54D4E962}.Debug|x86.Build.0 = Debug|Any CPU
673+
{E82AA66D-270B-4041-9D8B-364E54D4E962}.Release|Any CPU.ActiveCfg = Release|Any CPU
674+
{E82AA66D-270B-4041-9D8B-364E54D4E962}.Release|Any CPU.Build.0 = Release|Any CPU
675+
{E82AA66D-270B-4041-9D8B-364E54D4E962}.Release|x64.ActiveCfg = Release|Any CPU
676+
{E82AA66D-270B-4041-9D8B-364E54D4E962}.Release|x64.Build.0 = Release|Any CPU
677+
{E82AA66D-270B-4041-9D8B-364E54D4E962}.Release|x86.ActiveCfg = Release|Any CPU
678+
{E82AA66D-270B-4041-9D8B-364E54D4E962}.Release|x86.Build.0 = Release|Any CPU
665679
EndGlobalSection
666680
GlobalSection(SolutionProperties) = preSolution
667681
HideSolutionNode = FALSE
@@ -718,6 +732,7 @@ Global
718732
{127BD56E-993B-47A7-BC0A-2300DF53FADC} = {39985004-8041-41FC-BBB1-CCF999D7BC16}
719733
{499B0522-A7CE-4788-9166-1AFFBF506F68} = {995FCFF9-E5F6-4BDD-8E5B-FBDEA21145F9}
720734
{C6C8279D-CBC8-467A-875F-79E855D6824E} = {EF444B27-3CBA-4581-893A-7F6DB5527371}
735+
{E82AA66D-270B-4041-9D8B-364E54D4E962} = {A9BDD13F-8E19-459E-BE3F-4484AE699265}
721736
{7AFACAC0-EFD1-4736-B512-06E8282BB222} = {39985004-8041-41FC-BBB1-CCF999D7BC16}
722737
EndGlobalSection
723738
GlobalSection(ExtensibilityGlobals) = postSolution

build/trend-scenarios.yml

+8
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,14 @@ parameters:
6363
arguments: --scenario MvcJsonInput2k $(jsonJobs)
6464
- displayName: Json Mvc Input (NewtonSoft, 2KB)
6565
arguments: --scenario MvcJsonNetInput2k $(jsonJobs)
66+
- displayName: Json Mvc (60KB)
67+
arguments: --scenario MvcJsonOutput60k $(jsonJobs)
68+
- displayName: Json Mvc (NewtonSoft, 60KB)
69+
arguments: --scenario MvcJsonNetOutput60k $(jsonJobs)
70+
- displayName: Json Mvc Input (60KB)
71+
arguments: --scenario MvcJsonInput60k $(jsonJobs)
72+
- displayName: Json Mvc Input (NewtonSoft, 60KB)
73+
arguments: --scenario MvcJsonNetInput60k $(jsonJobs)
6674
- displayName: Json Mvc Input (2MB)
6775
arguments: --scenario MvcJsonInput2M $(jsonJobs)
6876
- displayName: Json Mvc Input (NewtonSoft, 2MB)

scripts/mvcjsoninput.2mb.lua

-3
Original file line numberDiff line numberDiff line change
@@ -27,12 +27,9 @@ function init(args)
2727

2828
data = data .. "]"
2929

30-
local contentLength = string.len(data)
31-
3230
wrk.method = "POST"
3331
wrk.body = data
3432
wrk.headers["Content-Type"] = "application/json"
35-
wrk.headers["Content-Length"] = contentLength
3633

3734
req = wrk.format()
3835
end

scripts/mvcjsoninput.lua

+6-4
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
local payloadItems = 8
21
local payloadItem = [[{
32
"attributes": {
43
"created": "2019-04-23T00:45:50+00:00",
@@ -15,6 +14,12 @@ local payloadItem = [[{
1514
}]]
1615

1716
function init(args)
17+
local payloadItems = 8
18+
if (#args ~= 0)
19+
then
20+
payloadItems = tonumber(args[1]) / 350 -- ~350 bytes per payloadItem
21+
end
22+
1823
local data = "["
1924
-- Note that this produces 4kb data. We're leaving the misnamed scenario as is to avoid loosing historical context
2025
for i = 1, payloadItems, 1 do
@@ -28,12 +33,9 @@ function init(args)
2833

2934
data = data .. "]"
3035

31-
local contentLength = string.len(data)
32-
3336
wrk.method = "POST"
3437
wrk.body = data
3538
wrk.headers["Content-Type"] = "application/json"
36-
wrk.headers["Content-Length"] = contentLength
3739

3840
req = wrk.format()
3941
end
+87
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
// Copyright (c) .NET Foundation. All rights reserved.
2+
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
3+
4+
using System;
5+
using System.Collections.Generic;
6+
using System.Linq;
7+
using Microsoft.AspNetCore.Mvc;
8+
9+
namespace Benchmarks.Controllers
10+
{
11+
[ApiController]
12+
public class JsonController : Controller
13+
{
14+
private static readonly List<Entry> _entries2k = Entry.Create(8).ToList();
15+
private static List<Entry> _entriesNk;
16+
private static int previousSizeInBytes;
17+
18+
[HttpGet("/json-helloworld")]
19+
[Produces("application/json")]
20+
public object Json()
21+
{
22+
return new { message = "Hello, World!" };
23+
}
24+
25+
[HttpGet("/json2k")]
26+
[Produces("application/json")]
27+
public List<Entry> Json2k() => _entries2k;
28+
29+
[HttpGet("/jsonNbytes/{sizeInBytes}")]
30+
[Produces("application/json")]
31+
public List<Entry> JsonNk([FromRoute] int sizeInBytes)
32+
{
33+
if (_entriesNk is null || sizeInBytes != previousSizeInBytes)
34+
{
35+
var numItems = sizeInBytes / 340; // ~ 340 bytes per item
36+
_entriesNk = Entry.Create(numItems);
37+
previousSizeInBytes = sizeInBytes;
38+
}
39+
40+
return _entriesNk;
41+
}
42+
43+
[HttpPost("/jsoninput")]
44+
[Consumes("application/json")]
45+
public ActionResult JsonInput([FromBody] List<Entry> entry) => Ok();
46+
}
47+
48+
public partial class Entry
49+
{
50+
public Attributes Attributes { get; set; }
51+
public string ContentType { get; set; }
52+
public string Id { get; set; }
53+
public bool Managed { get; set; }
54+
public string[] Tags { get; set; }
55+
56+
public static List<Entry> Create(int n)
57+
{
58+
var baseDateTime = new DateTimeOffset(new DateTime(2019, 04, 23));
59+
60+
return Enumerable.Range(1, n).Select(i => new Entry
61+
{
62+
Attributes = new Attributes
63+
{
64+
Created = baseDateTime.AddDays(i),
65+
Enabled = true,
66+
Expires = baseDateTime.AddDays(i).AddYears(1),
67+
NotBefore = baseDateTime,
68+
RecoveryLevel = "Purgeable",
69+
Updated = baseDateTime.AddSeconds(i),
70+
},
71+
ContentType = "application/xml",
72+
Id = "https://benchmarktest.id/item/value" + i,
73+
Tags = new[] { "test", "perf", "json" },
74+
}).ToList();
75+
}
76+
}
77+
78+
public partial class Attributes
79+
{
80+
public DateTimeOffset Created { get; set; }
81+
public bool Enabled { get; set; }
82+
public DateTimeOffset Expires { get; set; }
83+
public DateTimeOffset NotBefore { get; set; }
84+
public string RecoveryLevel { get; set; }
85+
public DateTimeOffset Updated { get; set; }
86+
}
87+
}

src/BenchmarksApps/Mvc/Mvc.csproj

+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
<Project Sdk="Microsoft.NET.Sdk.Web">
2+
3+
<PropertyGroup>
4+
<TargetFramework>netcoreapp5.0</TargetFramework>
5+
<TargetFramework Condition="'$(BenchmarksTargetFramework)' != ''">$(BenchmarksTargetFramework)</TargetFramework>
6+
<MicrosoftAspNetCoreAppPackageVersion Condition="'$(MicrosoftAspNetCoreAppPackageVersion)' == ''">5.0.0-*</MicrosoftAspNetCoreAppPackageVersion>
7+
</PropertyGroup>
8+
9+
<ItemGroup>
10+
<Content Include="mvcserver.yml" />
11+
</ItemGroup>
12+
13+
<ItemGroup>
14+
<PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="$(MicrosoftAspNetCoreAppPackageVersion)" />
15+
</ItemGroup>
16+
17+
<!-- These references are used when running on the Benchmarks Server -->
18+
<ItemGroup Condition="'$(BenchmarksTargetFramework)' != ''">
19+
<FrameworkReference Update="Microsoft.AspNetCore.App" RuntimeFrameworkVersion="$(MicrosoftAspNetCoreAppPackageVersion)" />
20+
<FrameworkReference Update="Microsoft.NETCore.App" RuntimeFrameworkVersion="$(MicrosoftNETCoreAppPackageVersion)" />
21+
</ItemGroup>
22+
23+
</Project>

src/BenchmarksApps/Mvc/Program.cs

+29
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
4+
using System.Reflection;
5+
using System.Threading.Tasks;
6+
using Microsoft.AspNetCore.Hosting;
7+
using Microsoft.AspNetCore.Mvc;
8+
using Microsoft.Extensions.Configuration;
9+
using Microsoft.Extensions.Hosting;
10+
using Microsoft.Extensions.Logging;
11+
12+
namespace Mvc
13+
{
14+
public class Program
15+
{
16+
public static void Main(string[] args)
17+
{
18+
Console.WriteLine($"MVC {string.Join(" ", args)}");
19+
CreateHostBuilder(args).Build().Run();
20+
}
21+
22+
public static IHostBuilder CreateHostBuilder(string[] args) =>
23+
Host.CreateDefaultBuilder(args)
24+
.ConfigureWebHostDefaults(webBuilder =>
25+
{
26+
webBuilder.UseStartup<Startup>();
27+
});
28+
}
29+
}

src/BenchmarksApps/Mvc/Startup.cs

+49
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
using System;
2+
using Microsoft.AspNetCore.Builder;
3+
using Microsoft.AspNetCore.Hosting;
4+
using Microsoft.Extensions.Configuration;
5+
using Microsoft.Extensions.DependencyInjection;
6+
using Microsoft.Extensions.Logging;
7+
8+
namespace Mvc
9+
{
10+
public class Startup
11+
{
12+
public Startup(IConfiguration configuration)
13+
{
14+
Configuration = configuration;
15+
UseNewtonsoftJson = Configuration["UseNewtonsoftJson"] == "true";
16+
}
17+
18+
public IConfiguration Configuration { get; }
19+
20+
bool UseNewtonsoftJson { get; }
21+
22+
// This method gets called by the runtime. Use this method to add services to the container.
23+
public void ConfigureServices(IServiceCollection services)
24+
{
25+
var mvcBuilder = services.AddControllers();
26+
27+
if (UseNewtonsoftJson)
28+
{
29+
mvcBuilder.AddNewtonsoftJson();
30+
}
31+
}
32+
33+
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
34+
public void Configure(IApplicationBuilder app, IWebHostEnvironment env, ILogger<Startup> logger)
35+
{
36+
if (UseNewtonsoftJson)
37+
{
38+
logger.LogInformation("MVC is configured to use Newtonsoft.Json.");
39+
}
40+
41+
app.UseRouting();
42+
43+
app.UseEndpoints(endpoints =>
44+
{
45+
endpoints.MapControllers();
46+
});
47+
}
48+
}
49+
}
+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
{
2+
"Logging": {
3+
"LogLevel": {
4+
"Default": "Information",
5+
"Microsoft": "Warning",
6+
"Microsoft.Hosting.Lifetime": "Information"
7+
}
8+
},
9+
"AllowedHosts": "*"
10+
}

0 commit comments

Comments
 (0)