From b702ae6389775c69939bfcbc7cc95af1ac8efb8c Mon Sep 17 00:00:00 2001
From: Shay Rojansky <roji@roji.org>
Date: Thu, 16 Mar 2023 19:59:29 +0100
Subject: [PATCH] Use separate DB connection pools for read/update in platform
 update benchmark

---
 .../PlatformBenchmarks/Data/RawDb.cs          | 45 ++++++++++++++++---
 1 file changed, 39 insertions(+), 6 deletions(-)

diff --git a/src/BenchmarksApps/TechEmpower/PlatformBenchmarks/Data/RawDb.cs b/src/BenchmarksApps/TechEmpower/PlatformBenchmarks/Data/RawDb.cs
index 9f83617dc..98fb1bd9b 100644
--- a/src/BenchmarksApps/TechEmpower/PlatformBenchmarks/Data/RawDb.cs
+++ b/src/BenchmarksApps/TechEmpower/PlatformBenchmarks/Data/RawDb.cs
@@ -20,7 +20,7 @@ private readonly MemoryCache _cache
             = new(new MemoryCacheOptions { ExpirationScanFrequency = TimeSpan.FromMinutes(60) });
 
 #if NET7_0_OR_GREATER
-        private readonly NpgsqlDataSource _dataSource;
+        private readonly NpgsqlDataSource _dataSource, _updateDataSource, _readOnlyDataSource;
 #else
         private readonly string _connectionString;
 #endif
@@ -30,6 +30,15 @@ public RawDb(ConcurrentRandom random, AppSettings appSettings)
             _random = random;
 #if NET7_0_OR_GREATER
             _dataSource = NpgsqlDataSource.Create(appSettings.ConnectionString);
+
+            // For the update benchmark, we use two different connection pools for read/update, to avoid head-of-line
+            // perf issues.
+            var dataSourceBuilder = new NpgsqlDataSourceBuilder(appSettings.ConnectionString);
+
+            dataSourceBuilder.ConnectionStringBuilder.MaxPoolSize = 18;
+            _readOnlyDataSource = dataSourceBuilder.Build();
+            dataSourceBuilder.ConnectionStringBuilder.MaxPoolSize = 9;
+            _updateDataSource = dataSourceBuilder.Build();
 #else
             _connectionString = appSettings.ConnectionString;
 #endif
@@ -170,14 +179,12 @@ public async Task<World[]> LoadMultipleQueriesRows(int count)
         }
 #endif
 
+#if NET7_0_OR_GREATER
         public async Task<World[]> LoadMultipleUpdatesRows(int count)
         {
             var results = new World[count];
 
-            using var connection = CreateConnection();
-            await connection.OpenAsync();
-
-#if NET7_0_OR_GREATER
+            using (var connection = await _readOnlyDataSource.OpenConnectionAsync())
             using (var batch = new NpgsqlBatch(connection))
             {
                 // Inserts a PG Sync message between each statement in the batch, required for compliance with
@@ -203,7 +210,33 @@ public async Task<World[]> LoadMultipleUpdatesRows(int count)
                     await reader.NextResultAsync();
                 }
             }
+
+            using (var connection = await _updateDataSource.OpenConnectionAsync())
+            using (var updateCmd = new NpgsqlCommand(BatchUpdateString.Query(count), connection))
+            {
+                for (var i = 0; i < results.Length; i++)
+                {
+                    var randomNumber = _random.Next(1, 10001);
+
+                    updateCmd.Parameters.Add(new NpgsqlParameter<int> { TypedValue = results[i].Id });
+                    updateCmd.Parameters.Add(new NpgsqlParameter<int> { TypedValue = randomNumber });
+
+                    results[i].RandomNumber = randomNumber;
+                }
+
+                await updateCmd.ExecuteNonQueryAsync();
+            }
+
+            return results;
+        }
 #else
+        public async Task<World[]> LoadMultipleUpdatesRows(int count)
+        {
+            var results = new World[count];
+
+            using var connection = CreateConnection();
+            await connection.OpenAsync();
+
             var (queryCmd, queryParameter) = CreateReadCommand(connection);
             using (queryCmd)
             {
@@ -213,7 +246,6 @@ public async Task<World[]> LoadMultipleUpdatesRows(int count)
                     queryParameter.TypedValue = _random.Next(1, 10001);
                 }
             }
-#endif
 
             using (var updateCmd = new NpgsqlCommand(BatchUpdateString.Query(count), connection))
             {
@@ -232,6 +264,7 @@ public async Task<World[]> LoadMultipleUpdatesRows(int count)
 
             return results;
         }
+#endif
 
         public async Task<List<Fortune>> LoadFortunesRows()
         {