From 1fc477ac98d30f64bc14805e8132a1d366da70e5 Mon Sep 17 00:00:00 2001 From: Netmentor Date: Sun, 31 Aug 2025 18:06:29 +0100 Subject: [PATCH] test profiler vs 2026 --- BenchmarkSuite1/BenchmarkSuite1.csproj | 18 +++++++ .../ProductsWriteStoreBenchmarks.cs | 52 +++++++++++++++++++ BenchmarkSuite1/Program.cs | 12 +++++ Distribt.sln | 10 +++- .../Properties/launchSettings.json | 2 +- .../DataAccess/ProductsWriteStore.cs | 33 +++++++++--- 6 files changed, 118 insertions(+), 9 deletions(-) create mode 100644 BenchmarkSuite1/BenchmarkSuite1.csproj create mode 100644 BenchmarkSuite1/ProductsWriteStoreBenchmarks.cs create mode 100644 BenchmarkSuite1/Program.cs diff --git a/BenchmarkSuite1/BenchmarkSuite1.csproj b/BenchmarkSuite1/BenchmarkSuite1.csproj new file mode 100644 index 0000000..44499fa --- /dev/null +++ b/BenchmarkSuite1/BenchmarkSuite1.csproj @@ -0,0 +1,18 @@ + + + + net8.0 + Exe + + + + + + + + + + + + + diff --git a/BenchmarkSuite1/ProductsWriteStoreBenchmarks.cs b/BenchmarkSuite1/ProductsWriteStoreBenchmarks.cs new file mode 100644 index 0000000..eb42da6 --- /dev/null +++ b/BenchmarkSuite1/ProductsWriteStoreBenchmarks.cs @@ -0,0 +1,52 @@ +using System; +using System.Threading.Tasks; +using BenchmarkDotNet.Attributes; +using Distribt.Services.Products.BusinessLogic.DataAccess; +using Distribt.Services.Products.Dtos; +using Microsoft.EntityFrameworkCore; + +namespace Benchmarks.Products +{ + [MemoryDiagnoser] + public class ProductsWriteStoreBenchmarks + { + private static DbContextOptions NewOptions() + => new DbContextOptionsBuilder() + .UseInMemoryDatabase(Guid.NewGuid().ToString()) + .Options; + + [Benchmark] + public async Task CreateRecord_Isolated() + { + var options = NewOptions(); + await using var store = new ProductsWriteStore(options); + + var details = new ProductDetails( + Name: "Product-" + Guid.NewGuid().ToString("N"), + Description: "Desc-" + Guid.NewGuid().ToString("N") + ); + + _ = await store.CreateRecord(details); + } + + [Benchmark] + public async Task UpdateProduct_Isolated() + { + var options = NewOptions(); + await using var store = new ProductsWriteStore(options); + + // Seed a product to update in this isolated database + var existingId = await store.CreateRecord(new ProductDetails( + Name: "Seed-" + Guid.NewGuid().ToString("N"), + Description: "Seed-Desc" + )); + + var updateDetails = new ProductDetails( + Name: "Updated-" + Guid.NewGuid().ToString("N"), + Description: "Updated-Desc" + ); + + await store.UpdateProduct(existingId, updateDetails); + } + } +} \ No newline at end of file diff --git a/BenchmarkSuite1/Program.cs b/BenchmarkSuite1/Program.cs new file mode 100644 index 0000000..68e2fdd --- /dev/null +++ b/BenchmarkSuite1/Program.cs @@ -0,0 +1,12 @@ +using BenchmarkDotNet.Running; + +namespace BenchmarkSuite1 +{ + internal class Program + { + static void Main(string[] args) + { + var _ = BenchmarkRunner.Run(typeof(Program).Assembly); + } + } +} diff --git a/Distribt.sln b/Distribt.sln index 7274e8a..dc7a3fa 100644 --- a/Distribt.sln +++ b/Distribt.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 17 -VisualStudioVersion = 17.0.31815.197 +# Visual Studio Version 18 +VisualStudioVersion = 18.0.10928.107 d18.0 MinimumVisualStudioVersion = 10.0.40219.1 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Api", "Api", "{25E556CF-D2DB-4BA2-9379-07CD4976BA9E}" EndProject @@ -93,6 +93,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Discovery", "Discovery", "{ EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Distribt.Test.Shared.Discovery.Tests", "src\Tests\Shared\Discovery\Distribt.Test.Shared.Discovery.Tests\Distribt.Test.Shared.Discovery.Tests.csproj", "{F9C0F635-D488-4E1F-A4AA-912EA8C518B5}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BenchmarkSuite1", "BenchmarkSuite1\BenchmarkSuite1.csproj", "{A20861A9-411E-6150-BF5C-69E8196E5D22}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -211,6 +213,10 @@ Global {F9C0F635-D488-4E1F-A4AA-912EA8C518B5}.Debug|Any CPU.Build.0 = Debug|Any CPU {F9C0F635-D488-4E1F-A4AA-912EA8C518B5}.Release|Any CPU.ActiveCfg = Release|Any CPU {F9C0F635-D488-4E1F-A4AA-912EA8C518B5}.Release|Any CPU.Build.0 = Release|Any CPU + {A20861A9-411E-6150-BF5C-69E8196E5D22}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A20861A9-411E-6150-BF5C-69E8196E5D22}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A20861A9-411E-6150-BF5C-69E8196E5D22}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A20861A9-411E-6150-BF5C-69E8196E5D22}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/src/Services/Products/Distribt.Services.Products.Api.Write/Properties/launchSettings.json b/src/Services/Products/Distribt.Services.Products.Api.Write/Properties/launchSettings.json index b06f58a..5aef3be 100644 --- a/src/Services/Products/Distribt.Services.Products.Api.Write/Properties/launchSettings.json +++ b/src/Services/Products/Distribt.Services.Products.Api.Write/Properties/launchSettings.json @@ -14,7 +14,7 @@ "dotnetRunMessages": true, "launchBrowser": true, "launchUrl": "swagger", - "applicationUrl": "https://localhost:60320;http://localhost:60310", + "applicationUrl": "https://localhost:60321;http://localhost:60311", "environmentVariables": { "ASPNETCORE_ENVIRONMENT": "Development", "VAULT-TOKEN": "vault-distribt-token" diff --git a/src/Services/Products/Distribt.Services.Products.BusinessLogic/DataAccess/ProductsWriteStore.cs b/src/Services/Products/Distribt.Services.Products.BusinessLogic/DataAccess/ProductsWriteStore.cs index 313cc07..01c5868 100644 --- a/src/Services/Products/Distribt.Services.Products.BusinessLogic/DataAccess/ProductsWriteStore.cs +++ b/src/Services/Products/Distribt.Services.Products.BusinessLogic/DataAccess/ProductsWriteStore.cs @@ -17,12 +17,33 @@ public class ProductsWriteStore : DbContext, IProductsWriteStore public ProductsWriteStore(DbContextOptions options) : base(options) { } + + protected override void OnModelCreating(ModelBuilder modelBuilder) + { + base.OnModelCreating(modelBuilder); + + modelBuilder.Entity(b => + { + b.HasKey(p => p.Id); + b.Property(p => p.Id).ValueGeneratedOnAdd(); + b.Property(p => p.Name).IsRequired(false); + b.Property(p => p.Description).IsRequired(false); + b.ToTable("Products"); + }); + } + public async Task UpdateProduct(int id, ProductDetails details) { - var product = await Products.SingleAsync(a => a.Id == id); - product.Description = details.Description; + // Avoid extra round-trip: attach a stub entity and mark only changed properties as modified + var product = new ProductDetailEntity { Id = id }; + Attach(product); + product.Name = details.Name; - + product.Description = details.Description; + + Entry(product).Property(p => p.Name).IsModified = true; + Entry(product).Property(p => p.Description).IsModified = true; + await SaveChangesAsync(); } @@ -34,16 +55,16 @@ public async Task CreateRecord(ProductDetails details) Name = details.Name }; - var result = await Products.AddAsync(newProduct); + Products.Add(newProduct); await SaveChangesAsync(); - return result.Entity.Id ?? throw new ApplicationException("the record has not been inserted in the db"); + return newProduct.Id; } private class ProductDetailEntity { - public int? Id { get; set; } + public int Id { get; set; } public string? Name { get; set; } public string? Description { get; set; } }