From fa58b5a14d5d9fbc924b4c503032615a909346ee Mon Sep 17 00:00:00 2001 From: adimiko Date: Wed, 7 Feb 2024 06:00:48 +0100 Subject: [PATCH] Added benchamark tests --- Directory.Packages.props | 1 + TransactionContext.sln | 7 ++ .../BenchmarkTest.cs | 106 ++++++++++++++++++ .../Program.cs | 3 + ...ansactionContext.Postgres.Benchmark.csproj | 22 ++++ 5 files changed, 139 insertions(+) create mode 100644 tests/TransactionContext.Postgres.Benchmark/BenchmarkTest.cs create mode 100644 tests/TransactionContext.Postgres.Benchmark/Program.cs create mode 100644 tests/TransactionContext.Postgres.Benchmark/TransactionContext.Postgres.Benchmark.csproj diff --git a/Directory.Packages.props b/Directory.Packages.props index 8e66685..ba406ec 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -4,6 +4,7 @@ false + diff --git a/TransactionContext.sln b/TransactionContext.sln index 41eb024..5349eb4 100644 --- a/TransactionContext.sln +++ b/TransactionContext.sln @@ -15,6 +15,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TransactionContext.Postgres EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TransactionContext.Tests.SeedWork", "tests\TransactionContext.Tests.SeedWork\TransactionContext.Tests.SeedWork.csproj", "{6459CE92-7FD3-4FBE-86E8-4C0321B4E694}" EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TransactionContext.Postgres.Benchmark", "tests\TransactionContext.Postgres.Benchmark\TransactionContext.Postgres.Benchmark.csproj", "{8239CE17-8D34-4344-8F67-A071C393F8AD}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -37,6 +39,10 @@ Global {6459CE92-7FD3-4FBE-86E8-4C0321B4E694}.Debug|Any CPU.Build.0 = Debug|Any CPU {6459CE92-7FD3-4FBE-86E8-4C0321B4E694}.Release|Any CPU.ActiveCfg = Release|Any CPU {6459CE92-7FD3-4FBE-86E8-4C0321B4E694}.Release|Any CPU.Build.0 = Release|Any CPU + {8239CE17-8D34-4344-8F67-A071C393F8AD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {8239CE17-8D34-4344-8F67-A071C393F8AD}.Debug|Any CPU.Build.0 = Debug|Any CPU + {8239CE17-8D34-4344-8F67-A071C393F8AD}.Release|Any CPU.ActiveCfg = Release|Any CPU + {8239CE17-8D34-4344-8F67-A071C393F8AD}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -46,6 +52,7 @@ Global {DD81C9E5-5DB6-4032-BD2C-F039300A63DD} = {6004A5FC-0B64-464C-977A-5E721E8567B7} {A7CC7D41-46AF-45D7-95C9-681253CCB885} = {5A6575AC-81E5-4E97-909F-BBE634A2BD14} {6459CE92-7FD3-4FBE-86E8-4C0321B4E694} = {5A6575AC-81E5-4E97-909F-BBE634A2BD14} + {8239CE17-8D34-4344-8F67-A071C393F8AD} = {5A6575AC-81E5-4E97-909F-BBE634A2BD14} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {48C38B93-C350-4CC9-BCDD-CE256D01DD7E} diff --git a/tests/TransactionContext.Postgres.Benchmark/BenchmarkTest.cs b/tests/TransactionContext.Postgres.Benchmark/BenchmarkTest.cs new file mode 100644 index 0000000..819a3f1 --- /dev/null +++ b/tests/TransactionContext.Postgres.Benchmark/BenchmarkTest.cs @@ -0,0 +1,106 @@ +using BenchmarkDotNet.Attributes; +using BenchmarkDotNet.Engines; +using Dapper; +using Microsoft.Extensions.DependencyInjection; +using System.Transactions; +using Testcontainers.PostgreSql; +using TransactionContext.Tests.SeedWork; + +namespace TransactionContext.Postgres.Benchmark +{ + [SimpleJob(RunStrategy.ColdStart, iterationCount: 1000)] + public class BenchmarkTest + { + private readonly PostgreSqlContainer _postgreSqlContainer = new PostgreSqlBuilder().Build(); + + protected IDbConnectionFactory DbConnectionFactory { get; private set; } + + protected IServiceProvider ServiceProvider { get; private set; } + + [GlobalSetup] + public async Task GlobalSetup() + { + await _postgreSqlContainer.StartAsync(); + + var connectionString = _postgreSqlContainer.GetConnectionString(); + + IServiceCollection services = new ServiceCollection(); + + services.AddTransactionContext(x => x.UsePostgres(connectionString)); + + ServiceProvider = services.BuildServiceProvider(); + DbConnectionFactory = ServiceProvider.GetRequiredService(); + + await CreateDb(); + } + + const int NumberOfCustomers = 10; + + [Benchmark] + public async Task DbContextTest() + { + using (var scope = ServiceProvider.CreateScope()) + { + var transactionContext = scope.ServiceProvider.GetRequiredService(); + + for (var i = 0; i < NumberOfCustomers; i++) + { + var customerId = Guid.NewGuid(); + var orderId = Guid.NewGuid(); + + transactionContext.Add(CustomerSQL.Insert, new { CustomerId = customerId, Name = $"name{i}" }); + transactionContext.Add(OrderSQL.Insert, new { OrderId = orderId, CustomerId = customerId }); + + transactionContext.Add(OrderItemSQL.Insert, new { OrderItemId = Guid.NewGuid(), OrderId = orderId, Name = $"Name{i}", Amount = i + 1 }); + transactionContext.Add(OrderItemSQL.Insert, new { OrderItemId = Guid.NewGuid(), OrderId = orderId, Name = $"Name{i}", Amount = i + 1 }); + transactionContext.Add(OrderItemSQL.Insert, new { OrderItemId = Guid.NewGuid(), OrderId = orderId, Name = $"Name{i}", Amount = i + 1 }); + transactionContext.Add(OrderItemSQL.Insert, new { OrderItemId = Guid.NewGuid(), OrderId = orderId, Name = $"Name{i}", Amount = i + 1 }); + } + + await transactionContext.Commit(); + } + } + + [Benchmark] + public async Task TransactionScopeTest() + { + using (TransactionScope scope = new TransactionScope(TransactionScopeAsyncFlowOption.Enabled)) + using (var connection = DbConnectionFactory.Create()) + { + for (var i = 0; i < NumberOfCustomers; i++) + { + var customerId = Guid.NewGuid(); + var orderId = Guid.NewGuid(); + + await connection.ExecuteAsync(CustomerSQL.Insert, new { CustomerId = customerId, Name = $"name{i}" }); + await connection.ExecuteAsync(OrderSQL.Insert, new { OrderId = orderId, CustomerId = customerId }); + + await connection.ExecuteAsync(OrderItemSQL.Insert, new { OrderItemId = Guid.NewGuid(), OrderId = orderId, Name = $"Name{i}", Amount = i + 1 }); + await connection.ExecuteAsync(OrderItemSQL.Insert, new { OrderItemId = Guid.NewGuid(), OrderId = orderId, Name = $"Name{i}", Amount = i + 1 }); + await connection.ExecuteAsync(OrderItemSQL.Insert, new { OrderItemId = Guid.NewGuid(), OrderId = orderId, Name = $"Name{i}", Amount = i + 1 }); + await connection.ExecuteAsync(OrderItemSQL.Insert, new { OrderItemId = Guid.NewGuid(), OrderId = orderId, Name = $"Name{i}", Amount = i + 1 }); + } + + scope.Complete(); + } + } + + [GlobalCleanup] + public Task GlobalCleanup() + { + return _postgreSqlContainer.DisposeAsync().AsTask(); + } + + private async Task CreateDb() + { + const string customerSql = "CREATE TABLE IF NOT EXISTS Customers (CustomerId UUID NOT NULL, Name VARCHAR NOT NULL, PRIMARY KEY (CustomerId))"; + const string orderSql = "CREATE TABLE IF NOT EXISTS Orders (OrderId UUID NOT NULL, CustomerId UUID NOT NULL, PRIMARY KEY (OrderId))"; + const string orderItemSql = "CREATE TABLE IF NOT EXISTS OrderItems (OrderItemId UUID NOT NULL, OrderId UUID NOT NULL, Name VARCHAR NOT NULL, Amount INT NOT NULL, PRIMARY KEY (OrderItemId))"; + using var connection = DbConnectionFactory.Create(); + + await connection.ExecuteAsync(customerSql); + await connection.ExecuteAsync(orderSql); + await connection.ExecuteAsync(orderItemSql); + } + } +} diff --git a/tests/TransactionContext.Postgres.Benchmark/Program.cs b/tests/TransactionContext.Postgres.Benchmark/Program.cs new file mode 100644 index 0000000..b986d99 --- /dev/null +++ b/tests/TransactionContext.Postgres.Benchmark/Program.cs @@ -0,0 +1,3 @@ +using BenchmarkDotNet.Running; + +BenchmarkSwitcher.FromAssembly(typeof(Program).Assembly).Run(args); diff --git a/tests/TransactionContext.Postgres.Benchmark/TransactionContext.Postgres.Benchmark.csproj b/tests/TransactionContext.Postgres.Benchmark/TransactionContext.Postgres.Benchmark.csproj new file mode 100644 index 0000000..2b23cef --- /dev/null +++ b/tests/TransactionContext.Postgres.Benchmark/TransactionContext.Postgres.Benchmark.csproj @@ -0,0 +1,22 @@ + + + + Exe + net8.0 + enable + enable + + + + + + + + + + + + + + +