Skip to content

Commit fc92496

Browse files
committed
Bring over a few changes from the TechEmpower repo
- incorporate aspnet/FrameworkBenchmarks@4830e2fc, "Only Prepare DbCommand once" - remove unused Microsoft.EntityFrameworkCore.Design dependency and EF tooling - remove irrelevant `#if NET46` code nits: - sort dependencies - clean up whitespace - accept VS suggestions
1 parent f9e2a45 commit fc92496

23 files changed

+89
-98
lines changed

src/Benchmarks/Benchmarks.csproj

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88
</PropertyGroup>
99

1010
<ItemGroup>
11-
<PackageReference Include="System.Runtime.Serialization.Primitives" Version="$(CoreFxVersion)" />
1211
<PackageReference Include="Dapper" Version="$(DapperVersion)" />
1312
<PackageReference Include="Microsoft.AspNetCore.Mvc" Version="$(AspNetCoreVersion)" />
1413
<PackageReference Include="Microsoft.AspNetCore.ResponseCaching" Version="$(AspNetCoreVersion)" />
@@ -17,7 +16,6 @@
1716
<PackageReference Include="Microsoft.AspNetCore.Server.Kestrel.Https" Version="$(AspNetCoreVersion)" />
1817
<PackageReference Include="Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets" Version="$(AspNetCoreVersion)" />
1918
<PackageReference Include="Microsoft.AspNetCore.StaticFiles" Version="$(AspNetCoreVersion)" />
20-
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="$(AspNetCoreVersion)" PrivateAssets="All" />
2119
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="$(AspNetCoreVersion)" />
2220
<PackageReference Include="Microsoft.Extensions.Caching.Memory" Version="$(AspNetCoreVersion)" />
2321
<PackageReference Include="Microsoft.Extensions.Configuration.CommandLine" Version="$(AspNetCoreVersion)" />
@@ -31,10 +29,6 @@
3129
-->
3230
<PackageReference Include="Npgsql" Version="$(NpgsqlVersion)" />
3331
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="$(NpgsqlEntityFrameworkCorePostgreSQLVersion)" />
32+
<PackageReference Include="System.Runtime.Serialization.Primitives" Version="$(CoreFxVersion)" />
3433
</ItemGroup>
35-
36-
<ItemGroup>
37-
<DotNetCliToolReference Include="Microsoft.EntityFrameworkCore.Tools.Dotnet" Version="$(AspNetCoreVersion)" />
38-
</ItemGroup>
39-
4034
</Project>

src/Benchmarks/Configuration/AppSettings.cs

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
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 Microsoft.Extensions.Logging;
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.
53

64
namespace Benchmarks.Configuration
75
{

src/Benchmarks/Configuration/Scenarios.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,7 @@ public static string GetPath(Expression<Func<Scenarios, bool>> scenarioExpressio
155155

156156
public int Enable(string partialName)
157157
{
158-
if(string.Equals(partialName, "[default]", StringComparison.OrdinalIgnoreCase))
158+
if (string.Equals(partialName, "[default]", StringComparison.OrdinalIgnoreCase))
159159
{
160160
EnableDefault();
161161
return 2;

src/Benchmarks/Data/ApplicationDbContext.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
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.
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.
33

44
using Microsoft.EntityFrameworkCore;
55

src/Benchmarks/Data/ApplicationDbSeeder.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
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.
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.
33

44
using System;
55
using System.Linq;

src/Benchmarks/Data/DapperDb.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
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.
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.
33

44
using System;
55
using System.Collections.Generic;
@@ -40,7 +40,7 @@ public async Task<World> LoadSingleQueryRow()
4040
async Task<World> ReadSingleRow(DbConnection db)
4141
{
4242
return await db.QueryFirstOrDefaultAsync<World>(
43-
"SELECT id, randomnumber FROM world WHERE Id = @Id",
43+
"SELECT id, randomnumber FROM world WHERE id = @Id",
4444
new { Id = _random.Next(1, 10001) });
4545
}
4646

src/Benchmarks/Data/EfDb.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
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.
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.
33

44
using System;
55
using System.Collections.Generic;

src/Benchmarks/Data/RawDb.cs

Lines changed: 45 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -28,20 +28,19 @@ public RawDb(IRandom random, DbProviderFactory dbProviderFactory, IOptions<AppSe
2828
public async Task<World> LoadSingleQueryRow()
2929
{
3030
using (var db = _dbProviderFactory.CreateConnection())
31-
using (var cmd = CreateReadCommand(db))
3231
{
3332
db.ConnectionString = _connectionString;
3433
await db.OpenAsync();
3534

36-
return await ReadSingleRow(db, cmd);
35+
using (var cmd = CreateReadCommand(db))
36+
{
37+
return await ReadSingleRow(db, cmd);
38+
}
3739
}
3840
}
3941

4042
async Task<World> ReadSingleRow(DbConnection connection, DbCommand cmd)
4143
{
42-
// Prepared statements improve PostgreSQL performance by 10-15%
43-
cmd.Prepare();
44-
4544
using (var rdr = await cmd.ExecuteReaderAsync(CommandBehavior.SingleRow))
4645
{
4746
await rdr.ReadAsync();
@@ -64,6 +63,10 @@ DbCommand CreateReadCommand(DbConnection connection)
6463
id.Value = _random.Next(1, 10001);
6564
cmd.Parameters.Add(id);
6665

66+
// Prepared statements improve PostgreSQL performance by 10-15%
67+
// Especially if you only call them once, instead of on every execution :)
68+
cmd.Prepare();
69+
6770
return cmd;
6871
}
6972

@@ -72,14 +75,16 @@ public async Task<World[]> LoadMultipleQueriesRows(int count)
7275
var result = new World[count];
7376

7477
using (var db = _dbProviderFactory.CreateConnection())
75-
using (var cmd = CreateReadCommand(db))
7678
{
7779
db.ConnectionString = _connectionString;
7880
await db.OpenAsync();
79-
for (int i = 0; i < count; i++)
81+
using (var cmd = CreateReadCommand(db))
8082
{
81-
result[i] = await ReadSingleRow(db, cmd);
82-
cmd.Parameters["@Id"].Value = _random.Next(1, 10001);
83+
for (int i = 0; i < count; i++)
84+
{
85+
result[i] = await ReadSingleRow(db, cmd);
86+
cmd.Parameters["@Id"].Value = _random.Next(1, 10001);
87+
}
8388
}
8489
}
8590

@@ -93,43 +98,45 @@ public async Task<World[]> LoadMultipleUpdatesRows(int count)
9398
var updateCommand = new StringBuilder(count);
9499

95100
using (var db = _dbProviderFactory.CreateConnection())
96-
using (var updateCmd = db.CreateCommand())
97-
using (var queryCmd = CreateReadCommand(db))
98101
{
99102
db.ConnectionString = _connectionString;
100103
await db.OpenAsync();
101104

102-
for (int i = 0; i < count; i++)
105+
using (var updateCmd = db.CreateCommand())
106+
using (var queryCmd = CreateReadCommand(db))
103107
{
104-
results[i] = await ReadSingleRow(db, queryCmd);
105-
queryCmd.Parameters["@Id"].Value = _random.Next(1, 10001);
106-
}
108+
for (int i = 0; i < count; i++)
109+
{
110+
results[i] = await ReadSingleRow(db, queryCmd);
111+
queryCmd.Parameters["@Id"].Value = _random.Next(1, 10001);
112+
}
107113

108-
// postgres has problems with deadlocks when these aren't sorted
109-
Array.Sort<World>(results, (a, b) => a.Id.CompareTo(b.Id));
114+
// postgres has problems with deadlocks when these aren't sorted
115+
Array.Sort<World>(results, (a, b) => a.Id.CompareTo(b.Id));
110116

111-
for(int i = 0; i < count; i++)
112-
{
113-
var id = updateCmd.CreateParameter();
114-
id.ParameterName = BatchUpdateString.Strings[i].Id;
115-
id.DbType = DbType.Int32;
116-
updateCmd.Parameters.Add(id);
117-
118-
var random = updateCmd.CreateParameter();
119-
random.ParameterName = BatchUpdateString.Strings[i].Random;
120-
id.DbType = DbType.Int32;
121-
updateCmd.Parameters.Add(random);
122-
123-
var randomNumber = _random.Next(1, 10001);
124-
id.Value = results[i].Id;
125-
random.Value = randomNumber;
126-
results[i].RandomNumber = randomNumber;
127-
128-
updateCommand.Append(BatchUpdateString.Strings[i].UpdateQuery);
129-
}
117+
for(int i = 0; i < count; i++)
118+
{
119+
var id = updateCmd.CreateParameter();
120+
id.ParameterName = BatchUpdateString.Strings[i].Id;
121+
id.DbType = DbType.Int32;
122+
updateCmd.Parameters.Add(id);
123+
124+
var random = updateCmd.CreateParameter();
125+
random.ParameterName = BatchUpdateString.Strings[i].Random;
126+
id.DbType = DbType.Int32;
127+
updateCmd.Parameters.Add(random);
128+
129+
var randomNumber = _random.Next(1, 10001);
130+
id.Value = results[i].Id;
131+
random.Value = randomNumber;
132+
results[i].RandomNumber = randomNumber;
133+
134+
updateCommand.Append(BatchUpdateString.Strings[i].UpdateQuery);
135+
}
130136

131-
updateCmd.CommandText = updateCommand.ToString();
132-
await updateCmd.ExecuteNonQueryAsync();
137+
updateCmd.CommandText = updateCommand.ToString();
138+
await updateCmd.ExecuteNonQueryAsync();
139+
}
133140
}
134141

135142
return results;

src/Benchmarks/Data/World.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
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.
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.
33

44
using System.ComponentModel.DataAnnotations.Schema;
55

src/Benchmarks/Middleware/DebugInfoPageMiddleware.cs

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
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.
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.
33

44
using System;
55
using System.Linq;
@@ -24,13 +24,7 @@ public class DebugInfoPageMiddleware
2424
private static readonly string _configurationName = "";
2525
#endif
2626

27-
#if NET46
28-
private static readonly string _targetFrameworkName = AppDomain.CurrentDomain.SetupInformation.TargetFrameworkName;
29-
#elif NETCOREAPP2_0
3027
private static readonly string _targetFrameworkName = AppContext.TargetFrameworkName;
31-
#else
32-
#error the target framework needs to be updated.
33-
#endif
3428

3529
private readonly IHostingEnvironment _hostingEnv;
3630
private readonly RequestDelegate _next;

src/Benchmarks/Middleware/FortunesDapperMiddleware.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
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.
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.
33

44
using System;
55
using System.Text.Encodings.Web;
@@ -40,7 +40,7 @@ public async Task Invoke(HttpContext httpContext)
4040
await _next(httpContext);
4141
}
4242
}
43-
43+
4444
public static class FortunesDapperMiddlewareExtensions
4545
{
4646
public static IApplicationBuilder UseFortunesDapper(this IApplicationBuilder builder)

src/Benchmarks/Middleware/FortunesRawMiddleware.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
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.
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.
33

44
using System;
55
using System.Text.Encodings.Web;
@@ -40,7 +40,7 @@ public async Task Invoke(HttpContext httpContext)
4040
await _next(httpContext);
4141
}
4242
}
43-
43+
4444
public static class FortunesRawMiddlewareExtensions
4545
{
4646
public static IApplicationBuilder UseFortunesRaw(this IApplicationBuilder builder)

src/Benchmarks/Middleware/MiddlewareHelpers.cs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,6 @@ public static async Task RenderFortunesHtml(IEnumerable<Fortune> model, HttpCont
5151
// fortunes includes multibyte characters so response.Length is incorrect
5252
httpContext.Response.ContentLength = Encoding.UTF8.GetByteCount(response);
5353
await httpContext.Response.WriteAsync(response);
54-
5554
}
5655
}
5756
}

src/Benchmarks/Middleware/MultipleQueriesDapperMiddleware.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
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.
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.
33

44
using System;
55
using System.Threading.Tasks;

src/Benchmarks/Middleware/MultipleQueriesRawMiddleware.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
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.
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.
33

44
using System;
55
using System.Threading.Tasks;

src/Benchmarks/Middleware/MultipleUpdatesDapperMiddleware.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
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.
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.
33

44
using System;
55
using System.Threading.Tasks;

src/Benchmarks/Middleware/MultipleUpdatesRawMiddleware.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
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.
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.
33

44
using System;
55
using System.Threading.Tasks;

src/Benchmarks/Middleware/PlaintextMiddleware.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
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.
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.
33

44
using System;
55
using System.Text;
@@ -16,7 +16,7 @@ public class PlaintextMiddleware
1616
private static readonly byte[] _helloWorldPayload = Encoding.UTF8.GetBytes("Hello, World!");
1717

1818
private readonly RequestDelegate _next;
19-
19+
2020
public PlaintextMiddleware(RequestDelegate next)
2121
{
2222
_next = next;
@@ -41,7 +41,7 @@ public static Task WriteResponse(HttpResponse response)
4141
return response.Body.WriteAsync(_helloWorldPayload, 0, payloadLength);
4242
}
4343
}
44-
44+
4545
public static class PlaintextMiddlewareExtensions
4646
{
4747
public static IApplicationBuilder UsePlainText(this IApplicationBuilder builder)

src/Benchmarks/Middleware/SingleQueryDapperMiddleware.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
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.
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.
33

44
using System;
55
using System.Threading.Tasks;

src/Benchmarks/Middleware/SingleQueryEfMiddleware.cs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88
using Microsoft.AspNetCore.Builder;
99
using Microsoft.AspNetCore.Http;
1010
using Microsoft.Extensions.DependencyInjection;
11-
1211
using Newtonsoft.Json;
1312
using Newtonsoft.Json.Serialization;
1413

src/Benchmarks/Middleware/SingleQueryRawMiddleware.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
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.
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.
33

44
using System;
55
using System.Threading.Tasks;

src/Benchmarks/Program.cs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -189,9 +189,11 @@ private static void StartInteractiveConsoleThread()
189189
Console.WriteLine($"Gen 0: {GC.CollectionCount(0)}, Gen 1: {GC.CollectionCount(1)}, Gen 2: {GC.CollectionCount(2)}");
190190
}
191191
}
192-
});
192+
})
193+
{
194+
IsBackground = true
195+
};
193196

194-
interactiveThread.IsBackground = true;
195197
interactiveThread.Start();
196198

197199
started.WaitOne();

0 commit comments

Comments
 (0)