Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 0 additions & 32 deletions src/BenchmarksApps/TechEmpower/PlatformBenchmarks/Data/Random.cs

This file was deleted.

63 changes: 29 additions & 34 deletions src/BenchmarksApps/TechEmpower/PlatformBenchmarks/Data/RawDb.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,14 @@
using System.Threading.Tasks;
using Microsoft.Extensions.Caching.Memory;
using Npgsql;
using NpgsqlTypes;

// ReSharper disable UseAwaitUsing

namespace PlatformBenchmarks
{
public sealed class RawDb
{
private readonly ConcurrentRandom _random;
private readonly MemoryCache _cache
= new(new MemoryCacheOptions { ExpirationScanFrequency = TimeSpan.FromMinutes(60) });

Expand All @@ -25,11 +25,10 @@ private readonly MemoryCache _cache
private readonly string _connectionString;
#endif

public RawDb(ConcurrentRandom random, AppSettings appSettings)
public RawDb(AppSettings appSettings)
{
_random = random;
#if NET8_0_OR_GREATER
_dataSource = new NpgsqlSlimDataSourceBuilder(appSettings.ConnectionString).Build();
_dataSource = new NpgsqlSlimDataSourceBuilder(appSettings.ConnectionString).EnableArrays().Build();
#elif NET7_0
_dataSource = NpgsqlDataSource.Create(appSettings.ConnectionString);
#else
Expand All @@ -53,10 +52,10 @@ public Task<CachedWorld[]> LoadCachedQueries(int count)
var result = new CachedWorld[count];
var cacheKeys = _cacheKeys;
var cache = _cache;
var random = _random;

for (var i = 0; i < result.Length; i++)
{
var id = random.Next(1, 10001);
var id = Random.Shared.Next(1, 10001);
var key = cacheKeys[id];
if (cache.TryGetValue(key, out var cached))
{
Expand Down Expand Up @@ -88,7 +87,7 @@ static async Task<CachedWorld[]> LoadUncachedQueries(int id, int i, int count, R
{
result[i] = await rawdb._cache.GetOrCreateAsync(key, create);

id = rawdb._random.Next(1, 10001);
id = Random.Shared.Next(1, 10001);
idParameter.TypedValue = id;
key = cacheKeys[id];
}
Expand Down Expand Up @@ -136,7 +135,7 @@ public async Task<World[]> LoadMultipleQueriesRows(int count)
batch.BatchCommands.Add(new()
{
CommandText = "SELECT id, randomnumber FROM world WHERE id = $1",
Parameters = { new NpgsqlParameter<int> { TypedValue = _random.Next(1, 10001) } }
Parameters = { new NpgsqlParameter<int> { TypedValue = Random.Shared.Next(1, 10001) } }
});
}

Expand Down Expand Up @@ -165,7 +164,7 @@ public async Task<World[]> LoadMultipleQueriesRows(int count)
for (var i = 0; i < results.Length; i++)
{
results[i] = await ReadSingleRow(cmd);
idParameter.TypedValue = _random.Next(1, 10001);
idParameter.TypedValue = Random.Shared.Next(1, 10001);
}

return results;
Expand All @@ -176,23 +175,29 @@ public async Task<World[]> LoadMultipleUpdatesRows(int count)
{
var results = new World[count];

var ids = new int[count];
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Given how small this array is, could we stackalloc it?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right here probably (I had tried on the update method at first), there is a MemoryExtensions method to do that on spans.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Got confused by the diff but we can't do this in the updates scenario because we need to pass the ids array as a parameter.

https://github.com/aspnet/Benchmarks/pull/2132/files#diff-c1e1042637f371e2cbc5f6e975883c9c038a0b0de7d30c4e7c55b5bfa45c0f5aR225

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ArrayPool then?

for (var i = 0; i < count; i++)
{
ids[i] = Random.Shared.Next(1, 10001);
}
Array.Sort(ids);

using var connection = CreateConnection();
await connection.OpenAsync();

#if NET7_0_OR_GREATER
using (var batch = new NpgsqlBatch(connection))
{
// Inserts a PG Sync message between each statement in the batch, required for compliance with
// TechEmpower general test requirement 7
// https://github.com/TechEmpower/FrameworkBenchmarks/wiki/Project-Information-Framework-Tests-Overview
batch.EnableErrorBarriers = true;

for (var i = 0; i < count; i++)
{
batch.BatchCommands.Add(new()
{
CommandText = "SELECT id, randomnumber FROM world WHERE id = $1",
Parameters = { new NpgsqlParameter<int> { TypedValue = _random.Next(1, 10001) } }
Parameters = { new NpgsqlParameter<int> { TypedValue = ids[i] } }
});
}

Expand All @@ -205,32 +210,22 @@ public async Task<World[]> LoadMultipleUpdatesRows(int count)
await reader.NextResultAsync();
}
}
#else
var (queryCmd, queryParameter) = CreateReadCommand(connection);
using (queryCmd)
{
for (var i = 0; i < results.Length; i++)
{
results[i] = await ReadSingleRow(queryCmd);
queryParameter.TypedValue = _random.Next(1, 10001);
}
}
#endif

using (var updateCmd = new NpgsqlCommand(BatchUpdateString.Query(count), connection))
var numbers = new int[count];
for (var i = 0; i < count; i++)
{
for (var i = 0; i < results.Length; i++)
{
var randomNumber = _random.Next(1, 10001);
var randomNumber = Random.Shared.Next(1, 10001);
results[i].RandomNumber = randomNumber;
numbers[i] = randomNumber;
}

updateCmd.Parameters.Add(new NpgsqlParameter<int> { TypedValue = results[i].Id });
updateCmd.Parameters.Add(new NpgsqlParameter<int> { TypedValue = randomNumber });
var update = "UPDATE world w SET randomnumber = u.new_val FROM (SELECT unnest($1) as id, unnest($2) as new_val) u WHERE w.id = u.id";

results[i].RandomNumber = randomNumber;
}
using var updateCmd = new NpgsqlCommand(update, connection);
updateCmd.Parameters.Add(new NpgsqlParameter<int[]> { TypedValue = ids, NpgsqlDbType = NpgsqlDbType.Array | NpgsqlDbType.Integer });
updateCmd.Parameters.Add(new NpgsqlParameter<int[]> { TypedValue = numbers, NpgsqlDbType = NpgsqlDbType.Array | NpgsqlDbType.Integer });

await updateCmd.ExecuteNonQueryAsync();
}
await updateCmd.ExecuteNonQueryAsync();

return results;
}
Expand Down Expand Up @@ -293,7 +288,7 @@ public Task<List<FortuneUtf8>> LoadFortunesRowsNoDb()
private (NpgsqlCommand readCmd, NpgsqlParameter<int> idParameter) CreateReadCommand(NpgsqlConnection connection)
{
var cmd = new NpgsqlCommand("SELECT id, randomnumber FROM world WHERE id = $1", connection);
var parameter = new NpgsqlParameter<int> { TypedValue = _random.Next(1, 10001) };
var parameter = new NpgsqlParameter<int> { TypedValue = Random.Shared.Next(1, 10001) };

cmd.Parameters.Add(parameter);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ public static IWebHost BuildWebHost(string[] args)

if (appSettings.Database == DatabaseServer.PostgreSql)
{
BenchmarkApplication.RawDb = new RawDb(new ConcurrentRandom(), appSettings);
BenchmarkApplication.RawDb = new RawDb(appSettings);
BenchmarkApplication.DapperDb = new DapperDb(appSettings);
BenchmarkApplication.EfDb = new EfDb(appSettings);
}
Expand Down
98 changes: 98 additions & 0 deletions src/BenchmarksApps/TechEmpower/apphost.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
#:sdk Aspire.AppHost.Sdk@13.0.0

var builder = DistributedApplication.CreateBuilder(args);

// Add the postgres database from Dockerfile
var postgres = builder.AddDockerfile("postgres-techempower", "../../../docker/postgres-techempower")
.WithEndpoint(port: 5432, targetPort: 5432, name: "tcp")
.WithEnvironment("POSTGRES_USER", "benchmarkdbuser")
.WithEnvironment("POSTGRES_PASSWORD", "benchmarkdbpass")
.WithEnvironment("POSTGRES_DB", "hello_world");

var postgresEndpoint = postgres.GetEndpoint("tcp");
var connectionString = ReferenceExpression.Create($"Server={postgresEndpoint.Property(EndpointProperty.Host)};Port={postgresEndpoint.Property(EndpointProperty.Port)};Database=hello_world;User Id=benchmarkdbuser;Password=benchmarkdbpass");

// Add all TechEmpower benchmark applications
// Note: BlazorSSR, Minimal, Mvc only support net8.0. MvcFull targets .NET Framework 4.8.
// PlatformBenchmarks and RazorPages support net8.0;net9.0 multi-targeting.

builder.AddProject("blazorssr", "BlazorSSR/BlazorSSR.csproj")
.WaitFor(postgres)
.WithEnvironment("ConnectionString", connectionString)
.WithUrls(context =>
{
var http = context.GetEndpoint("http");
if (http is not null)
{
context.Urls.Add(new() { Url = $"{http.Url}/plaintext", DisplayText = "plaintext" });
context.Urls.Add(new() { Url = $"{http.Url}/json", DisplayText = "json" });
context.Urls.Add(new() { Url = $"{http.Url}/fortunes", DisplayText = "fortunes" });
context.Urls.Add(new() { Url = $"{http.Url}/updates/20", DisplayText = "updates" });
}
});

builder.AddProject("minimal", "Minimal/Minimal.csproj")
.WaitFor(postgres)
.WithEnvironment("ConnectionString", connectionString)
.WithUrls(context =>
{
var http = context.GetEndpoint("http");
if (http is not null)
{
context.Urls.Add(new() { Url = $"{http.Url}/plaintext", DisplayText = "plaintext" });
context.Urls.Add(new() { Url = $"{http.Url}/json", DisplayText = "json" });
context.Urls.Add(new() { Url = $"{http.Url}/fortunes", DisplayText = "fortunes" });
context.Urls.Add(new() { Url = $"{http.Url}/updates/20", DisplayText = "updates" });
}
});

builder.AddProject("mvc", "Mvc/Mvc.csproj")
.WaitFor(postgres)
.WithEnvironment("ConnectionString", connectionString)
.WithUrls(context =>
{
var http = context.GetEndpoint("http");
if (http is not null)
{
context.Urls.Add(new() { Url = $"{http.Url}/plaintext", DisplayText = "plaintext" });
context.Urls.Add(new() { Url = $"{http.Url}/json", DisplayText = "json" });
context.Urls.Add(new() { Url = $"{http.Url}/fortunes", DisplayText = "fortunes" });
context.Urls.Add(new() { Url = $"{http.Url}/updates/20", DisplayText = "updates" });
}
});

builder.AddProject("platformbenchmarks", "PlatformBenchmarks/PlatformBenchmarks.csproj")
.WaitFor(postgres)
.WithEnvironment("ConnectionString", connectionString)
.WithArgs("--framework", "net9.0")
.WithArgs("-p:IsDatabase=true")
.WithEnvironment("DATABASE", "PostgreSql")
.WithUrls(context =>
{
var http = context.GetEndpoint("http");
if (http is not null)
{
context.Urls.Add(new() { Url = $"{http.Url}/plaintext", DisplayText = "plaintext" });
context.Urls.Add(new() { Url = $"{http.Url}/json", DisplayText = "json" });
context.Urls.Add(new() { Url = $"{http.Url}/fortunes", DisplayText = "fortunes" });
context.Urls.Add(new() { Url = $"{http.Url}/updates/20", DisplayText = "updates" });
}
});

builder.AddProject("razorpages", "RazorPages/RazorPages.csproj")
.WaitFor(postgres)
.WithEnvironment("ConnectionString", connectionString)
.WithArgs("--framework", "net9.0")
.WithUrls(context =>
{
var http = context.GetEndpoint("http");
if (http is not null)
{
context.Urls.Add(new() { Url = $"{http.Url}/plaintext", DisplayText = "plaintext" });
context.Urls.Add(new() { Url = $"{http.Url}/json", DisplayText = "json" });
context.Urls.Add(new() { Url = $"{http.Url}/fortunes", DisplayText = "fortunes" });
context.Urls.Add(new() { Url = $"{http.Url}/updates/20", DisplayText = "updates" });
}
});

builder.Build().Run();
31 changes: 31 additions & 0 deletions src/BenchmarksApps/TechEmpower/apphost.run.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
{
"$schema": "https://json.schemastore.org/launchsettings.json",
"profiles": {
"https": {
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": true,
"applicationUrl": "https://localhost:17005;http://localhost:15223",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development",
"DOTNET_ENVIRONMENT": "Development",
"ASPIRE_DASHBOARD_OTLP_ENDPOINT_URL": "https://localhost:21012",
"ASPIRE_DASHBOARD_MCP_ENDPOINT_URL": "https://localhost:23127",
"ASPIRE_RESOURCE_SERVICE_ENDPOINT_URL": "https://localhost:22253"
}
},
"http": {
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": true,
"applicationUrl": "http://localhost:15223",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development",
"DOTNET_ENVIRONMENT": "Development",
"ASPIRE_DASHBOARD_OTLP_ENDPOINT_URL": "http://localhost:19080",
"ASPIRE_DASHBOARD_MCP_ENDPOINT_URL": "http://localhost:18252",
"ASPIRE_RESOURCE_SERVICE_ENDPOINT_URL": "http://localhost:20285"
}
}
}
}
Loading