Browse Source

Use latest version of pgpool2 and reverse batch update to separate statements (#6745)

* Latest version of pgpool2 and optimal number of connections

* Reverse batch update to separate statements

Co-authored-by: LLT21 <[email protected]>
LLT21 4 years ago
parent
commit
236bee597e

+ 10 - 5
frameworks/CSharp/appmpower/appmpower.dockerfile

@@ -46,12 +46,17 @@ RUN apt-get update
 # The following installs standard versions unixodbc 2.3.6 and pgsqlodbc 11
 # The following installs standard versions unixodbc 2.3.6 and pgsqlodbc 11
 #RUN apt-get install -y unixodbc odbc-postgresql
 #RUN apt-get install -y unixodbc odbc-postgresql
 # unixodbc still needs to be installed even if compiled locally
 # unixodbc still needs to be installed even if compiled locally
-RUN apt-get install -y unixodbc
+RUN apt-get install -y unixodbc wget curl libpq-dev build-essential
 
 
-RUN apt-get -yqq install clang zlib1g-dev libkrb5-dev libtinfo5
-RUN apt-get install -y make build-essential libssl-dev zlib1g-dev libbz2-dev \
-   libreadline-dev libsqlite3-dev wget curl llvm libncurses5-dev libncursesw5-dev \
-   xz-utils tk-dev libffi-dev liblzma-dev pgpool2 vim-tiny
+WORKDIR /odbc
+
+RUN curl -L -o pgpool-II-4.2.3.tar.gz https://www.pgpool.net/mediawiki/download.php?f=pgpool-II-4.2.3.tar.gz
+RUN tar -xvf pgpool-II-4.2.3.tar.gz
+
+WORKDIR /odbc/pgpool-II-4.2.3
+RUN ./configure
+RUN make
+RUN make install
 
 
 COPY --from=build /usr/local/unixODBC /usr/local/unixODBC
 COPY --from=build /usr/local/unixODBC /usr/local/unixODBC
 
 

+ 1 - 1
frameworks/CSharp/appmpower/src/Db/PooledConnections.cs

@@ -9,7 +9,7 @@ namespace appMpower.Db
    {
    {
       private static bool _connectionsCreated = false;
       private static bool _connectionsCreated = false;
       private static short _createdConnections = 0;
       private static short _createdConnections = 0;
-      private static short _maxConnections = 400; //Math.Min((byte)Environment.ProcessorCount, (byte)21);
+      private static short _maxConnections = 333;
       private static ConcurrentStack<PooledConnection> _stack = new ConcurrentStack<PooledConnection>();
       private static ConcurrentStack<PooledConnection> _stack = new ConcurrentStack<PooledConnection>();
       private static ConcurrentQueue<TaskCompletionSource<PooledConnection>> _waitingQueue = new ConcurrentQueue<TaskCompletionSource<PooledConnection>>();
       private static ConcurrentQueue<TaskCompletionSource<PooledConnection>> _waitingQueue = new ConcurrentQueue<TaskCompletionSource<PooledConnection>>();
 
 

+ 11 - 9
frameworks/CSharp/appmpower/src/FortunesView.cs

@@ -16,29 +16,31 @@ namespace appMpower
       private readonly static KeyValuePair<string, StringValues> _headerContentType =
       private readonly static KeyValuePair<string, StringValues> _headerContentType =
          new KeyValuePair<string, StringValues>("Content-Type", "text/html; charset=UTF-8");
          new KeyValuePair<string, StringValues>("Content-Type", "text/html; charset=UTF-8");
 
 
-      public static string _fortunesTableStart = "<!DOCTYPE html><html><head><title>Fortunes</title></head><body><table><tr><th>id</th><th>message</th></tr>";
-      public static string _fortunesRowStart = "<tr><td>";
-      public static string _fortunesColumn = "</td><td>";
-      public static string _fortunesRowEnd = "</td></tr>";
-      public static string _fortunesTableEnd = "</table></body></html>";
+      public static char[] _fortunesTableStart = "<!DOCTYPE html><html><head><title>Fortunes</title></head><body><table><tr><th>id</th><th>message</th></tr>".ToCharArray();
+      public static char[] _fortunesRowStart = "<tr><td>".ToCharArray();
+      public static char[] _fortunesColumn = "</td><td>".ToCharArray();
+      public static char[] _fortunesRowEnd = "</td></tr>".ToCharArray();
+      public static char[] _fortunesTableEnd = "</table></body></html>".ToCharArray();
 
 
       public static async Task Render(IHeaderDictionary headerDictionary, PipeWriter pipeWriter, List<Fortune> fortunes)
       public static async Task Render(IHeaderDictionary headerDictionary, PipeWriter pipeWriter, List<Fortune> fortunes)
       {
       {
          headerDictionary.Add(_headerServer);
          headerDictionary.Add(_headerServer);
          headerDictionary.Add(_headerContentType);
          headerDictionary.Add(_headerContentType);
 
 
-         string writer = _fortunesTableStart;
+         var writer = StringBuilderCache.Acquire();
+
+         writer.Append(_fortunesTableStart);
 
 
          foreach (var fortune in fortunes)
          foreach (var fortune in fortunes)
          {
          {
-            writer += _fortunesRowStart + fortune.Id + _fortunesColumn + HttpUtility.HtmlEncode(fortune.Message) + _fortunesRowEnd;
+            writer.Append(_fortunesRowStart).Append(fortune.Id).Append(_fortunesColumn).Append(HttpUtility.HtmlEncode(fortune.Message)).Append(_fortunesRowEnd);
          }
          }
 
 
-         writer += _fortunesTableEnd;
+         writer.Append(_fortunesTableEnd);
 
 
          headerDictionary.Add(new KeyValuePair<string, StringValues>("Content-Length", (writer.Length + 32).ToString()));
          headerDictionary.Add(new KeyValuePair<string, StringValues>("Content-Length", (writer.Length + 32).ToString()));
 
 
-         await pipeWriter.WriteAsync(Encoding.UTF8.GetBytes(writer));
+         await pipeWriter.WriteAsync(Encoding.UTF8.GetBytes(StringBuilderCache.GetStringAndRelease(writer)));
          pipeWriter.Complete();
          pipeWriter.Complete();
       }
       }
    }
    }

+ 4 - 4
frameworks/CSharp/appmpower/src/Microsoft/BatchUpdateString.cs

@@ -37,13 +37,14 @@ namespace PlatformBenchmarks
          //   Enumerable.Range(0, batchSize).ToList().ForEach(i => sb.Append($"UPDATE world SET randomnumber = @Random_{i} WHERE id = @Id_{i};"));
          //   Enumerable.Range(0, batchSize).ToList().ForEach(i => sb.Append($"UPDATE world SET randomnumber = @Random_{i} WHERE id = @Id_{i};"));
          //}
          //}
 
 
+         /* --- this is extremely slow with odbc, probably due to int specification ? 
          sb.Append("UPDATE world SET randomNumber = temp.randomNumber FROM (VALUES ");
          sb.Append("UPDATE world SET randomNumber = temp.randomNumber FROM (VALUES ");
          Enumerable.Range(0, lastIndex).ToList().ForEach(i => sb.Append("(?::int,?::int),"));
          Enumerable.Range(0, lastIndex).ToList().ForEach(i => sb.Append("(?::int,?::int),"));
          //sb.Append("(?::int,?::int) ORDER BY 1) AS temp(id, randomNumber) WHERE temp.id = world.id");
          //sb.Append("(?::int,?::int) ORDER BY 1) AS temp(id, randomNumber) WHERE temp.id = world.id");
          sb.Append("(?::int,?::int)) AS temp(id, randomNumber) WHERE temp.id = world.id");
          sb.Append("(?::int,?::int)) AS temp(id, randomNumber) WHERE temp.id = world.id");
 
 
-         /* --- only for alternative update statement - will be used for MySQL
-         sb.Append("UPDATE world SET randomNumber = CASE id ");
+         /* --- only for alternative update statement - will be used for MySQL */
+         sb.Append("UPDATE world SET randomNumber=CASE id ");
 
 
          for (int i = 0; i < batchSize; i++)
          for (int i = 0; i < batchSize; i++)
          {
          {
@@ -55,12 +56,11 @@ namespace PlatformBenchmarks
 
 
          for (int i = 0; i < lastIndex; i++)
          for (int i = 0; i < lastIndex; i++)
          {
          {
-            sb.Append("?, ");
+            sb.Append("?,");
          }
          }
 
 
          //Enumerable.Range(0, lastIndex).ToList().ForEach(i => sb.Append("?, "));
          //Enumerable.Range(0, lastIndex).ToList().ForEach(i => sb.Append("?, "));
          sb.Append("?)");
          sb.Append("?)");
-         */
 
 
          return _queries[batchSize] = StringBuilderCache.GetStringAndRelease(sb);
          return _queries[batchSize] = StringBuilderCache.GetStringAndRelease(sb);
       }
       }

+ 8 - 8
frameworks/CSharp/appmpower/src/RawDb.cs

@@ -56,7 +56,7 @@ namespace appMpower
          pooledConnection.Open();
          pooledConnection.Open();
 
 
          var pooledCommand = new PooledCommand("SELECT * FROM fortune", pooledConnection);
          var pooledCommand = new PooledCommand("SELECT * FROM fortune", pooledConnection);
-         var dataReader = await pooledCommand.ExecuteReaderAsync(CommandBehavior.SingleResult);
+         var dataReader = await pooledCommand.ExecuteReaderAsync(CommandBehavior.SingleResult & CommandBehavior.SequentialAccess);
 
 
          while (dataReader.Read())
          while (dataReader.Read())
          {
          {
@@ -99,7 +99,7 @@ namespace appMpower
          var ids = PlatformBenchmarks.BatchUpdateString.Ids;
          var ids = PlatformBenchmarks.BatchUpdateString.Ids;
          var randoms = PlatformBenchmarks.BatchUpdateString.Randoms;
          var randoms = PlatformBenchmarks.BatchUpdateString.Randoms;
          // --- only for alternative update statement - will be used for MySQL
          // --- only for alternative update statement - will be used for MySQL
-         //var jds = PlatformBenchmarks.BatchUpdateString.Jds;
+         var jds = PlatformBenchmarks.BatchUpdateString.Jds;
 
 
          for (int i = 0; i < count; i++)
          for (int i = 0; i < count; i++)
          {
          {
@@ -112,10 +112,10 @@ namespace appMpower
          }
          }
 
 
          // --- only for alternative update statement - will be used for MySQL
          // --- only for alternative update statement - will be used for MySQL
-         //for (int i = 0; i < count; i++)
-         //{
-         //   updateCommand.CreateParameter(jds[i], DbType.Int32, worlds[i].Id);
-         //}
+         for (int i = 0; i < count; i++)
+         {
+            updateCommand.CreateParameter(jds[i], DbType.Int32, worlds[i].Id);
+         }
 
 
          await updateCommand.ExecuteNonQueryAsync();
          await updateCommand.ExecuteNonQueryAsync();
 
 
@@ -135,7 +135,7 @@ namespace appMpower
 
 
       private static async Task<World> ReadSingleRow(PooledCommand pooledCommand)
       private static async Task<World> ReadSingleRow(PooledCommand pooledCommand)
       {
       {
-         var dataReader = await pooledCommand.ExecuteReaderAsync(CommandBehavior.SingleRow);
+         var dataReader = await pooledCommand.ExecuteReaderAsync(CommandBehavior.SingleRow & CommandBehavior.SequentialAccess);
 
 
          dataReader.Read();
          dataReader.Read();
 
 
@@ -183,7 +183,7 @@ namespace appMpower
             pooledCommand.CreateParameter(ids[i], DbType.Int32, _random.Next(1, 10001));
             pooledCommand.CreateParameter(ids[i], DbType.Int32, _random.Next(1, 10001));
          }
          }
 
 
-         var dataReader = await pooledCommand.ExecuteReaderAsync(CommandBehavior.Default);
+         var dataReader = await pooledCommand.ExecuteReaderAsync(CommandBehavior.Default & CommandBehavior.SequentialAccess);
 
 
          do
          do
          {
          {