Browse Source

Merge branch 'master' of https://github.com/TechEmpower/FrameworkBenchmarks

jaguililla 8 months ago
parent
commit
f236c8b2f9
100 changed files with 961 additions and 733 deletions
  1. 15 0
      frameworks/C++/poco/README.md
  2. 10 1
      frameworks/C++/poco/benchmark.cpp
  3. 6 6
      frameworks/C++/poco/poco.dockerfile
  4. 5 3
      frameworks/CSharp/appmpower/appmpower-odbc-my.dockerfile
  5. 7 3
      frameworks/CSharp/appmpower/appmpower-odbc-pg.dockerfile
  6. 2 2
      frameworks/CSharp/appmpower/appmpower.dockerfile
  7. 59 0
      frameworks/CSharp/appmpower/src/appMpower.Orm/NativeMethods.cs
  8. 24 0
      frameworks/CSharp/appmpower/src/appMpower.Orm/Serializers/FortunesSerializer.cs
  9. 2 2
      frameworks/CSharp/appmpower/src/appMpower.Orm/appMpower.Orm.csproj
  10. 115 0
      frameworks/CSharp/appmpower/src/appMpower/Middleware/FortunesMiddleware.cs
  11. 22 0
      frameworks/CSharp/appmpower/src/appMpower/Objects/Fortune.cs
  12. 2 0
      frameworks/CSharp/appmpower/src/appMpower/Slices/Fortunes.cshtml
  13. 10 0
      frameworks/CSharp/appmpower/src/appMpower/Slices/_ViewImports.cshtml
  14. 2 1
      frameworks/CSharp/appmpower/src/appMpower/appMpower.csproj
  15. 1 1
      frameworks/CSharp/aspnetcore/README.md
  16. 1 1
      frameworks/CSharp/aspnetcore/appsettings.postgresql.json
  17. 3 3
      frameworks/CSharp/aspnetcore/aspnetcore-aot.dockerfile
  18. 5 2
      frameworks/CSharp/aspnetcore/aspnetcore-minimal.dockerfile
  19. 5 2
      frameworks/CSharp/aspnetcore/aspnetcore-mvc.dockerfile
  20. 5 2
      frameworks/CSharp/aspnetcore/aspnetcore-mysql.dockerfile
  21. 6 3
      frameworks/CSharp/aspnetcore/aspnetcore.dockerfile
  22. 1 0
      frameworks/CSharp/aspnetcore/benchmark_config.json
  23. 4 4
      frameworks/CSharp/aspnetcore/src/Minimal/Minimal.csproj
  24. 6 8
      frameworks/CSharp/aspnetcore/src/Minimal/Program.cs
  25. 0 0
      frameworks/CSharp/aspnetcore/src/Minimal/Slices/Fortunes.cshtml
  26. 0 0
      frameworks/CSharp/aspnetcore/src/Minimal/Slices/_ViewImports.cshtml
  27. 3 3
      frameworks/CSharp/aspnetcore/src/Mvc/Mvc.csproj
  28. 1 1
      frameworks/CSharp/aspnetcore/src/Platform/BenchmarkApplication.Caching.cs
  29. 7 8
      frameworks/CSharp/aspnetcore/src/Platform/BenchmarkApplication.Fortunes.cs
  30. 4 4
      frameworks/CSharp/aspnetcore/src/Platform/BenchmarkApplication.HttpConnection.cs
  31. 1 1
      frameworks/CSharp/aspnetcore/src/Platform/BenchmarkApplication.Json.cs
  32. 1 1
      frameworks/CSharp/aspnetcore/src/Platform/BenchmarkApplication.MultipleQueries.cs
  33. 1 1
      frameworks/CSharp/aspnetcore/src/Platform/BenchmarkApplication.Plaintext.cs
  34. 1 1
      frameworks/CSharp/aspnetcore/src/Platform/BenchmarkApplication.SingleQuery.cs
  35. 1 1
      frameworks/CSharp/aspnetcore/src/Platform/BenchmarkApplication.Updates.cs
  36. 7 12
      frameworks/CSharp/aspnetcore/src/Platform/BenchmarkApplication.cs
  37. 35 8
      frameworks/CSharp/aspnetcore/src/Platform/ChunkedPipeWriter.cs
  38. 8 9
      frameworks/CSharp/aspnetcore/src/Platform/Platform.csproj
  39. 0 1
      frameworks/CSharp/aspnetcore/src/Platform/Program.cs
  40. 36 38
      frameworks/CSharp/genhttp/Benchmarks/Benchmarks.csproj
  41. 23 32
      frameworks/CSharp/genhttp/Benchmarks/Model/DatabaseContext.cs
  42. 10 18
      frameworks/CSharp/genhttp/Benchmarks/Model/Fortune.cs
  43. 9 12
      frameworks/CSharp/genhttp/Benchmarks/Model/World.cs
  44. 16 31
      frameworks/CSharp/genhttp/Benchmarks/Program.cs
  45. 0 7
      frameworks/CSharp/genhttp/Benchmarks/Resources/Fortunes.html
  46. 16 3
      frameworks/CSharp/genhttp/Benchmarks/Resources/Template.html
  47. 54 54
      frameworks/CSharp/genhttp/Benchmarks/Tests/CacheResource.cs
  48. 10 18
      frameworks/CSharp/genhttp/Benchmarks/Tests/DbResource.cs
  49. 48 79
      frameworks/CSharp/genhttp/Benchmarks/Tests/FortuneHandler.cs
  50. 11 12
      frameworks/CSharp/genhttp/Benchmarks/Tests/JsonResource.cs
  51. 27 30
      frameworks/CSharp/genhttp/Benchmarks/Tests/QueryResource.cs
  52. 39 41
      frameworks/CSharp/genhttp/Benchmarks/Tests/UpdateResource.cs
  53. 4 8
      frameworks/CSharp/genhttp/Benchmarks/Utilities/ServerHeader.cs
  54. 23 36
      frameworks/CSharp/genhttp/Benchmarks/Utilities/ServerHeaderConcern.cs
  55. 4 12
      frameworks/CSharp/genhttp/Benchmarks/Utilities/ServerHeaderConcernBuilder.cs
  56. 2 2
      frameworks/CSharp/genhttp/README.md
  57. 1 1
      frameworks/CSharp/genhttp/benchmark_config.json
  58. 1 1
      frameworks/CSharp/genhttp/config.toml
  59. 13 13
      frameworks/CSharp/genhttp/genhttp.dockerfile
  60. 2 2
      frameworks/CSharp/reaper/reaper.dockerfile
  61. 3 3
      frameworks/CSharp/reaper/src/Benchmark/Benchmark.csproj
  62. 3 2
      frameworks/CSharp/reaper/src/Benchmark/JsonEndpoint.cs
  63. 3 2
      frameworks/CSharp/reaper/src/Benchmark/PlainTextEndpoint.cs
  64. 1 10
      frameworks/CSharp/reaper/src/Benchmark/Program.cs
  65. 1 1
      frameworks/CSharp/reaper/src/Benchmark/appsettings.Development.json
  66. 1 1
      frameworks/Crystal/kemal/kemal.dockerfile
  67. 1 1
      frameworks/Crystal/kemal/shard.lock
  68. 1 1
      frameworks/Crystal/kemal/shard.yml
  69. 2 2
      frameworks/Crystal/lucky/lucky.dockerfile
  70. 3 3
      frameworks/Crystal/lucky/shard.lock
  71. 12 10
      frameworks/Elixir/phoenix/config/dev.exs
  72. 4 1
      frameworks/Elixir/phoenix/config/prod.exs
  73. 0 3
      frameworks/Elixir/phoenix/lib/hello_web.ex
  74. 1 1
      frameworks/Elixir/phoenix/lib/hello_web/controllers/page_controller.ex
  75. 0 24
      frameworks/Elixir/phoenix/lib/hello_web/gettext.ex
  76. 1 3
      frameworks/Elixir/phoenix/mix.exs
  77. 11 18
      frameworks/Elixir/phoenix/mix.lock
  78. 2 0
      frameworks/Elixir/phoenix/phoenix.dockerfile
  79. 4 2
      frameworks/FSharp/oxpecker/oxpecker.dockerfile
  80. 6 6
      frameworks/FSharp/oxpecker/src/App/App.fsproj
  81. 4 2
      frameworks/FSharp/oxpecker/src/App/Common.fs
  82. 15 12
      frameworks/FSharp/oxpecker/src/App/Db.fs
  83. 13 26
      frameworks/FSharp/oxpecker/src/App/Program.fs
  84. 20 9
      frameworks/FSharp/oxpecker/src/App/RenderHelpers.fs
  85. 4 4
      frameworks/Go/fiber/src/go.mod
  86. 8 8
      frameworks/Go/fiber/src/go.sum
  87. 1 1
      frameworks/Go/goravel/src/fiber/go.mod
  88. 2 1
      frameworks/Go/goravel/src/fiber/go.sum
  89. 1 1
      frameworks/Go/goravel/src/gin/go.mod
  90. 2 1
      frameworks/Go/goravel/src/gin/go.sum
  91. 4 4
      frameworks/Go/hertz/go.mod
  92. 8 8
      frameworks/Go/hertz/go.sum
  93. 11 0
      frameworks/Go/pine/README.md
  94. 26 0
      frameworks/Go/pine/benchmark_config.json
  95. 10 0
      frameworks/Go/pine/pine.dockerfile
  96. 5 0
      frameworks/Go/pine/src/go.mod
  97. 2 0
      frameworks/Go/pine/src/go.sum
  98. 28 0
      frameworks/Go/pine/src/main.go
  99. 0 8
      frameworks/Java/helidon/nima/src/main/java/io/helidon/benchmark/nima/models/DbRepository.java
  100. 0 9
      frameworks/Java/helidon/nima/src/main/java/io/helidon/benchmark/nima/models/HikariJdbcRepository.java

+ 15 - 0
frameworks/C++/poco/README.md

@@ -0,0 +1,15 @@
+# POCO C++ Libraries Benchmarking Test
+
+- [POCO Github Repository](https://github.com/pocoproject/poco)
+- [POCO Website](https://pocoproject.org/)
+
+## Software Versions
+
+- [buildpack-deps noble](https://hub.docker.com/_/buildpack-deps)
+- [g++ 14](https://gcc.gnu.org/gcc-14/)
+- [c++17](https://en.cppreference.com/w/cpp/17)
+- [POCO 1.13.1](https://pocoproject.org/releases/poco-1.13.1/poco-1.13.1-all.zip)
+ 
+## Test URLs
+
+- `PLAINTEXT` - [http://127.0.0.1:8080/plaintext](http://127.0.0.1:8080/plaintext) 

+ 10 - 1
frameworks/C++/poco/benchmark.cpp

@@ -6,6 +6,8 @@
 #include <Poco/Net/HTTPServerRequest.h>
 #include <Poco/Net/HTTPServerRequest.h>
 #include <Poco/Net/HTTPServerResponse.h>
 #include <Poco/Net/HTTPServerResponse.h>
 #include <Poco/Util/ServerApplication.h>
 #include <Poco/Util/ServerApplication.h>
+#include <Poco/Timespan.h>
+#include <Poco/Thread.h>
 
 
 #include <iostream>
 #include <iostream>
 #include <string>
 #include <string>
@@ -15,7 +17,9 @@
 #define PLAIN_CONTENT_TYPE   "text/plain"
 #define PLAIN_CONTENT_TYPE   "text/plain"
 #define RES_BODY             "Hello, World!"
 #define RES_BODY             "Hello, World!"
 #define SERVER_NAME          "poco"
 #define SERVER_NAME          "poco"
+#define MAX_CONNECTIONS      16384
 
 
+using namespace Poco;
 using namespace Poco::Net;
 using namespace Poco::Net;
 using namespace Poco::Util;
 using namespace Poco::Util;
 using namespace std;
 using namespace std;
@@ -58,7 +62,12 @@ protected:
         HTTPServerParams* hsp = new HTTPServerParams;
         HTTPServerParams* hsp = new HTTPServerParams;
         hsp->setMaxThreads(stoi(args[1]));
         hsp->setMaxThreads(stoi(args[1]));
         hsp->setKeepAlive(true);
         hsp->setKeepAlive(true);
-        HTTPServer s(new MyRequestHandlerFactory, ServerSocket(stoi(args[0]), 4000), hsp);
+        hsp->setMaxKeepAliveRequests(MAX_CONNECTIONS);
+        hsp->setMaxQueued(MAX_CONNECTIONS);
+        hsp->setThreadPriority(Thread::PRIO_HIGHEST);
+        ServerSocket socket(stoi(args[0]), MAX_CONNECTIONS);
+        socket.setBlocking(false);
+        HTTPServer s(new MyRequestHandlerFactory, socket, hsp);
         s.start();
         s.start();
         waitForTerminationRequest();
         waitForTerminationRequest();
         s.stop();
         s.stop();

+ 6 - 6
frameworks/C++/poco/poco.dockerfile

@@ -1,11 +1,11 @@
-FROM buildpack-deps:xenial
+FROM buildpack-deps:noble
 
 
 RUN apt-get update -yqq && apt-get install -yqq software-properties-common unzip cmake
 RUN apt-get update -yqq && apt-get install -yqq software-properties-common unzip cmake
 
 
-RUN apt-get install -yqq g++-4.8 libjson0-dev
-RUN update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-4.8 50
+RUN apt-get install -yqq g++-14
+RUN update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-14 50
 
 
-ENV POCO_VERSION 1.6.1
+ENV POCO_VERSION 1.13.3
 ENV POCO_HOME /poco
 ENV POCO_HOME /poco
 
 
 WORKDIR ${POCO_HOME}
 WORKDIR ${POCO_HOME}
@@ -20,10 +20,10 @@ ENV LD_LIBRARY_PATH ${POCO_HOME}/lib/Linux/x86_64
 
 
 COPY benchmark.cpp benchmark.cpp
 COPY benchmark.cpp benchmark.cpp
 
 
-RUN g++-4.8 \
+RUN g++-14 \
     -O3 \
     -O3 \
     -DNDEBUG \
     -DNDEBUG \
-    -std=c++0x \
+    -std=c++17 \
     -o \
     -o \
     poco \
     poco \
     benchmark.cpp \
     benchmark.cpp \

+ 5 - 3
frameworks/CSharp/appmpower/appmpower-odbc-my.dockerfile

@@ -1,4 +1,4 @@
-FROM mcr.microsoft.com/dotnet/sdk:8.0.100 AS build
+FROM mcr.microsoft.com/dotnet/sdk:9.0.100 AS build
 RUN apt-get update
 RUN apt-get update
 RUN apt-get -yqq install clang zlib1g-dev
 RUN apt-get -yqq install clang zlib1g-dev
 RUN apt-get update
 RUN apt-get update
@@ -8,12 +8,12 @@ COPY src .
 RUN dotnet publish -c Release -o out /p:Database=mysql
 RUN dotnet publish -c Release -o out /p:Database=mysql
 
 
 # Construct the actual image that will run
 # Construct the actual image that will run
-FROM mcr.microsoft.com/dotnet/aspnet:8.0.0 AS runtime
+FROM mcr.microsoft.com/dotnet/aspnet:9.0.0 AS runtime
 
 
 RUN apt-get update
 RUN apt-get update
 # The following installs standard versions unixodbc and pgsqlodbc
 # The following installs standard versions unixodbc and pgsqlodbc
 # 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 wget curl
+RUN apt-get install -y unixodbc-dev unixodbc wget curl
 RUN apt-get update
 RUN apt-get update
 
 
 WORKDIR /odbc
 WORKDIR /odbc
@@ -45,6 +45,8 @@ WORKDIR /app
 COPY --from=build /app/out ./
 COPY --from=build /app/out ./
 
 
 RUN cp /usr/lib/libm* /app
 RUN cp /usr/lib/libm* /app
+#RUN cp /usr/lib/aarch64-linux-gnu/libodbc* /app
+RUN cp /usr/lib/x86_64-linux-gnu/libodbc* /app
 
 
 EXPOSE 8080
 EXPOSE 8080
 
 

+ 7 - 3
frameworks/CSharp/appmpower/appmpower-odbc-pg.dockerfile

@@ -1,4 +1,4 @@
-FROM mcr.microsoft.com/dotnet/sdk:8.0.100 AS build
+FROM mcr.microsoft.com/dotnet/sdk:9.0.100 AS build
 RUN apt-get update
 RUN apt-get update
 RUN apt-get -yqq install clang zlib1g-dev libkrb5-dev libtinfo5
 RUN apt-get -yqq install clang zlib1g-dev libkrb5-dev libtinfo5
 
 
@@ -7,10 +7,10 @@ COPY src .
 RUN dotnet publish -c Release -o out /p:Database=postgresql
 RUN dotnet publish -c Release -o out /p:Database=postgresql
 
 
 # Construct the actual image that will run
 # Construct the actual image that will run
-FROM mcr.microsoft.com/dotnet/aspnet:8.0.0 AS runtime
+FROM mcr.microsoft.com/dotnet/aspnet:9.0.0 AS runtime
 
 
 RUN apt-get update
 RUN apt-get update
-RUN apt-get install -y unixodbc odbc-postgresql
+RUN apt-get install -y unixodbc-dev unixodbc odbc-postgresql
 # unixodbc still needs to be installed even if compiled locally
 # unixodbc still needs to be installed even if compiled locally
 
 
 ENV PATH=/usr/local/unixODBC/bin:$PATH
 ENV PATH=/usr/local/unixODBC/bin:$PATH
@@ -27,6 +27,10 @@ ENV ASPNETCORE_URLS http://+:8080
 WORKDIR /app
 WORKDIR /app
 COPY --from=build /app/out ./
 COPY --from=build /app/out ./
 
 
+#RUN cp /usr/lib/aarch64-linux-gnu/libodbc* /app
+RUN cp /usr/lib/x86_64-linux-gnu/libodbc* /app
+
+
 EXPOSE 8080
 EXPOSE 8080
 
 
 ENTRYPOINT ["./appMpower"]
 ENTRYPOINT ["./appMpower"]

+ 2 - 2
frameworks/CSharp/appmpower/appmpower.dockerfile

@@ -1,4 +1,4 @@
-FROM mcr.microsoft.com/dotnet/sdk:8.0.100 AS build
+FROM mcr.microsoft.com/dotnet/sdk:9.0.100 AS build
 RUN apt-get update
 RUN apt-get update
 RUN apt-get -yqq install clang zlib1g-dev libkrb5-dev libtinfo5
 RUN apt-get -yqq install clang zlib1g-dev libkrb5-dev libtinfo5
 
 
@@ -8,7 +8,7 @@ COPY src .
 RUN dotnet publish -c Release -o out
 RUN dotnet publish -c Release -o out
 
 
 # Construct the actual image that will run
 # Construct the actual image that will run
-FROM mcr.microsoft.com/dotnet/aspnet:8.0.0 AS runtime
+FROM mcr.microsoft.com/dotnet/aspnet:9.0.0 AS runtime
 # Full PGO
 # Full PGO
 ENV DOTNET_TieredPGO 1 
 ENV DOTNET_TieredPGO 1 
 ENV DOTNET_TC_QuickJitForLoops 1 
 ENV DOTNET_TC_QuickJitForLoops 1 

+ 59 - 0
frameworks/CSharp/appmpower/src/appMpower.Orm/NativeMethods.cs

@@ -17,6 +17,9 @@ public static class NativeMethods
 
 
     private readonly static WorldSerializer _worldSerializer = new WorldSerializer();
     private readonly static WorldSerializer _worldSerializer = new WorldSerializer();
     private readonly static WorldsSerializer _worldsSerializer = new WorldsSerializer();
     private readonly static WorldsSerializer _worldsSerializer = new WorldsSerializer();
+    private readonly static FortunesSerializer _fortunesSerializer = new FortunesSerializer();
+    private static readonly byte[] _delimiter = new byte[] { 0xFF, 0xFF, 0xFF, 0xFF };
+
 
 
     [UnmanagedCallersOnly(EntryPoint = "Dbms")]
     [UnmanagedCallersOnly(EntryPoint = "Dbms")]
     public static void Dbms(int dbms)
     public static void Dbms(int dbms)
@@ -66,6 +69,7 @@ public static class NativeMethods
         */
         */
     }
     }
 
 
+    /*
     [UnmanagedCallersOnly(EntryPoint = "Fortunes")]
     [UnmanagedCallersOnly(EntryPoint = "Fortunes")]
     public static unsafe IntPtr Fortunes(int* length, IntPtr* handlePointer)
     public static unsafe IntPtr Fortunes(int* length, IntPtr* handlePointer)
     {
     {
@@ -81,6 +85,61 @@ public static class NativeMethods
 
 
         return byteArrayPointer;
         return byteArrayPointer;
     }
     }
+    */
+
+    [UnmanagedCallersOnly(EntryPoint = "Fortunes")]
+    public static unsafe IntPtr Fortunes(int* length, IntPtr* handlePointer)
+    {
+        List<Fortune> fortunes = RawDb.LoadFortunesRows().GetAwaiter().GetResult(); 
+
+        int totalSize = 0;
+
+        foreach (var fortune in fortunes)
+        {
+            totalSize += sizeof(int) // for Id
+                       + Encoding.UTF8.GetByteCount(fortune.Message ?? "") // for Message
+                       + _delimiter.Length; // for delimiter
+        }
+
+        // Allocate the total buffer
+        byte[] buffer = new byte[totalSize];
+        int offset = 0;
+
+        // Write each object to the buffer
+        foreach (var fortune in fortunes)
+        {
+            // Write Id
+            BitConverter.TryWriteBytes(buffer.AsSpan(offset, sizeof(int)), fortune.Id);
+            offset += sizeof(int);
+
+            // Write Message
+            int descriptionLength = Encoding.UTF8.GetBytes(fortune.Message ?? "", buffer.AsSpan(offset));
+            offset += descriptionLength;
+
+            // Write Delimiter
+            _delimiter.CopyTo(buffer, offset);
+            offset += _delimiter.Length;
+        }
+
+        byte[] byteArray = buffer.ToArray();
+        *length = byteArray.Length; 
+
+        /*
+        var memoryStream = new MemoryStream();
+        using var utf8JsonWriter = new Utf8JsonWriter(memoryStream, _jsonWriterOptions);
+
+        _fortunesSerializer.Serialize(utf8JsonWriter, fortunes);
+
+        byte[] byteArray = memoryStream.ToArray();
+        *length = (int)utf8JsonWriter.BytesCommitted; 
+        */
+
+        GCHandle handle = GCHandle.Alloc(byteArray, GCHandleType.Pinned);
+        IntPtr byteArrayPointer = handle.AddrOfPinnedObject();
+        *handlePointer = GCHandle.ToIntPtr(handle);
+
+        return byteArrayPointer;
+    }
 
 
     [UnmanagedCallersOnly(EntryPoint = "Query")]
     [UnmanagedCallersOnly(EntryPoint = "Query")]
     public static unsafe IntPtr Query(int queries, int* length, IntPtr* handlePointer)
     public static unsafe IntPtr Query(int queries, int* length, IntPtr* handlePointer)

+ 24 - 0
frameworks/CSharp/appmpower/src/appMpower.Orm/Serializers/FortunesSerializer.cs

@@ -0,0 +1,24 @@
+using System.Text.Json;
+using appMpower.Orm.Objects;
+
+namespace appMpower.Orm.Serializers
+{
+   public class FortunesSerializer : IJsonSerializer<List<Fortune>>
+   {
+      public void Serialize(Utf8JsonWriter utf8JsonWriter, List<Fortune> fortunes)
+      {
+         utf8JsonWriter.WriteStartArray();
+
+         foreach (Fortune fortune in fortunes)
+         {
+            utf8JsonWriter.WriteStartObject();
+            utf8JsonWriter.WriteNumber("id", fortune.Id);
+            utf8JsonWriter.WriteString("message", fortune.Message);
+            utf8JsonWriter.WriteEndObject();
+         }
+
+         utf8JsonWriter.WriteEndArray();
+         utf8JsonWriter.Flush();
+      }
+   }
+}

+ 2 - 2
frameworks/CSharp/appmpower/src/appMpower.Orm/appMpower.Orm.csproj

@@ -1,7 +1,7 @@
 <Project Sdk="Microsoft.NET.Sdk">
 <Project Sdk="Microsoft.NET.Sdk">
 
 
   <PropertyGroup>
   <PropertyGroup>
-    <TargetFramework>net8.0</TargetFramework>
+    <TargetFramework>net9.0</TargetFramework>
     <ImplicitUsings>enable</ImplicitUsings>
     <ImplicitUsings>enable</ImplicitUsings>
 
 
     <PublishAot>true</PublishAot>
     <PublishAot>true</PublishAot>
@@ -36,7 +36,7 @@
   </PropertyGroup>
   </PropertyGroup>
 
 
   <ItemGroup>
   <ItemGroup>
-    <PackageReference Include="System.Data.Odbc" Version="8.0.0" />
+    <PackageReference Include="System.Data.Odbc" Version="9.0.0" />
   </ItemGroup>
   </ItemGroup>
 
 
 </Project>
 </Project>

+ 115 - 0
frameworks/CSharp/appmpower/src/appMpower/Middleware/FortunesMiddleware.cs

@@ -2,7 +2,11 @@ using System;
 using System.Collections.Generic;
 using System.Collections.Generic;
 using System.Runtime.InteropServices;
 using System.Runtime.InteropServices;
 using System.Text;
 using System.Text;
+using System.Text.Encodings.Web;
+using System.Text.Json;
+using System.Text.Unicode;
 using System.Threading.Tasks;
 using System.Threading.Tasks;
+using appMpower.Objects;
 using Microsoft.AspNetCore.Builder;
 using Microsoft.AspNetCore.Builder;
 using Microsoft.AspNetCore.Http;
 using Microsoft.AspNetCore.Http;
 using Microsoft.Extensions.Primitives;
 using Microsoft.Extensions.Primitives;
@@ -11,11 +15,21 @@ namespace appMpower;
 
 
 public class FortunesMiddleware
 public class FortunesMiddleware
 {
 {
+    static readonly HtmlEncoder htmlEncoder = CreateHtmlEncoder();
+    static HtmlEncoder CreateHtmlEncoder()
+    {
+        var settings = new TextEncoderSettings(UnicodeRanges.BasicLatin, UnicodeRanges.Katakana, UnicodeRanges.Hiragana);
+        settings.AllowCharacter('\u2014'); // allow EM DASH through
+        return HtmlEncoder.Create(settings);
+    }
+
     private readonly static KeyValuePair<string, StringValues> _headerServer =
     private readonly static KeyValuePair<string, StringValues> _headerServer =
          new KeyValuePair<string, StringValues>("Server", new StringValues("k"));
          new KeyValuePair<string, StringValues>("Server", new StringValues("k"));
     private readonly static KeyValuePair<string, StringValues> _headerContentType =
     private readonly static KeyValuePair<string, StringValues> _headerContentType =
          new KeyValuePair<string, StringValues>("Content-Type", new StringValues("text/html; charset=UTF-8"));
          new KeyValuePair<string, StringValues>("Content-Type", new StringValues("text/html; charset=UTF-8"));
 
 
+    private static readonly byte[] _delimiter = new byte[] { 0xFF, 0xFF, 0xFF, 0xFF };
+
     private readonly RequestDelegate _next;
     private readonly RequestDelegate _next;
 
 
     public FortunesMiddleware(RequestDelegate next)
     public FortunesMiddleware(RequestDelegate next)
@@ -27,6 +41,66 @@ public class FortunesMiddleware
     {
     {
         if (httpContext.Request.Path.StartsWithSegments("/fortunes", StringComparison.Ordinal))
         if (httpContext.Request.Path.StartsWithSegments("/fortunes", StringComparison.Ordinal))
         {
         {
+            int payloadLength;
+            IntPtr handlePointer; 
+
+            IntPtr bytePointer = NativeMethods.Fortunes(out payloadLength, out handlePointer);
+
+            /*
+            byte[] json = new byte[payloadLength];
+            Marshal.Copy(bytePointer, json, 0, payloadLength);
+            NativeMethods.FreeHandlePointer(handlePointer);
+
+            string s = Encoding.UTF8.GetString(json, 0, json.Length);
+
+            var options = new JsonSerializerOptions
+            {
+                PropertyNameCaseInsensitive = true
+            };
+
+            List<Fortune> fortunes = JsonSerializer.Deserialize<List<Fortune>>(s, options);
+
+            var response = httpContext.Response; 
+            response.Headers.Add(_headerServer);
+
+            var result = Results.Extensions.RazorSlice<Slices.Fortunes, List<Fortune>>(fortunes);
+            result.HtmlEncoder = htmlEncoder;
+
+            return result.ExecuteAsync(httpContext);
+            */
+
+            byte[] byteArray = new byte[payloadLength];
+            Marshal.Copy(bytePointer, byteArray, 0, payloadLength);
+
+            List<Fortune> fortunes = new List<Fortune>();
+
+            // Convert the byte array into segments split by the delimiter
+            int delimiterLength = _delimiter.Length;
+            int start = 0;
+            int index;
+
+            while ((index = FindDelimiterIndex(byteArray, _delimiter, start)) >= 0)
+            {
+                // Use a span over the segment of bytes for the current object
+                var objectDataSpan = new ReadOnlySpan<byte>(byteArray, start, index - start);
+                Fortune fortune = ConvertBytesToObject(objectDataSpan);
+                fortunes.Add(fortune);
+
+                // Move past the delimiter
+                start = index + delimiterLength;
+            }
+
+            NativeMethods.FreeHandlePointer(handlePointer);
+
+            var response = httpContext.Response; 
+            response.Headers.Add(_headerServer);
+
+            var result = Results.Extensions.RazorSlice<Slices.Fortunes, List<Fortune>>(fortunes);
+            result.HtmlEncoder = htmlEncoder;
+
+            return result.ExecuteAsync(httpContext);
+
+            /*
             var response = httpContext.Response; 
             var response = httpContext.Response; 
             response.Headers.Add(_headerServer);
             response.Headers.Add(_headerServer);
             response.Headers.Add(_headerContentType);
             response.Headers.Add(_headerContentType);
@@ -43,10 +117,51 @@ public class FortunesMiddleware
                 new KeyValuePair<string, StringValues>("Content-Length", payloadLength.ToString()));
                 new KeyValuePair<string, StringValues>("Content-Length", payloadLength.ToString()));
 
 
             return response.Body.WriteAsync(json, 0, payloadLength);
             return response.Body.WriteAsync(json, 0, payloadLength);
+            */
         }
         }
 
 
         return _next(httpContext);
         return _next(httpContext);
     }
     }
+
+    private static int FindDelimiterIndex(byte[] array, byte[] delimiter, int startIndex)
+    {
+        int endIndex = array.Length - delimiter.Length;
+
+        for (int i = startIndex; i <= endIndex; i++)
+        {
+            bool isMatch = true;
+
+            for (int j = 0; j < delimiter.Length; j++)
+            {
+                if (array[i + j] != delimiter[j])
+                {
+                    isMatch = false;
+                    break;
+                }
+            }
+
+            if (isMatch)
+            {
+                return i;
+            }
+        }
+
+        return -1;
+    }
+
+    private static Fortune ConvertBytesToObject(ReadOnlySpan<byte> data)
+    {
+        int offset = 0;
+
+        // Read Id
+        int id = BitConverter.ToInt32(data.Slice(offset, sizeof(int)));
+        offset += sizeof(int);
+
+        // Read Message (remaining bytes in the span)
+        string message = Encoding.UTF8.GetString(data.Slice(offset));
+
+        return new Fortune(id, message);
+    }
 }
 }
 
 
 public static class FortunesMiddlewareExtensions
 public static class FortunesMiddlewareExtensions

+ 22 - 0
frameworks/CSharp/appmpower/src/appMpower/Objects/Fortune.cs

@@ -0,0 +1,22 @@
+using System;
+
+namespace appMpower.Objects
+{
+   public struct Fortune : IComparable<Fortune>, IComparable
+   {
+      public Fortune(int id, string message)
+      {
+         Id = id;
+         Message = message;
+      }
+
+      public int Id { get; set; }
+
+      public string Message { get; set; }
+
+      public int CompareTo(object obj) => throw new InvalidOperationException("The non-generic CompareTo should not be used");
+
+      // Performance critical, using culture insensitive comparison
+      public int CompareTo(Fortune other) => string.CompareOrdinal(Message, other.Message);
+   }
+}

+ 2 - 0
frameworks/CSharp/appmpower/src/appMpower/Slices/Fortunes.cshtml

@@ -0,0 +1,2 @@
+@inherits RazorSliceHttpResult<List<appMpower.Objects.Fortune>>
+<!DOCTYPE html><html><head><title>Fortunes</title></head><body><table><tr><th>id</th><th>message</th></tr>@foreach (var item in Model){<tr><td>@WriteNumber(item.Id, default, CultureInfo.InvariantCulture, false)</td><td>@item.Message</td></tr>}</table></body></html>

+ 10 - 0
frameworks/CSharp/appmpower/src/appMpower/Slices/_ViewImports.cshtml

@@ -0,0 +1,10 @@
+@inherits RazorSliceHttpResult
+
+@using System.Globalization;
+@using Microsoft.AspNetCore.Razor;
+@using Microsoft.AspNetCore.Http.HttpResults;
+@using RazorSlices;
+@using appMpower.Objects;
+
+@tagHelperPrefix __disable_tagHelpers__:
+@removeTagHelper *, Microsoft.AspNetCore.Mvc.Razor

+ 2 - 1
frameworks/CSharp/appmpower/src/appMpower/appMpower.csproj

@@ -1,7 +1,7 @@
 <Project Sdk="Microsoft.NET.Sdk.Web">
 <Project Sdk="Microsoft.NET.Sdk.Web">
 
 
   <PropertyGroup>
   <PropertyGroup>
-    <TargetFramework>net8.0</TargetFramework>
+    <TargetFramework>net9.0</TargetFramework>
     <OutputType>Exe</OutputType>
     <OutputType>Exe</OutputType>
     <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
     <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
   </PropertyGroup>
   </PropertyGroup>
@@ -24,6 +24,7 @@
 
 
   <ItemGroup>
   <ItemGroup>
     <ProjectReference Include = "..\appMpower.Orm\appMpower.Orm.csproj" />
     <ProjectReference Include = "..\appMpower.Orm\appMpower.Orm.csproj" />
+    <PackageReference Include="RazorSlices" Version="0.8.1" />
   </ItemGroup>
   </ItemGroup>
 
 
   <PropertyGroup>
   <PropertyGroup>

+ 1 - 1
frameworks/CSharp/aspnetcore/README.md

@@ -6,5 +6,5 @@ See [.NET Core](http://dot.net) and [ASP.NET Core](https://github.com/dotnet/asp
 
 
 **Language**
 **Language**
 
 
-* C# 8.0
+* C# 13.0
 
 

+ 1 - 1
frameworks/CSharp/aspnetcore/appsettings.postgresql.json

@@ -1,4 +1,4 @@
 {
 {
-  "ConnectionString": "Server=tfb-database;Database=hello_world;User Id=benchmarkdbuser;Password=benchmarkdbpass;SSL Mode=Disable;Maximum Pool Size=18;NoResetOnClose=true;Enlist=false;Max Auto Prepare=4;Multiplexing=true;Write Coalescing Buffer Threshold Bytes=1000",
+  "ConnectionString": "Server=tfb-database;Database=hello_world;User Id=benchmarkdbuser;Password=benchmarkdbpass;SSL Mode=Disable;Maximum Pool Size=512;NoResetOnClose=true;Enlist=false;Max Auto Prepare=4",
   "Database": "postgresql"
   "Database": "postgresql"
 }
 }

+ 3 - 3
frameworks/CSharp/aspnetcore/aspnetcore-aot.dockerfile

@@ -1,12 +1,12 @@
-FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build
+FROM mcr.microsoft.com/dotnet/sdk:9.0 AS build
 RUN apt-get update
 RUN apt-get update
 RUN apt-get -yqq install clang zlib1g-dev
 RUN apt-get -yqq install clang zlib1g-dev
 WORKDIR /app
 WORKDIR /app
 COPY src/Platform .
 COPY src/Platform .
 RUN dotnet publish -c Release -o out /p:DatabaseProvider=Npgsql /p:PublishAot=true /p:OptimizationPreference=Speed /p:GarbageCollectionAdaptationMode=0
 RUN dotnet publish -c Release -o out /p:DatabaseProvider=Npgsql /p:PublishAot=true /p:OptimizationPreference=Speed /p:GarbageCollectionAdaptationMode=0
 
 
-FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS runtime
-ENV URLS http://+:8080
+FROM mcr.microsoft.com/dotnet/aspnet:9.0 AS runtime
+ENV URLS=http://+:8080
 
 
 WORKDIR /app
 WORKDIR /app
 COPY --from=build /app/out ./
 COPY --from=build /app/out ./

+ 5 - 2
frameworks/CSharp/aspnetcore/aspnetcore-minimal.dockerfile

@@ -1,10 +1,13 @@
-FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build
+FROM mcr.microsoft.com/dotnet/sdk:9.0 AS build
 WORKDIR /app
 WORKDIR /app
 COPY src/Minimal .
 COPY src/Minimal .
 RUN dotnet publish -c Release -o out
 RUN dotnet publish -c Release -o out
 
 
-FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS runtime
+FROM mcr.microsoft.com/dotnet/aspnet:9.0 AS runtime
 ENV URLS http://+:8080
 ENV URLS http://+:8080
+ENV DOTNET_GCDynamicAdaptationMode=0
+ENV DOTNET_ReadyToRun=0
+ENV DOTNET_HillClimbing_Disable=1
 
 
 WORKDIR /app
 WORKDIR /app
 COPY --from=build /app/out ./
 COPY --from=build /app/out ./

+ 5 - 2
frameworks/CSharp/aspnetcore/aspnetcore-mvc.dockerfile

@@ -1,10 +1,13 @@
-FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build
+FROM mcr.microsoft.com/dotnet/sdk:9.0 AS build
 WORKDIR /app
 WORKDIR /app
 COPY src/Mvc .
 COPY src/Mvc .
 RUN dotnet publish -c Release -o out
 RUN dotnet publish -c Release -o out
 
 
-FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS runtime
+FROM mcr.microsoft.com/dotnet/aspnet:9.0 AS runtime
 ENV URLS http://+:8080
 ENV URLS http://+:8080
+ENV DOTNET_GCDynamicAdaptationMode=0
+ENV DOTNET_ReadyToRun=0
+ENV DOTNET_HillClimbing_Disable=1
 
 
 WORKDIR /app
 WORKDIR /app
 COPY --from=build /app/out ./
 COPY --from=build /app/out ./

+ 5 - 2
frameworks/CSharp/aspnetcore/aspnetcore-mysql.dockerfile

@@ -1,10 +1,13 @@
-FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build
+FROM mcr.microsoft.com/dotnet/sdk:9.0 AS build
 WORKDIR /app
 WORKDIR /app
 COPY src/Platform .
 COPY src/Platform .
 RUN dotnet publish -c Release -o out /p:DatabaseProvider=MySqlConnector
 RUN dotnet publish -c Release -o out /p:DatabaseProvider=MySqlConnector
 
 
-FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS runtime
+FROM mcr.microsoft.com/dotnet/aspnet:9.0 AS runtime
 ENV URLS http://+:8080
 ENV URLS http://+:8080
+ENV DOTNET_GCDynamicAdaptationMode=0
+ENV DOTNET_ReadyToRun=0
+ENV DOTNET_HillClimbing_Disable=1
 
 
 WORKDIR /app
 WORKDIR /app
 COPY --from=build /app/out ./
 COPY --from=build /app/out ./

+ 6 - 3
frameworks/CSharp/aspnetcore/aspnetcore.dockerfile

@@ -1,10 +1,13 @@
-FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build
+FROM mcr.microsoft.com/dotnet/sdk:9.0 AS build
 WORKDIR /app
 WORKDIR /app
 COPY src/Platform .
 COPY src/Platform .
 RUN dotnet publish -c Release -o out /p:DatabaseProvider=Npgsql
 RUN dotnet publish -c Release -o out /p:DatabaseProvider=Npgsql
 
 
-FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS runtime
-ENV URLS http://+:8080
+FROM mcr.microsoft.com/dotnet/aspnet:9.0 AS runtime
+ENV URLS=http://+:8080
+ENV DOTNET_GCDynamicAdaptationMode=0
+ENV DOTNET_ReadyToRun=0
+ENV DOTNET_HillClimbing_Disable=1
 
 
 WORKDIR /app
 WORKDIR /app
 COPY --from=build /app/out ./
 COPY --from=build /app/out ./

+ 1 - 0
frameworks/CSharp/aspnetcore/benchmark_config.json

@@ -30,6 +30,7 @@
         "json_url": "/json",
         "json_url": "/json",
         "db_url": "/db",
         "db_url": "/db",
         "query_url": "/queries/",
         "query_url": "/queries/",
+        "fortune_url": "/fortunes",
         "update_url": "/updates/",
         "update_url": "/updates/",
         "cached_query_url": "/cached-worlds/",
         "cached_query_url": "/cached-worlds/",
         "port": 8080,
         "port": 8080,

+ 4 - 4
frameworks/CSharp/aspnetcore/src/Minimal/Minimal.csproj

@@ -1,7 +1,7 @@
 <Project Sdk="Microsoft.NET.Sdk.Web">
 <Project Sdk="Microsoft.NET.Sdk.Web">
 
 
   <PropertyGroup>
   <PropertyGroup>
-    <TargetFramework>net8.0</TargetFramework>
+    <TargetFramework>net9.0</TargetFramework>
     <Nullable>enable</Nullable>
     <Nullable>enable</Nullable>
     <ImplicitUsings>enable</ImplicitUsings>
     <ImplicitUsings>enable</ImplicitUsings>
     <LangVersion>latest</LangVersion>
     <LangVersion>latest</LangVersion>
@@ -9,9 +9,9 @@
   </PropertyGroup>
   </PropertyGroup>
 
 
   <ItemGroup>
   <ItemGroup>
-    <PackageReference Include="Npgsql" Version="8.0.3" />
-    <PackageReference Include="Dapper" Version="2.1.21" />
-    <PackageReference Include="RazorSlices" Version="0.7.0" />
+    <PackageReference Include="Npgsql" Version="9.0.2" />
+    <PackageReference Include="Dapper" Version="2.1.35" />
+    <PackageReference Include="RazorSlices" Version="0.8.1" />
   </ItemGroup>
   </ItemGroup>
 
 
 </Project>
 </Project>

+ 6 - 8
frameworks/CSharp/aspnetcore/src/Minimal/Program.cs

@@ -1,13 +1,11 @@
 // Copyright (c) .NET Foundation. All rights reserved. 
 // Copyright (c) .NET Foundation. All rights reserved. 
 // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. 
 // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. 
 
 
-using System.Text.Encodings.Web;
-using System.Text.Unicode;
-using Microsoft.AspNetCore.Http.HttpResults;
-using RazorSlices;
 using Minimal;
 using Minimal;
 using Minimal.Database;
 using Minimal.Database;
 using Minimal.Models;
 using Minimal.Models;
+using System.Text.Encodings.Web;
+using System.Text.Unicode;
 
 
 var builder = WebApplication.CreateBuilder(args);
 var builder = WebApplication.CreateBuilder(args);
 
 
@@ -36,14 +34,14 @@ app.MapGet("/json", () => new { message = "Hello, World!" });
 
 
 app.MapGet("/db", async (Db db) => await db.LoadSingleQueryRow());
 app.MapGet("/db", async (Db db) => await db.LoadSingleQueryRow());
 
 
-var createFortunesTemplate = RazorSlice.ResolveSliceFactory<List<Fortune>>("/Templates/Fortunes.cshtml");
 var htmlEncoder = CreateHtmlEncoder();
 var htmlEncoder = CreateHtmlEncoder();
 
 
 app.MapGet("/fortunes", async (HttpContext context, Db db) => {
 app.MapGet("/fortunes", async (HttpContext context, Db db) => {
     var fortunes = await db.LoadFortunesRows();
     var fortunes = await db.LoadFortunesRows();
-    var template = (RazorSliceHttpResult<List<Fortune>>)createFortunesTemplate(fortunes);
-    template.HtmlEncoder = htmlEncoder;
-    return template;
+    var result = Results.Extensions.RazorSlice<Minimal.Slices.Fortunes, List<Fortune>>(fortunes);
+    result.HtmlEncoder = htmlEncoder;
+
+    return result;
 });
 });
 
 
 app.MapGet("/queries/{count?}", async (Db db, string? count) => await db.LoadMultipleQueriesRows(count));
 app.MapGet("/queries/{count?}", async (Db db, string? count) => await db.LoadMultipleQueriesRows(count));

+ 0 - 0
frameworks/CSharp/aspnetcore/src/Minimal/Templates/Fortunes.cshtml → frameworks/CSharp/aspnetcore/src/Minimal/Slices/Fortunes.cshtml


+ 0 - 0
frameworks/CSharp/aspnetcore/src/Minimal/Templates/_ViewImports.cshtml → frameworks/CSharp/aspnetcore/src/Minimal/Slices/_ViewImports.cshtml


+ 3 - 3
frameworks/CSharp/aspnetcore/src/Mvc/Mvc.csproj

@@ -1,7 +1,7 @@
 <Project Sdk="Microsoft.NET.Sdk.Web">
 <Project Sdk="Microsoft.NET.Sdk.Web">
 
 
   <PropertyGroup>
   <PropertyGroup>
-    <TargetFramework>net8.0</TargetFramework>
+    <TargetFramework>net9.0</TargetFramework>
     <Nullable>enable</Nullable>
     <Nullable>enable</Nullable>
     <ImplicitUsings>enable</ImplicitUsings>
     <ImplicitUsings>enable</ImplicitUsings>
     <LangVersion>latest</LangVersion>
     <LangVersion>latest</LangVersion>
@@ -9,8 +9,8 @@
   </PropertyGroup>
   </PropertyGroup>
 
 
   <ItemGroup>
   <ItemGroup>
-    <PackageReference Include="Npgsql" Version="8.0.3" />
-    <PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="8.0.0-rc.2" />
+    <PackageReference Include="Npgsql" Version="9.0.2" />
+    <PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="9.0.2" />
   </ItemGroup>
   </ItemGroup>
 
 
 </Project>
 </Project>

+ 1 - 1
frameworks/CSharp/aspnetcore/src/Platform/BenchmarkApplication.Caching.cs

@@ -6,7 +6,7 @@ using System.Threading.Tasks;
 
 
 namespace PlatformBenchmarks;
 namespace PlatformBenchmarks;
 
 
-public partial class BenchmarkApplication
+public sealed partial class BenchmarkApplication
 {
 {
     private static async Task Caching(PipeWriter pipeWriter, int count)
     private static async Task Caching(PipeWriter pipeWriter, int count)
     {
     {

+ 7 - 8
frameworks/CSharp/aspnetcore/src/Platform/BenchmarkApplication.Fortunes.cs

@@ -1,7 +1,7 @@
 // Copyright (c) .NET Foundation. All rights reserved.
 // Copyright (c) .NET Foundation. All rights reserved.
 // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
 // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
 
 
-#if !AOT
+using System;
 using System.IO.Pipelines;
 using System.IO.Pipelines;
 using System.Runtime.CompilerServices;
 using System.Runtime.CompilerServices;
 using System.Threading.Tasks;
 using System.Threading.Tasks;
@@ -9,7 +9,7 @@ using RazorSlices;
 
 
 namespace PlatformBenchmarks;
 namespace PlatformBenchmarks;
 
 
-public partial class BenchmarkApplication
+public sealed partial class BenchmarkApplication
 {
 {
     private async Task FortunesRaw(PipeWriter pipeWriter)
     private async Task FortunesRaw(PipeWriter pipeWriter)
     {
     {
@@ -19,7 +19,7 @@ public partial class BenchmarkApplication
             FortunesTemplateFactory);
             FortunesTemplateFactory);
     }
     }
 
 
-    private ValueTask OutputFortunes<TModel>(PipeWriter pipeWriter, TModel model, SliceFactory<TModel> templateFactory)
+    private ValueTask OutputFortunes<TModel>(PipeWriter pipeWriter, TModel model, Func<TModel, RazorSlice<TModel>> templateFactory)
     {
     {
         // Render headers
         // Render headers
         var preamble = """
         var preamble = """
@@ -39,7 +39,7 @@ public partial class BenchmarkApplication
         // Kestrel PipeWriter span size is 4K, headers above already written to first span & template output is ~1350 bytes,
         // Kestrel PipeWriter span size is 4K, headers above already written to first span & template output is ~1350 bytes,
         // so 2K chunk size should result in only a single span and chunk being used.
         // so 2K chunk size should result in only a single span and chunk being used.
         var chunkedWriter = GetChunkedWriter(pipeWriter, chunkSizeHint: 2048);
         var chunkedWriter = GetChunkedWriter(pipeWriter, chunkSizeHint: 2048);
-        var renderTask = template.RenderAsync(chunkedWriter, null, HtmlEncoder);
+        var renderTask = template.RenderAsync(chunkedWriter, HtmlEncoder);
 
 
         if (renderTask.IsCompletedSuccessfully)
         if (renderTask.IsCompletedSuccessfully)
         {
         {
@@ -51,18 +51,17 @@ public partial class BenchmarkApplication
         return AwaitTemplateRenderTask(renderTask, chunkedWriter, template);
         return AwaitTemplateRenderTask(renderTask, chunkedWriter, template);
     }
     }
 
 
-    private static async ValueTask AwaitTemplateRenderTask(ValueTask renderTask, ChunkedBufferWriter<WriterAdapter> chunkedWriter, RazorSlice template)
+    private static async ValueTask AwaitTemplateRenderTask(ValueTask renderTask, ChunkedPipeWriter chunkedWriter, RazorSlice template)
     {
     {
         await renderTask;
         await renderTask;
         EndTemplateRendering(chunkedWriter, template);
         EndTemplateRendering(chunkedWriter, template);
     }
     }
 
 
     [MethodImpl(MethodImplOptions.AggressiveInlining)]
     [MethodImpl(MethodImplOptions.AggressiveInlining)]
-    private static void EndTemplateRendering(ChunkedBufferWriter<WriterAdapter> chunkedWriter, RazorSlice template)
+    private static void EndTemplateRendering(ChunkedPipeWriter chunkedWriter, RazorSlice template)
     {
     {
-        chunkedWriter.End();
+        chunkedWriter.Complete();
         ReturnChunkedWriter(chunkedWriter);
         ReturnChunkedWriter(chunkedWriter);
         template.Dispose();
         template.Dispose();
     }
     }
 }
 }
-#endif

+ 4 - 4
frameworks/CSharp/aspnetcore/src/Platform/BenchmarkApplication.HttpConnection.cs

@@ -12,7 +12,7 @@ using Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http;
 
 
 namespace PlatformBenchmarks;
 namespace PlatformBenchmarks;
 
 
-public partial class BenchmarkApplication : IHttpConnection
+public sealed partial class BenchmarkApplication : IHttpConnection
 {
 {
     private State _state;
     private State _state;
 
 
@@ -193,15 +193,15 @@ public partial class BenchmarkApplication : IHttpConnection
         => new(new(pipeWriter), sizeHint);
         => new(new(pipeWriter), sizeHint);
 
 
     [MethodImpl(MethodImplOptions.AggressiveInlining)]
     [MethodImpl(MethodImplOptions.AggressiveInlining)]
-    private static ChunkedBufferWriter<WriterAdapter> GetChunkedWriter(PipeWriter pipeWriter, int chunkSizeHint)
+    private static ChunkedPipeWriter GetChunkedWriter(PipeWriter pipeWriter, int chunkSizeHint)
     {
     {
         var writer = ChunkedWriterPool.Get();
         var writer = ChunkedWriterPool.Get();
-        writer.SetOutput(new WriterAdapter(pipeWriter), chunkSizeHint);
+        writer.SetOutput(pipeWriter, chunkSizeHint);
         return writer;
         return writer;
     }
     }
 
 
     [MethodImpl(MethodImplOptions.AggressiveInlining)]
     [MethodImpl(MethodImplOptions.AggressiveInlining)]
-    private static void ReturnChunkedWriter(ChunkedBufferWriter<WriterAdapter> writer) => ChunkedWriterPool.Return(writer);
+    private static void ReturnChunkedWriter(ChunkedPipeWriter writer) => ChunkedWriterPool.Return(writer);
 
 
     private struct WriterAdapter : IBufferWriter<byte>
     private struct WriterAdapter : IBufferWriter<byte>
     {
     {

+ 1 - 1
frameworks/CSharp/aspnetcore/src/Platform/BenchmarkApplication.Json.cs

@@ -9,7 +9,7 @@ using System.Threading.Tasks;
 
 
 namespace PlatformBenchmarks;
 namespace PlatformBenchmarks;
 
 
-public partial class BenchmarkApplication
+public sealed partial class BenchmarkApplication
 {
 {
     private readonly static uint _jsonPayloadSize = (uint)JsonSerializer.SerializeToUtf8Bytes(
     private readonly static uint _jsonPayloadSize = (uint)JsonSerializer.SerializeToUtf8Bytes(
         new JsonMessage { message = "Hello, World!" },
         new JsonMessage { message = "Hello, World!" },

+ 1 - 1
frameworks/CSharp/aspnetcore/src/Platform/BenchmarkApplication.MultipleQueries.cs

@@ -8,7 +8,7 @@ using System.Text.Json.Serialization.Metadata;
 
 
 namespace PlatformBenchmarks;
 namespace PlatformBenchmarks;
 
 
-public partial class BenchmarkApplication
+public sealed partial class BenchmarkApplication
 {
 {
     private static async Task MultipleQueries(PipeWriter pipeWriter, int count)
     private static async Task MultipleQueries(PipeWriter pipeWriter, int count)
     {
     {

+ 1 - 1
frameworks/CSharp/aspnetcore/src/Platform/BenchmarkApplication.Plaintext.cs

@@ -7,7 +7,7 @@ using System.Threading.Tasks;
 
 
 namespace PlatformBenchmarks;
 namespace PlatformBenchmarks;
 
 
-public partial class BenchmarkApplication
+public sealed partial class BenchmarkApplication
 {
 {
     private static ReadOnlySpan<byte> _plaintextPreamble =>
     private static ReadOnlySpan<byte> _plaintextPreamble =>
         "HTTP/1.1 200 OK\r\n"u8 +
         "HTTP/1.1 200 OK\r\n"u8 +

+ 1 - 1
frameworks/CSharp/aspnetcore/src/Platform/BenchmarkApplication.SingleQuery.cs

@@ -7,7 +7,7 @@ using System.Threading.Tasks;
 
 
 namespace PlatformBenchmarks;
 namespace PlatformBenchmarks;
 
 
-public partial class BenchmarkApplication
+public sealed partial class BenchmarkApplication
 {
 {
     private static async Task SingleQuery(PipeWriter pipeWriter)
     private static async Task SingleQuery(PipeWriter pipeWriter)
     {
     {

+ 1 - 1
frameworks/CSharp/aspnetcore/src/Platform/BenchmarkApplication.Updates.cs

@@ -7,7 +7,7 @@ using System.Threading.Tasks;
 
 
 namespace PlatformBenchmarks;
 namespace PlatformBenchmarks;
 
 
-public partial class BenchmarkApplication
+public sealed partial class BenchmarkApplication
 {
 {
     private static async Task Updates(PipeWriter pipeWriter, int count)
     private static async Task Updates(PipeWriter pipeWriter, int count)
     {
     {

+ 7 - 12
frameworks/CSharp/aspnetcore/src/Platform/BenchmarkApplication.cs

@@ -10,9 +10,8 @@ using System.Text.Json.Serialization;
 using System.Threading.Tasks;
 using System.Threading.Tasks;
 using Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http;
 using Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http;
 using Microsoft.Extensions.ObjectPool;
 using Microsoft.Extensions.ObjectPool;
-#if !AOT
+using Platform.Templates;
 using RazorSlices;
 using RazorSlices;
-#endif
 
 
 namespace PlatformBenchmarks
 namespace PlatformBenchmarks
 {
 {
@@ -42,26 +41,24 @@ namespace PlatformBenchmarks
 
 
         public static RawDb RawDb { get; set; }
         public static RawDb RawDb { get; set; }
 
 
-        private static readonly DefaultObjectPool<ChunkedBufferWriter<WriterAdapter>> ChunkedWriterPool
+        private static readonly DefaultObjectPool<ChunkedPipeWriter> ChunkedWriterPool
             = new(new ChunkedWriterObjectPolicy());
             = new(new ChunkedWriterObjectPolicy());
 
 
-        private sealed class ChunkedWriterObjectPolicy : IPooledObjectPolicy<ChunkedBufferWriter<WriterAdapter>>
+        private sealed class ChunkedWriterObjectPolicy : IPooledObjectPolicy<ChunkedPipeWriter>
         {
         {
-            public ChunkedBufferWriter<WriterAdapter> Create() => new();
+            public ChunkedPipeWriter Create() => new();
 
 
-            public bool Return(ChunkedBufferWriter<WriterAdapter> writer)
+            public bool Return(ChunkedPipeWriter writer)
             {
             {
                 writer.Reset();
                 writer.Reset();
                 return true;
                 return true;
             }
             }
         }
         }
 
 
-#if !AOT
 #if NPGSQL
 #if NPGSQL
-        private readonly static SliceFactory<List<FortuneUtf8>> FortunesTemplateFactory = RazorSlice.ResolveSliceFactory<List<FortuneUtf8>>("/Templates/FortunesUtf8.cshtml");
+        private readonly static Func<List<FortuneUtf8>, RazorSlice<List<FortuneUtf8>>> FortunesTemplateFactory = FortunesUtf8.Create;
 #else
 #else
-        private readonly static SliceFactory<List<FortuneUtf16>> FortunesTemplateFactory = RazorSlice.ResolveSliceFactory<List<FortuneUtf16>>("/Templates/FortunesUtf16.cshtml");
-#endif
+        private readonly static Func<List<FortuneUtf16>, RazorSlice<List<FortuneUtf16>>> FortunesTemplateFactory = FortunesUtf16.Create;
 #endif
 #endif
 
 
         [ThreadStatic]
         [ThreadStatic]
@@ -167,9 +164,7 @@ namespace PlatformBenchmarks
 
 
         private Task ProcessRequestAsync() => _requestType switch
         private Task ProcessRequestAsync() => _requestType switch
         {
         {
-#if !AOT
             RequestType.FortunesRaw => FortunesRaw(Writer),
             RequestType.FortunesRaw => FortunesRaw(Writer),
-#endif
             RequestType.SingleQuery => SingleQuery(Writer),
             RequestType.SingleQuery => SingleQuery(Writer),
             RequestType.Caching => Caching(Writer, _queries),
             RequestType.Caching => Caching(Writer, _queries),
             RequestType.Updates => Updates(Writer, _queries),
             RequestType.Updates => Updates(Writer, _queries),

+ 35 - 8
frameworks/CSharp/aspnetcore/src/Platform/ChunkedBufferWriter.cs → frameworks/CSharp/aspnetcore/src/Platform/ChunkedPipeWriter.cs

@@ -5,35 +5,40 @@ using System;
 using System.Buffers;
 using System.Buffers;
 using System.Buffers.Text;
 using System.Buffers.Text;
 using System.Diagnostics;
 using System.Diagnostics;
+using System.IO.Pipelines;
 using System.Numerics;
 using System.Numerics;
 using System.Runtime.CompilerServices;
 using System.Runtime.CompilerServices;
+using System.Threading;
+using System.Threading.Tasks;
 
 
 namespace PlatformBenchmarks;
 namespace PlatformBenchmarks;
 
 
-internal sealed class ChunkedBufferWriter<TWriter> : IBufferWriter<byte> where TWriter : IBufferWriter<byte>
+internal sealed class ChunkedPipeWriter : PipeWriter
 {
 {
     private const int DefaultChunkSizeHint = 2048;
     private const int DefaultChunkSizeHint = 2048;
     private static readonly StandardFormat DefaultHexFormat = GetHexFormat(DefaultChunkSizeHint);
     private static readonly StandardFormat DefaultHexFormat = GetHexFormat(DefaultChunkSizeHint);
     private static ReadOnlySpan<byte> ChunkTerminator => "\r\n"u8;
     private static ReadOnlySpan<byte> ChunkTerminator => "\r\n"u8;
 
 
-    private TWriter _output;
+    private PipeWriter _output;
     private int _chunkSizeHint;
     private int _chunkSizeHint;
     private StandardFormat _hexFormat = DefaultHexFormat;
     private StandardFormat _hexFormat = DefaultHexFormat;
     private Memory<byte> _currentFullChunk;
     private Memory<byte> _currentFullChunk;
     private Memory<byte> _currentChunk;
     private Memory<byte> _currentChunk;
     private int _buffered;
     private int _buffered;
+    private long _unflushedBytes;
     private bool _ended = false;
     private bool _ended = false;
 
 
     public Memory<byte> Memory => _currentChunk;
     public Memory<byte> Memory => _currentChunk;
 
 
-    public TWriter Output => _output;
+    public PipeWriter Output => _output;
 
 
     public int Buffered => _buffered;
     public int Buffered => _buffered;
 
 
     [MethodImpl(MethodImplOptions.AggressiveInlining)]
     [MethodImpl(MethodImplOptions.AggressiveInlining)]
-    public void SetOutput(TWriter output, int chunkSizeHint = DefaultChunkSizeHint)
+    public void SetOutput(PipeWriter output, int chunkSizeHint = DefaultChunkSizeHint)
     {
     {
         _buffered = 0;
         _buffered = 0;
+        _unflushedBytes = 0;
         _chunkSizeHint = chunkSizeHint;
         _chunkSizeHint = chunkSizeHint;
         _output = output;
         _output = output;
 
 
@@ -44,6 +49,7 @@ internal sealed class ChunkedBufferWriter<TWriter> : IBufferWriter<byte> where T
     public void Reset()
     public void Reset()
     {
     {
         _buffered = 0;
         _buffered = 0;
+        _unflushedBytes = 0;
         _output = default;
         _output = default;
         _ended = false;
         _ended = false;
         _hexFormat = DefaultHexFormat;
         _hexFormat = DefaultHexFormat;
@@ -51,16 +57,21 @@ internal sealed class ChunkedBufferWriter<TWriter> : IBufferWriter<byte> where T
         _currentChunk = default;
         _currentChunk = default;
     }
     }
 
 
+    public override bool CanGetUnflushedBytes => true;
+
+    public override long UnflushedBytes => _unflushedBytes;
+
     [MethodImpl(MethodImplOptions.AggressiveInlining)]
     [MethodImpl(MethodImplOptions.AggressiveInlining)]
-    public void Advance(int count)
+    public override void Advance(int count)
     {
     {
         ThrowIfEnded();
         ThrowIfEnded();
 
 
         _buffered += count;
         _buffered += count;
+        _unflushedBytes += count;
         _currentChunk = _currentChunk[count..];
         _currentChunk = _currentChunk[count..];
     }
     }
 
 
-    public Memory<byte> GetMemory(int sizeHint = 0)
+    public override Memory<byte> GetMemory(int sizeHint = 0)
     {
     {
         ThrowIfEnded();
         ThrowIfEnded();
 
 
@@ -71,9 +82,14 @@ internal sealed class ChunkedBufferWriter<TWriter> : IBufferWriter<byte> where T
         return _currentChunk;
         return _currentChunk;
     }
     }
 
 
-    public Span<byte> GetSpan(int sizeHint = 0) => GetMemory(sizeHint).Span;
+    public override Span<byte> GetSpan(int sizeHint = 0) => GetMemory(sizeHint).Span;
+
+    public override void CancelPendingFlush()
+    {
+        _output.CancelPendingFlush();
+    }
 
 
-    public void End()
+    public override void Complete(Exception exception = null)
     {
     {
         ThrowIfEnded();
         ThrowIfEnded();
 
 
@@ -82,6 +98,17 @@ internal sealed class ChunkedBufferWriter<TWriter> : IBufferWriter<byte> where T
         _ended = true;
         _ended = true;
     }
     }
 
 
+    public override ValueTask<FlushResult> FlushAsync(CancellationToken cancellationToken = default)
+    {
+        CommitCurrentChunk(isFinal: false);
+
+        var flushTask = _output.FlushAsync(cancellationToken);
+
+        _unflushedBytes = 0;
+
+        return flushTask;
+    }
+
     [MethodImpl(MethodImplOptions.AggressiveInlining)]
     [MethodImpl(MethodImplOptions.AggressiveInlining)]
     private static StandardFormat GetHexFormat(int maxValue)
     private static StandardFormat GetHexFormat(int maxValue)
     {
     {

+ 8 - 9
frameworks/CSharp/aspnetcore/src/Platform/Platform.csproj

@@ -1,12 +1,11 @@
 <Project Sdk="Microsoft.NET.Sdk.Web">
 <Project Sdk="Microsoft.NET.Sdk.Web">
 
 
   <PropertyGroup>
   <PropertyGroup>
-    <TargetFramework>net8.0</TargetFramework>
+    <TargetFramework>net9.0</TargetFramework>
     <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
     <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
     <IsTestAssetProject>true</IsTestAssetProject>
     <IsTestAssetProject>true</IsTestAssetProject>
     <LangVersion>preview</LangVersion>
     <LangVersion>preview</LangVersion>
     <UserSecretsId>38063504-d08c-495a-89c9-daaad2f60f31</UserSecretsId>
     <UserSecretsId>38063504-d08c-495a-89c9-daaad2f60f31</UserSecretsId>
-    <DefineConstants Condition="'$(PublishAot)' == 'true'">AOT;$(DefineConstants)</DefineConstants>
   </PropertyGroup>
   </PropertyGroup>
 
 
   <PropertyGroup>
   <PropertyGroup>
@@ -19,14 +18,14 @@
   </ItemGroup>
   </ItemGroup>
 
 
   <ItemGroup>
   <ItemGroup>
-    <PackageReference Include="Npgsql" Version="8.0.3" />
-    <PackageReference Include="MySqlConnector" Version="2.3.1" />
-    <PackageReference Include="Dapper" Version="2.1.21" />
-    <PackageReference Include="RazorSlices" Version="0.7.0" Condition="$(PublishAot) != 'true'" />
+    <PackageReference Include="Npgsql" Version="9.0.2" />
+    <PackageReference Include="MySqlConnector" Version="2.3.7" />
+    <PackageReference Include="Dapper" Version="2.1.35" />
+    <PackageReference Include="RazorSlices" Version="0.8.1" />
   </ItemGroup>
   </ItemGroup>
 
 
-  <PropertyGroup Condition="$(PublishAot) == 'true'">
-    <DefaultItemExcludes>$(MSBuildThisFileDirectory)Templates/**;$(DefaultItemExcludes)</DefaultItemExcludes>
-  </PropertyGroup>
+  <ItemGroup Condition="$(PublishAot) == 'true'">
+    <RuntimeHostConfigurationOption Include="System.Threading.ThreadPool.HillClimbing.Disable" Value="true" />
+  </ItemGroup>
 
 
 </Project>
 </Project>

+ 0 - 1
frameworks/CSharp/aspnetcore/src/Platform/Program.cs

@@ -52,7 +52,6 @@ public class Program
 #if DEBUG
 #if DEBUG
             .AddUserSecrets<Program>()
             .AddUserSecrets<Program>()
 #endif
 #endif
-            .AddEnvironmentVariables()
             .AddEnvironmentVariables()
             .AddEnvironmentVariables()
             .AddCommandLine(args)
             .AddCommandLine(args)
             .Build();
             .Build();

+ 36 - 38
frameworks/CSharp/genhttp/Benchmarks/Benchmarks.csproj

@@ -1,40 +1,38 @@
 <Project Sdk="Microsoft.NET.Sdk">
 <Project Sdk="Microsoft.NET.Sdk">
-  
-  <PropertyGroup>
-    
-    <TargetFramework>net8.0</TargetFramework>
-    <LangVersion>10.0</LangVersion>
-    
-    <AssemblyTitle>GenHTTP Benchmarks</AssemblyTitle>
-    <Description>Test suite to be executed with TechEmpower FrameworkBenchmarks.</Description>
-    
-    <StartupObject>Benchmarks.Program</StartupObject>    
-    <OutputType>Exe</OutputType>
-    
-    <ServerGarbageCollection>true</ServerGarbageCollection>
-	  <TieredPGO>true</TieredPGO>
-    
-  </PropertyGroup>
-  
-  <ItemGroup>
-    <None Remove="Resources\Fortunes.html" />
-    <None Remove="Resources\Template.html" />
-  </ItemGroup>
-  
-  <ItemGroup>
-    <EmbeddedResource Include="Resources\Template.html" />
-    <EmbeddedResource Include="Resources\Fortunes.html" />
-  </ItemGroup>
-    
-  <ItemGroup>
-	  
-    <PackageReference Include="GenHTTP.Core" Version="8.5.2" />
-    <PackageReference Include="GenHTTP.Modules.Razor" Version="8.5.0" />
-    <PackageReference Include="GenHTTP.Modules.Webservices" Version="8.5.0" />
-	  
-    <PackageReference Include="Microsoft.EntityFrameworkCore" Version="8.0.6" />
-    <PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="8.0.4" />
-	  
-  </ItemGroup>
-  
+
+    <PropertyGroup>
+
+        <TargetFramework>net9.0</TargetFramework>
+        <LangVersion>13.0</LangVersion>
+        <ImplicitUsings>true</ImplicitUsings>
+        <OutputType>Exe</OutputType>
+
+        <AssemblyTitle>GenHTTP Benchmarks</AssemblyTitle>
+        <Description>Test suite to be executed with TechEmpower FrameworkBenchmarks.</Description>
+
+        <ServerGarbageCollection>true</ServerGarbageCollection>
+        <TieredPGO>true</TieredPGO>
+
+    </PropertyGroup>
+
+    <ItemGroup>
+        <None Remove="Resources\Fortunes.html"/>
+        <None Remove="Resources\Template.html"/>
+    </ItemGroup>
+
+    <ItemGroup>
+        <EmbeddedResource Include="Resources\Template.html"/>
+    </ItemGroup>
+
+    <ItemGroup>
+
+        <PackageReference Include="GenHTTP.Core.Kestrel" Version="9.0.0" />
+        <PackageReference Include="GenHTTP.Modules.Razor" Version="8.6.0" />
+        <PackageReference Include="GenHTTP.Modules.Webservices" Version="9.0.0" />
+
+        <PackageReference Include="Microsoft.EntityFrameworkCore" Version="9.0.0" />
+        <PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="9.0.0" />
+
+    </ItemGroup>
+
 </Project>
 </Project>

+ 23 - 32
frameworks/CSharp/genhttp/Benchmarks/Model/DatabaseContext.cs

@@ -1,52 +1,43 @@
 using Microsoft.EntityFrameworkCore;
 using Microsoft.EntityFrameworkCore;
 
 
-namespace Benchmarks.Model
+namespace Benchmarks.Model;
+
+public sealed class DatabaseContext : DbContext
 {
 {
+    private static DbContextOptions<DatabaseContext> _options;
 
 
-    public sealed class DatabaseContext : DbContext
-    {
-        private static DbContextOptions<DatabaseContext> _Options;
+    private static DbContextOptions<DatabaseContext> _noTrackingOptions;
 
 
-        private static DbContextOptions<DatabaseContext> _NoTrackingOptions;
+    #region Factory
 
 
-        #region Factory
+    public static DatabaseContext Create() => new(_options ??= GetOptions(true));
 
 
-        public static DatabaseContext Create()
-        {
-            return new DatabaseContext(_Options ??= GetOptions(true));
-        }
-
-        public static DatabaseContext CreateNoTracking()
-        {
-            return new DatabaseContext(_NoTrackingOptions ??= GetOptions(false));
-        }
+    public static DatabaseContext CreateNoTracking() => new(_noTrackingOptions ??= GetOptions(false));
 
 
-        private static DbContextOptions<DatabaseContext> GetOptions(bool tracking)
-        {
-            var optionsBuilder = new DbContextOptionsBuilder<DatabaseContext>();
-
-            optionsBuilder.UseNpgsql("Server=tfb-database;Database=hello_world;User Id=benchmarkdbuser;Password=benchmarkdbpass;Maximum Pool Size=256;NoResetOnClose=true;Enlist=false;Max Auto Prepare=4");
+    private static DbContextOptions<DatabaseContext> GetOptions(bool tracking)
+    {
+        var optionsBuilder = new DbContextOptionsBuilder<DatabaseContext>();
 
 
-            if (!tracking)
-            {
-                optionsBuilder.UseQueryTrackingBehavior(QueryTrackingBehavior.NoTracking);
-            }
+        optionsBuilder.UseNpgsql("Server=tfb-database;Database=hello_world;User Id=benchmarkdbuser;Password=benchmarkdbpass;SSL Mode=Disable;Maximum Pool Size=512;NoResetOnClose=true;Enlist=false;Max Auto Prepare=4");
 
 
-            return optionsBuilder.Options;
+        if (!tracking)
+        {
+            optionsBuilder.UseQueryTrackingBehavior(QueryTrackingBehavior.NoTracking);
         }
         }
 
 
-        private DatabaseContext(DbContextOptions options) : base(options) { }
+        return optionsBuilder.Options;
+    }
 
 
-        #endregion
+    private DatabaseContext(DbContextOptions options) : base(options) { }
 
 
-        #region Entities
+    #endregion
 
 
-        public DbSet<World> World { get; set; }
+    #region Entities
 
 
-        public DbSet<Fortune> Fortune { get; set; }
+    public DbSet<World> World { get; set; }
 
 
-        #endregion
+    public DbSet<Fortune> Fortune { get; set; }
 
 
-    }
+    #endregion
 
 
 }
 }

+ 10 - 18
frameworks/CSharp/genhttp/Benchmarks/Model/Fortune.cs

@@ -1,25 +1,17 @@
-using System;
-using System.ComponentModel.DataAnnotations;
+using System.ComponentModel.DataAnnotations;
 using System.ComponentModel.DataAnnotations.Schema;
 using System.ComponentModel.DataAnnotations.Schema;
 
 
-namespace Benchmarks.Model
-{
-
-    [Table("fortune")]
-    public class Fortune : IComparable<Fortune>, IComparable
-    {
-
-        [Column("id")]
-        public int ID { get; set; }
+namespace Benchmarks.Model;
 
 
-        [Column("message")]
-        [StringLength(2048)]
-        public string Message { get; set; }
-
-        public int CompareTo(object obj) => CompareTo((Fortune)obj);
+[Table("fortune")]
+public class Fortune
+{
 
 
-        public int CompareTo(Fortune other) => string.CompareOrdinal(Message, other.Message);
+    [Column("id")]
+    public int Id { get; set; }
 
 
-    }
+    [Column("message")]
+    [StringLength(2048)]
+    public string Message { get; set; }
 
 
 }
 }

+ 9 - 12
frameworks/CSharp/genhttp/Benchmarks/Model/World.cs

@@ -1,18 +1,15 @@
 using System.ComponentModel.DataAnnotations.Schema;
 using System.ComponentModel.DataAnnotations.Schema;
 
 
-namespace Benchmarks.Model
-{
-
-    [Table("world")]
-    public class World
-    {
+namespace Benchmarks.Model;
 
 
-        [Column("id")]
-        public int Id { get; set; }
+[Table("world")]
+public class World
+{
 
 
-        [Column("randomnumber")]
-        public int RandomNumber { get; set; }
+    [Column("id")]
+    public int Id { get; set; }
 
 
-    }
+    [Column("randomnumber")]
+    public int RandomNumber { get; set; }
 
 
-}
+}

+ 16 - 31
frameworks/CSharp/genhttp/Benchmarks/Program.cs

@@ -1,35 +1,20 @@
-using GenHTTP.Engine;
-
+using Benchmarks.Tests;
+using Benchmarks.Utilities;
+using GenHTTP.Engine.Kestrel;
 using GenHTTP.Modules.IO;
 using GenHTTP.Modules.IO;
 using GenHTTP.Modules.Layouting;
 using GenHTTP.Modules.Layouting;
 using GenHTTP.Modules.Webservices;
 using GenHTTP.Modules.Webservices;
 
 
-using Benchmarks.Tests;
-using Benchmarks.Utilities;
-
-namespace Benchmarks
-{
-
-    public static class Program
-    {
-
-        public static int Main(string[] args)
-        { 
-            var tests = Layout.Create()
-                              .Add("plaintext", Content.From(Resource.FromString("Hello, World!")))
-                              .Add("fortunes", new FortuneHandlerBuilder())
-                              .AddService<JsonResource>("json")
-                              .AddService<DbResource>("db")
-                              .AddService<QueryResource>("queries")
-                              .AddService<UpdateResource>("updates")
-                              .AddService<CacheResource>("cached-worlds")
-                              .Add(ServerHeader.Create());
-
-            return Host.Create()
-                       .Handler(tests)
-                       .Run();
-        }
-
-    }
-
-}
+var tests = Layout.Create()
+                  .Add("plaintext", Content.From(Resource.FromString("Hello, World!")))
+                  .Add("fortunes", new FortuneHandler())
+                  .AddService<JsonResource>("json")
+                  .AddService<DbResource>("db")
+                  .AddService<QueryResource>("queries")
+                  .AddService<UpdateResource>("updates")
+                  .AddService<CacheResource>("cached-worlds")
+                  .Add(ServerHeader.Create());
+
+return await Host.Create()
+                 .Handler(tests)
+                 .RunAsync();

+ 0 - 7
frameworks/CSharp/genhttp/Benchmarks/Resources/Fortunes.html

@@ -1,7 +0,0 @@
-<table>
-    <tr><th>id</th><th>message</th></tr>
-    @foreach (var cookie in Model.Cookies)
-    {
-    <tr><td>@cookie.ID</td><td>@HttpUtility.HtmlEncode(cookie.Message)</td></tr>
-    }
-</table>

+ 16 - 3
frameworks/CSharp/genhttp/Benchmarks/Resources/Template.html

@@ -1,9 +1,22 @@
 <!DOCTYPE html>
 <!DOCTYPE html>
 <html>
 <html>
 <head>
 <head>
-    <title>@Model.Meta.Title</title>
+    <title>Fortunes</title>
 </head>
 </head>
 <body>
 <body>
-    @Model.Content
+
+<table>
+    <tr>
+        <th>id</th>
+        <th>message</th>
+    </tr>
+    {for cookie in cookies:
+    <tr>
+        <td>{ cookie.id }</td>
+        <td>{ cookie.message }</td>
+    </tr>
+    }
+</table>
+
 </body>
 </body>
-</html>
+</html>

+ 54 - 54
frameworks/CSharp/genhttp/Benchmarks/Tests/CacheResource.cs

@@ -1,84 +1,84 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Threading.Tasks;
-
+using Benchmarks.Model;
+using GenHTTP.Modules.Webservices;
 using Microsoft.EntityFrameworkCore;
 using Microsoft.EntityFrameworkCore;
 using Microsoft.Extensions.Caching.Memory;
 using Microsoft.Extensions.Caching.Memory;
 
 
-using Benchmarks.Model;
-
-using GenHTTP.Modules.Webservices;
+namespace Benchmarks.Tests;
 
 
-namespace Benchmarks.Tests
+public sealed class CacheResource
 {
 {
+    private static readonly Random Random = new();
 
 
-    public sealed class CacheResource
+    private static readonly MemoryCache Cache = new(new MemoryCacheOptions
     {
     {
-        private static readonly Random _Random = new Random();
-
-        private static readonly MemoryCache _Cache = new MemoryCache(new MemoryCacheOptions() { ExpirationScanFrequency = TimeSpan.FromMinutes(60) });
-
-        private static readonly object[] _CacheKeys = Enumerable.Range(0, 10001).Select((i) => new CacheKey(i)).ToArray();
-
-        public sealed class CacheKey : IEquatable<CacheKey>
-        {
-            private readonly int _value;
-
-            public CacheKey(int value) => _value = value;
+        ExpirationScanFrequency = TimeSpan.FromMinutes(60)
+    });
 
 
-            public bool Equals(CacheKey key) => key._value == _value;
+    private static readonly object[] CacheKeys = Enumerable.Range(0, 10001).Select(i => new CacheKey(i)).ToArray();
 
 
-            public override bool Equals(object obj) => ReferenceEquals(obj, this);
+    [ResourceMethod(":queries")]
+    public ValueTask<List<World>> GetWorldsFromPath(string queries) => GetWorlds(queries);
 
 
-            public override int GetHashCode() => _value;
+    [ResourceMethod]
+    public async ValueTask<List<World>> GetWorlds(string queries)
+    {
+        var count = 1;
 
 
-            public override string ToString() => _value.ToString();
+        int.TryParse(queries, out count);
 
 
+        if (count < 1)
+        {
+            count = 1;
         }
         }
+        else if (count > 500)
+        {
+            count = 500;
+        }
+
+        var result = new List<World>(count);
 
 
-        [ResourceMethod(":queries")]
-        public ValueTask<List<World>> GetWorldsFromPath(string queries) => GetWorlds(queries);
+        await using var context = DatabaseContext.CreateNoTracking();
 
 
-        [ResourceMethod]
-        public async ValueTask<List<World>> GetWorlds(string queries)
+        for (var i = 0; i < count; i++)
         {
         {
-            var count = 1;
+            var id = Random.Next(1, 10001);
 
 
-            int.TryParse(queries, out count);
+            var key = CacheKeys[id];
 
 
-            if (count < 1) count = 1;
-            else if (count > 500) count = 500;
+            var data = Cache.Get<World>(key);
 
 
-            var result = new List<World>(count);
+            if (data != null)
+            {
+                result.Add(data);
+            }
+            else
+            {
+                var resolved = await context.World.FirstOrDefaultAsync(w => w.Id == id).ConfigureAwait(false);
 
 
-            using var context = DatabaseContext.CreateNoTracking();
+                Cache.Set(key, resolved);
 
 
-            for (var i = 0; i < count; i++)
-            {
-                var id = _Random.Next(1, 10001);
+                result.Add(resolved);
+            }
+        }
 
 
-                var key = _CacheKeys[id];
+        return result;
+    }
 
 
-                var data = _Cache.Get<World>(key);
+    public sealed class CacheKey : IEquatable<CacheKey>
+    {
+        private readonly int _value;
 
 
-                if (data != null)
-                {
-                    result.Add(data);
-                }
-                else
-                {
-                    var resolved = await context.World.FirstOrDefaultAsync(w => w.Id == id).ConfigureAwait(false);
+        public CacheKey(int value)
+        {
+            _value = value;
+        }
 
 
-                    _Cache.Set(key, resolved);
+        public bool Equals(CacheKey key) => key._value == _value;
 
 
-                    result.Add(resolved);
-                }
-            }
+        public override bool Equals(object obj) => ReferenceEquals(obj, this);
 
 
-            return result;
-        }
+        public override int GetHashCode() => _value;
 
 
+        public override string ToString() => _value.ToString();
     }
     }
-
 }
 }

+ 10 - 18
frameworks/CSharp/genhttp/Benchmarks/Tests/DbResource.cs

@@ -1,29 +1,21 @@
-using System;
-using System.Threading.Tasks;
-
-using Microsoft.EntityFrameworkCore;
-
+using Benchmarks.Model;
 using GenHTTP.Modules.Webservices;
 using GenHTTP.Modules.Webservices;
+using Microsoft.EntityFrameworkCore;
 
 
-using Benchmarks.Model;
+namespace Benchmarks.Tests;
 
 
-namespace Benchmarks.Tests
+public sealed class DbResource
 {
 {
+    private static readonly Random Random = new();
 
 
-    public sealed class DbResource
+    [ResourceMethod]
+    public async ValueTask<World> GetRandomWorld()
     {
     {
-        private static readonly Random _Random = new();
-
-        [ResourceMethod]
-        public async ValueTask<World> GetRandomWorld()
-        {
-            var id = _Random.Next(1, 10001);
-
-            using var context = DatabaseContext.CreateNoTracking();
+        var id = Random.Next(1, 10001);
 
 
-            return await context.World.FirstOrDefaultAsync(w => w.Id == id).ConfigureAwait(false);
-        }
+        await using var context = DatabaseContext.CreateNoTracking();
 
 
+        return await context.World.FirstOrDefaultAsync(w => w.Id == id).ConfigureAwait(false);
     }
     }
 
 
 }
 }

+ 48 - 79
frameworks/CSharp/genhttp/Benchmarks/Tests/FortuneHandler.cs

@@ -1,116 +1,85 @@
-using System.Collections.Generic;
-using System.Threading.Tasks;
-using System.Linq;
-using System.Web;
-using System.IO;
-
-using Microsoft.EntityFrameworkCore;
-
+using System.Web;
+using Benchmarks.Model;
+using Cottle;
 using GenHTTP.Api.Content;
 using GenHTTP.Api.Content;
-using GenHTTP.Api.Content.Templating;
 using GenHTTP.Api.Protocol;
 using GenHTTP.Api.Protocol;
 
 
 using GenHTTP.Modules.IO;
 using GenHTTP.Modules.IO;
-using GenHTTP.Modules.Razor;
-
-using Benchmarks.Model;
+using GenHTTP.Modules.Pages;
+using GenHTTP.Modules.Pages.Rendering;
 
 
-namespace Benchmarks.Tests
-{
+using Microsoft.EntityFrameworkCore;
 
 
-    #region Factory
+namespace Benchmarks.Tests;
 
 
-    public class FortuneHandlerBuilder : IHandlerBuilder
-    {
+public class FortuneHandler : IHandler
+{
 
 
-        public IHandler Build(IHandler parent)
-        {
-            return new FortuneHandler(parent);
-        }
+    #region Get-/Setters
 
 
-    }
+    private TemplateRenderer Template { get; }
 
 
     #endregion
     #endregion
 
 
-    #region Supporting data structures
+    #region Initialization
 
 
-    public sealed class FortuneModel : BasicModel
+    public FortuneHandler()
     {
     {
+        var resource = Resource.FromAssembly("Template.html").Build();
 
 
-        public List<Fortune> Cookies { get; }
-
-        public FortuneModel(IRequest request, IHandler handler, List<Fortune> cookies) : base(request, handler)
-        {
-            Cookies = cookies;
-        }
-
+        Template = Renderer.From(resource);
     }
     }
 
 
     #endregion
     #endregion
 
 
-    public class FortuneHandler : IHandler, IPageRenderer
-    {
-
-        #region Get-/Setters
-
-        public IHandler Parent { get; }
+    #region Functionality
 
 
-        private IHandler Page { get; }
+    public ValueTask PrepareAsync() => new();
 
 
-        private IRenderer<TemplateModel> Template { get; }
-
-        #endregion
-
-        #region Initialization
-
-        public FortuneHandler(IHandler parent)
+    public async ValueTask<IResponse> HandleAsync(IRequest request)
+    {
+        var data = new Dictionary<Value, Value>
         {
         {
-            Parent = parent;
+            ["cookies"] = Value.FromEnumerable(await GetFortunes())
+        };
 
 
-            Page = ModRazor.Page(Resource.FromAssembly("Fortunes.html"), (r, h) => GetFortunes(r, h))
-                           .Title("Fortunes")
-                           .AddAssemblyReference<HttpUtility>()
-                           .AddUsing("System.Web")
-                           .Build(this);
+        return request.GetPage(await Template.RenderAsync(data)).Build();
+    }
 
 
-            Template = ModRazor.Template<TemplateModel>(Resource.FromAssembly("Template.html")).Build();
-        }
+    private static async ValueTask<List<Value>> GetFortunes()
+    {
+        await using var context = DatabaseContext.CreateNoTracking();
 
 
-        #endregion
+        var fortunes = await context.Fortune.ToListAsync().ConfigureAwait(false);
 
 
-        #region Functionality
+        var result = new List<Value>(fortunes.Count + 1);
 
 
-        public async ValueTask PrepareAsync()
+        foreach (var fortune in fortunes)
         {
         {
-            await Page.PrepareAsync();
-            await Template.PrepareAsync();
+            result.Add(Value.FromDictionary(new Dictionary<Value, Value>()
+            {
+                ["id"] = fortune.Id,
+                ["message"] = HttpUtility.HtmlEncode(fortune.Message)
+            }));
         }
         }
 
 
-        public ValueTask<ulong> CalculateChecksumAsync() => new(17);
-
-        public IAsyncEnumerable<ContentElement> GetContentAsync(IRequest request) => AsyncEnumerable.Empty<ContentElement>();
-
-        public ValueTask<string> RenderAsync(TemplateModel model) => Template.RenderAsync(model);
-
-        public ValueTask RenderAsync(TemplateModel model, Stream target) => Template.RenderAsync(model, target);
-
-        public ValueTask<IResponse> HandleAsync(IRequest request) => Page.HandleAsync(request);
-
-        private static async ValueTask<FortuneModel> GetFortunes(IRequest request, IHandler handler)
+        result.Add(Value.FromDictionary(new Dictionary<Value, Value>()
         {
         {
-            using var context = DatabaseContext.CreateNoTracking();
-
-            var fortunes = await context.Fortune.ToListAsync().ConfigureAwait(false);
-
-            fortunes.Add(new Fortune() { Message = "Additional fortune added at request time." });
-
-            fortunes.Sort();
+            ["id"] = 0,
+            ["message"] = "Additional fortune added at request time."
+        }));
 
 
-            return new FortuneModel(request, handler, fortunes);
-        }
+        result.Sort((one, two) =>
+        {
+            var firstMessage = one.Fields["message"].AsString;
+            var secondMessage = two.Fields["message"].AsString;
 
 
-        #endregion
+            return string.Compare(firstMessage, secondMessage, StringComparison.Ordinal);
+        });
 
 
+        return result;
     }
     }
 
 
+    #endregion
+
 }
 }

+ 11 - 12
frameworks/CSharp/genhttp/Benchmarks/Tests/JsonResource.cs

@@ -1,21 +1,20 @@
 using GenHTTP.Modules.Webservices;
 using GenHTTP.Modules.Webservices;
 
 
-namespace Benchmarks.Tests
-{
+namespace Benchmarks.Tests;
 
 
-    public sealed class JsonResult
-    {
+public sealed class JsonResult
+{
 
 
-        public string Message { get; set; }
+    public string Message { get; set; }
+}
 
 
-    }
+public sealed class JsonResource
+{
 
 
-    public sealed class JsonResource
+    [ResourceMethod]
+    public JsonResult GetMessage() => new()
     {
     {
-
-        [ResourceMethod]
-        public JsonResult GetMessage() => new() { Message = "Hello, World!" };
-
-    }
+        Message = "Hello, World!"
+    };
 
 
 }
 }

+ 27 - 30
frameworks/CSharp/genhttp/Benchmarks/Tests/QueryResource.cs

@@ -1,47 +1,44 @@
-using System;
-using System.Collections.Generic;
-using System.Threading.Tasks;
-
+using Benchmarks.Model;
+using GenHTTP.Modules.Webservices;
 using Microsoft.EntityFrameworkCore;
 using Microsoft.EntityFrameworkCore;
 
 
-using Benchmarks.Model;
-
-using GenHTTP.Modules.Webservices;
+namespace Benchmarks.Tests;
 
 
-namespace Benchmarks.Tests
+public sealed class QueryResource
 {
 {
+    private static readonly Random Random = new();
+
+    [ResourceMethod(":queries")]
+    public ValueTask<List<World>> GetWorldsFromPath(string queries) => GetWorlds(queries);
 
 
-    public sealed class QueryResource
+    [ResourceMethod]
+    public async ValueTask<List<World>> GetWorlds(string queries)
     {
     {
-        private static readonly Random _Random = new Random();
+        var count = 1;
 
 
-        [ResourceMethod(":queries")]
-        public ValueTask<List<World>> GetWorldsFromPath(string queries) => GetWorlds(queries);
+        int.TryParse(queries, out count);
 
 
-        [ResourceMethod]
-        public async ValueTask<List<World>> GetWorlds(string queries)
+        if (count < 1)
         {
         {
-            var count = 1;
-
-            int.TryParse(queries, out count);
-
-            if (count < 1) count = 1;
-            else if (count > 500) count = 500;
-
-            var result = new List<World>(count);
+            count = 1;
+        }
+        else if (count > 500)
+        {
+            count = 500;
+        }
 
 
-            using var context = DatabaseContext.CreateNoTracking();
+        var result = new List<World>(count);
 
 
-            for (int _ = 0; _ < count; _++)
-            {
-                var id = _Random.Next(1, 10001);
+        using var context = DatabaseContext.CreateNoTracking();
 
 
-                result.Add(await context.World.FirstOrDefaultAsync(w => w.Id == id).ConfigureAwait(false));
-            }
+        for (var _ = 0; _ < count; _++)
+        {
+            var id = Random.Next(1, 10001);
 
 
-            return result;
+            result.Add(await context.World.FirstOrDefaultAsync(w => w.Id == id).ConfigureAwait(false));
         }
         }
 
 
+        return result;
     }
     }
 
 
-}
+}

+ 39 - 41
frameworks/CSharp/genhttp/Benchmarks/Tests/UpdateResource.cs

@@ -1,66 +1,64 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Threading.Tasks;
-
+using Benchmarks.Model;
+using GenHTTP.Modules.Webservices;
 using Microsoft.EntityFrameworkCore;
 using Microsoft.EntityFrameworkCore;
 
 
-using Benchmarks.Model;
+namespace Benchmarks.Tests;
 
 
-using GenHTTP.Modules.Webservices;
-
-namespace Benchmarks.Tests
+public sealed class UpdateResource
 {
 {
+    private static readonly Random Random = new();
+
+    [ResourceMethod(":queries")]
+    public ValueTask<List<World>> UpdateWorldsFromPath(string queries) => UpdateWorlds(queries);
 
 
-    public sealed class UpdateResource
+    [ResourceMethod]
+    public async ValueTask<List<World>> UpdateWorlds(string queries)
     {
     {
-        private static Random _Random = new Random();
+        var count = 1;
 
 
-        [ResourceMethod(":queries")]
-        public ValueTask<List<World>> UpdateWorldsFromPath(string queries) => UpdateWorlds(queries);
+        int.TryParse(queries, out count);
 
 
-        [ResourceMethod]
-        public async ValueTask<List<World>> UpdateWorlds(string queries)
+        if (count < 1)
         {
         {
-            var count = 1;
-
-            int.TryParse(queries, out count);
-
-            if (count < 1) count = 1;
-            else if (count > 500) count = 500;
+            count = 1;
+        }
+        else if (count > 500)
+        {
+            count = 500;
+        }
 
 
-            var result = new List<World>(count);
+        var result = new List<World>(count);
 
 
-            var ids = Enumerable.Range(1, 10000).Select(x => _Random.Next(1, 10001)).Distinct().Take(count).ToArray();
+        var ids = Enumerable.Range(1, 10000).Select(x => Random.Next(1, 10001)).Distinct().Take(count).ToArray();
 
 
-            using (var context = DatabaseContext.Create())
+        using (var context = DatabaseContext.Create())
+        {
+            foreach (var id in ids)
             {
             {
-                foreach (var id in ids)
-                {
-                    var record = await context.World.FirstOrDefaultAsync(w => w.Id == id).ConfigureAwait(false);
+                var record = await context.World.FirstOrDefaultAsync(w => w.Id == id).ConfigureAwait(false);
 
 
-                    var old = record.RandomNumber;
+                var old = record.RandomNumber;
 
 
-                    var current = old;
+                var current = old;
 
 
-                    for (int i = 0; i < 5; i++)
-                    {
-                        current = _Random.Next(1, 10001);
+                for (var i = 0; i < 5; i++)
+                {
+                    current = Random.Next(1, 10001);
 
 
-                        if (current != old) break;
+                    if (current != old)
+                    {
+                        break;
                     }
                     }
+                }
 
 
-                    record.RandomNumber = current;
+                record.RandomNumber = current;
 
 
-                    result.Add(record);
+                result.Add(record);
 
 
-                    await context.SaveChangesAsync();
-                }
+                await context.SaveChangesAsync();
             }
             }
-
-            return result;
         }
         }
 
 
+        return result;
     }
     }
-
-}
+}

+ 4 - 8
frameworks/CSharp/genhttp/Benchmarks/Utilities/ServerHeader.cs

@@ -1,11 +1,7 @@
-namespace Benchmarks.Utilities
-{
-
-    public static class ServerHeader
-    {
+namespace Benchmarks.Utilities;
 
 
-        public static ServerHeaderConcernBuilder Create() => new ServerHeaderConcernBuilder();
-
-    }
+public static class ServerHeader
+{
 
 
+    public static ServerHeaderConcernBuilder Create() => new();
 }
 }

+ 23 - 36
frameworks/CSharp/genhttp/Benchmarks/Utilities/ServerHeaderConcern.cs

@@ -1,55 +1,42 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Threading.Tasks;
-
-using GenHTTP.Api.Content;
+using GenHTTP.Api.Content;
 using GenHTTP.Api.Protocol;
 using GenHTTP.Api.Protocol;
 
 
-namespace Benchmarks.Utilities
-{
-
-    public sealed class ServerHeaderConcern : IConcern
-    {
+namespace Benchmarks.Utilities;
 
 
-        #region Get-/Setters
+public sealed class ServerHeaderConcern : IConcern
+{
 
 
-        public IHandler Content { get; }
+    #region Initialization
 
 
-        public IHandler Parent { get; }
+    public ServerHeaderConcern(IHandler content)
+    {
+        Content = content;
+    }
 
 
-        #endregion
+    #endregion
 
 
-        #region Initialization
+    #region Get-/Setters
 
 
-        public ServerHeaderConcern(IHandler parent, Func<IHandler, IHandler> contentFactory)
-        {
-            Parent = parent;
-            Content = contentFactory(this);
-        }
+    public IHandler Content { get; }
 
 
-        #endregion
+    #endregion
 
 
-        #region Functionality
+    #region Functionality
 
 
-        public IAsyncEnumerable<ContentElement> GetContentAsync(IRequest request) => Content.GetContentAsync(request);
+    public ValueTask PrepareAsync() => Content.PrepareAsync();
 
 
-        public ValueTask PrepareAsync() => Content.PrepareAsync();
+    public async ValueTask<IResponse> HandleAsync(IRequest request)
+    {
+        var response = await Content.HandleAsync(request);
 
 
-        public async ValueTask<IResponse> HandleAsync(IRequest request)
+        if (response != null)
         {
         {
-            var response = await Content.HandleAsync(request);
-
-            if (response != null)
-            {
-                response.Headers.Add("Server", "TFB");
-            }
-
-            return response;
+            response.Headers.Add("Server", "TFB");
         }
         }
 
 
-        #endregion
-
+        return response;
     }
     }
 
 
+    #endregion
+
 }
 }

+ 4 - 12
frameworks/CSharp/genhttp/Benchmarks/Utilities/ServerHeaderConcernBuilder.cs

@@ -1,18 +1,10 @@
-using System;
+using GenHTTP.Api.Content;
 
 
-using GenHTTP.Api.Content;
+namespace Benchmarks.Utilities;
 
 
-namespace Benchmarks.Utilities
+public sealed class ServerHeaderConcernBuilder : IConcernBuilder
 {
 {
 
 
-    public sealed class ServerHeaderConcernBuilder : IConcernBuilder
-    {
-
-        public IConcern Build(IHandler parent, Func<IHandler, IHandler> contentFactory)
-        {
-            return new ServerHeaderConcern(parent, contentFactory);
-        }
-
-    }
+    public IConcern Build(IHandler content) => new ServerHeaderConcern(content);
 
 
 }
 }

+ 2 - 2
frameworks/CSharp/genhttp/README.md

@@ -6,11 +6,11 @@ See the [GenHTTP website](https://genhttp.org) for more information.
 
 
 **Language**
 **Language**
 
 
-* C# 8.0
+* C# 13.0
 
 
 **Platforms**
 **Platforms**
 
 
-* .NET Core
+* .NET 8/9
 
 
 **Web Servers**
 **Web Servers**
 
 

+ 1 - 1
frameworks/CSharp/genhttp/benchmark_config.json

@@ -17,7 +17,7 @@
       "language": "C#",
       "language": "C#",
       "orm": "Raw",
       "orm": "Raw",
       "platform": ".NET",
       "platform": ".NET",
-      "webserver": "GenHTTP",
+      "webserver": "Kestrel",
       "os": "Linux",
       "os": "Linux",
       "database_os": "Linux",
       "database_os": "Linux",
       "display_name": "GenHTTP",
       "display_name": "GenHTTP",

+ 1 - 1
frameworks/CSharp/genhttp/config.toml

@@ -16,5 +16,5 @@ database_os = "Linux"
 os = "Linux"
 os = "Linux"
 orm = "Raw"
 orm = "Raw"
 platform = ".NET"
 platform = ".NET"
-webserver = "GenHTTP"
+webserver = "Kestrel"
 versus = "None"
 versus = "None"

+ 13 - 13
frameworks/CSharp/genhttp/genhttp.dockerfile

@@ -1,19 +1,19 @@
-FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build
-WORKDIR /app
-COPY Benchmarks .
-RUN dotnet publish -c Release -o out
+FROM mcr.microsoft.com/dotnet/sdk:9.0-alpine AS build
+WORKDIR /source
 
 
-FROM mcr.microsoft.com/dotnet/runtime:8.0 AS runtime
-ENV DOTNET_SYSTEM_NET_SOCKETS_INLINE_COMPLETIONS 1
+# copy csproj and restore as distinct layers
+COPY Benchmarks/*.csproj .
+RUN dotnet restore -r linux-musl-x64
 
 
-# Full PGO
-ENV DOTNET_TieredPGO 1 
-ENV DOTNET_TC_QuickJitForLoops 1 
-ENV DOTNET_ReadyToRun 0
+# copy and publish app and libraries
+COPY Benchmarks/ .
+RUN dotnet publish -c release -o /app -r linux-musl-x64 --no-restore --self-contained
 
 
+# final stage/image
+FROM mcr.microsoft.com/dotnet/runtime-deps:9.0-alpine
 WORKDIR /app
 WORKDIR /app
-COPY --from=build /app/out ./
+COPY --from=build /app .
 
 
-EXPOSE 8080
+ENTRYPOINT ["./Benchmarks"]
 
 
-ENTRYPOINT ["dotnet", "Benchmarks.dll"]
+EXPOSE 8080

+ 2 - 2
frameworks/CSharp/reaper/reaper.dockerfile

@@ -1,4 +1,4 @@
-FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build
+FROM mcr.microsoft.com/dotnet/sdk:9.0 AS build
 WORKDIR /src
 WORKDIR /src
 COPY src .
 COPY src .
 RUN apt-get update \
 RUN apt-get update \
@@ -7,7 +7,7 @@ RUN apt-get update \
 WORKDIR "/src/Benchmark"
 WORKDIR "/src/Benchmark"
 RUN dotnet publish "Benchmark.csproj" -c Release -o /app/publish
 RUN dotnet publish "Benchmark.csproj" -c Release -o /app/publish
 
 
-FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS final
+FROM mcr.microsoft.com/dotnet/aspnet:9.0 AS final
 WORKDIR /app
 WORKDIR /app
 EXPOSE 8080
 EXPOSE 8080
 COPY --from=build /app/publish .
 COPY --from=build /app/publish .

+ 3 - 3
frameworks/CSharp/reaper/src/Benchmark/Benchmark.csproj

@@ -1,7 +1,7 @@
 <Project Sdk="Microsoft.NET.Sdk.Web">
 <Project Sdk="Microsoft.NET.Sdk.Web">
 
 
     <PropertyGroup>
     <PropertyGroup>
-        <TargetFramework>net8.0</TargetFramework>
+        <TargetFramework>net9.0</TargetFramework>
         <Nullable>enable</Nullable>
         <Nullable>enable</Nullable>
         <ImplicitUsings>enable</ImplicitUsings>
         <ImplicitUsings>enable</ImplicitUsings>
         <DockerDefaultTargetOS>Linux</DockerDefaultTargetOS>
         <DockerDefaultTargetOS>Linux</DockerDefaultTargetOS>
@@ -18,8 +18,8 @@
     </ItemGroup>
     </ItemGroup>
     
     
     <ItemGroup>
     <ItemGroup>
-        <PackageReference Include="Reaper.Core" Version="0.1.0-alpha.0.6" />
-        <PackageReference Include="Reaper.SourceGenerator" Version="0.1.0-alpha.0.6" />
+        <PackageReference Include="Reaper.Core" Version="0.1.0-alpha.0.43" />
+        <PackageReference Include="Reaper.SourceGenerator" Version="0.1.0-alpha.0.43" />
     </ItemGroup>
     </ItemGroup>
 
 
 </Project>
 </Project>

+ 3 - 2
frameworks/CSharp/reaper/src/Benchmark/JsonEndpoint.cs

@@ -11,9 +11,10 @@ public class JsonResponse
 [ReaperRoute(HttpVerbs.Get, "/json")]
 [ReaperRoute(HttpVerbs.Get, "/json")]
 public class JsonEndpoint : ReaperEndpointXR<JsonResponse>
 public class JsonEndpoint : ReaperEndpointXR<JsonResponse>
 {
 {
-    public override Task<JsonResponse> HandleAsync()
+    public override Task ExecuteAsync()
     {
     {
         Context.Response.ContentLength = 27;
         Context.Response.ContentLength = 27;
-        return Task.FromResult(new JsonResponse { Message = "Hello, World!" });
+        Result = new JsonResponse { Message = "Hello, World!" };
+        return Task.CompletedTask;
     }
     }
 }
 }

+ 3 - 2
frameworks/CSharp/reaper/src/Benchmark/PlainTextEndpoint.cs

@@ -6,11 +6,12 @@ namespace Benchmark;
 [ReaperRoute(HttpVerbs.Get, "/plaintext")]
 [ReaperRoute(HttpVerbs.Get, "/plaintext")]
 public class PlainTextEndpoint : ReaperEndpointXR<string>
 public class PlainTextEndpoint : ReaperEndpointXR<string>
 {
 {
-    public override Task<string> HandleAsync()
+    public override Task ExecuteAsync()
     {
     {
         Context.Response.StatusCode = 200;
         Context.Response.StatusCode = 200;
         Context.Response.ContentType = "text/plain";
         Context.Response.ContentType = "text/plain";
         Context.Response.ContentLength = 13;
         Context.Response.ContentLength = 13;
-        return Task.FromResult("Hello, World!");
+        Result = "Hello, World!";
+        return Task.CompletedTask;
     }
     }
 }
 }

+ 1 - 10
frameworks/CSharp/reaper/src/Benchmark/Program.cs

@@ -1,14 +1,8 @@
-using System.Text.Json.Serialization;
-using Benchmark;
 using Reaper;
 using Reaper;
 
 
 var builder = WebApplication.CreateSlimBuilder(args);
 var builder = WebApplication.CreateSlimBuilder(args);
 builder.Logging.ClearProviders();
 builder.Logging.ClearProviders();
 builder.Logging.Configure(o => o.ActivityTrackingOptions = ActivityTrackingOptions.None);
 builder.Logging.Configure(o => o.ActivityTrackingOptions = ActivityTrackingOptions.None);
-builder.Services.ConfigureHttpJsonOptions(o =>
-{
-    o.SerializerOptions.TypeInfoResolverChain.Insert(0, SourceGenerationContext.Default);
-});
 builder.UseReaper();
 builder.UseReaper();
 
 
 var app = builder.Build();
 var app = builder.Build();
@@ -16,7 +10,4 @@ var app = builder.Build();
 app.UseReaperMiddleware();
 app.UseReaperMiddleware();
 app.MapReaperEndpoints();
 app.MapReaperEndpoints();
 
 
-app.Run();
-
-[JsonSerializable(typeof(JsonResponse))]
-internal partial class SourceGenerationContext : JsonSerializerContext { }
+app.Run();

+ 1 - 1
frameworks/CSharp/reaper/src/Benchmark/appsettings.Development.json

@@ -5,4 +5,4 @@
       "Microsoft.AspNetCore": "Warning"
       "Microsoft.AspNetCore": "Warning"
     }
     }
   }
   }
-}
+}

+ 1 - 1
frameworks/Crystal/kemal/kemal.dockerfile

@@ -1,4 +1,4 @@
-FROM crystallang/crystal:1.12.1
+FROM crystallang/crystal:1.14.0
 
 
 WORKDIR /kemal
 WORKDIR /kemal
 COPY views views
 COPY views views

+ 1 - 1
frameworks/Crystal/kemal/shard.lock

@@ -18,7 +18,7 @@ shards:
 
 
   kemal:
   kemal:
     git: https://github.com/kemalcr/kemal.git
     git: https://github.com/kemalcr/kemal.git
-    version: 1.5.0
+    version: 1.6.0
 
 
   pg:
   pg:
     git: https://github.com/will/crystal-pg.git
     git: https://github.com/will/crystal-pg.git

+ 1 - 1
frameworks/Crystal/kemal/shard.yml

@@ -9,7 +9,7 @@ dependencies:
     version: 0.28.0
     version: 0.28.0
   kemal:
   kemal:
     github: kemalcr/kemal
     github: kemalcr/kemal
-    version: 1.5.0
+    version: 1.6.0
   redis:
   redis:
     github: stefanwille/crystal-redis
     github: stefanwille/crystal-redis
     version: 2.8.0
     version: 2.8.0

+ 2 - 2
frameworks/Crystal/lucky/lucky.dockerfile

@@ -1,4 +1,4 @@
-FROM crystallang/crystal:1.12.1
+FROM crystallang/crystal:1.14.0
 
 
 WORKDIR /lucky
 WORKDIR /lucky
 COPY shard.lock shard.lock
 COPY shard.lock shard.lock
@@ -14,7 +14,7 @@ ENV LUCKY_ENV production
 
 
 RUN shards build bench --release --no-debug
 RUN shards build bench --release --no-debug
 
 
-ENV DATABASE_URL postgres://benchmarkdbuser:benchmarkdbpass@tfb-database:5432/hello_world?initial_pool_size=56&max_idle_pool_size=56
+ENV DATABASE_URL postgres://benchmarkdbuser:benchmarkdbpass@tfb-database:5432/hello_world?initial_pool_size=10&max_idle_pool_size=10
 
 
 EXPOSE 8080
 EXPOSE 8080
 
 

+ 3 - 3
frameworks/Crystal/lucky/shard.lock

@@ -2,7 +2,7 @@ version: 2.0
 shards:
 shards:
   avram:
   avram:
     git: https://github.com/luckyframework/avram.git
     git: https://github.com/luckyframework/avram.git
-    version: 1.2.0
+    version: 1.3.0
 
 
   backtracer:
   backtracer:
     git: https://github.com/sija/backtracer.cr.git
     git: https://github.com/sija/backtracer.cr.git
@@ -30,7 +30,7 @@ shards:
 
 
   habitat:
   habitat:
     git: https://github.com/luckyframework/habitat.git
     git: https://github.com/luckyframework/habitat.git
-    version: 0.4.8
+    version: 0.4.9
 
 
   lucky:
   lucky:
     git: https://github.com/luckyframework/lucky.git
     git: https://github.com/luckyframework/lucky.git
@@ -66,7 +66,7 @@ shards:
 
 
   splay_tree_map:
   splay_tree_map:
     git: https://github.com/wyhaines/splay_tree_map.cr.git
     git: https://github.com/wyhaines/splay_tree_map.cr.git
-    version: 0.2.2
+    version: 0.3.0
 
 
   wordsmith:
   wordsmith:
     git: https://github.com/luckyframework/wordsmith.git
     git: https://github.com/luckyframework/wordsmith.git

+ 12 - 10
frameworks/Elixir/phoenix/config/dev.exs

@@ -1,13 +1,15 @@
 import Config
 import Config
 
 
-# For development, we disable any cache and enable
-# debugging and code reloading.
-#
-# The watchers configuration can be used to run external
-# watchers to your application. For example, we use it
-# with brunch.io to recompile .js and .css sources.
 config :hello, HelloWeb.Endpoint,
 config :hello, HelloWeb.Endpoint,
-  http: [port: 8080],
+  adapter: Bandit.PhoenixAdapter,
+  http: [
+    port: 4000,
+    ip: {0, 0, 0, 0},
+    http_options: [
+      compress: false,
+      log_protocol_errors: :verbose
+    ],
+  ],
   debug_errors: true,
   debug_errors: true,
   code_reloader: true,
   code_reloader: true,
   cache_static_lookup: false
   cache_static_lookup: false
@@ -23,10 +25,10 @@ config :hello, HelloWeb.Endpoint,
   ]
   ]
 
 
 config :hello, Hello.Repo,
 config :hello, Hello.Repo,
-  username: "benchmarkdbuser",
-  password: "benchmarkdbpass",
+  username: "postgres",
+  password: "postgres",
   database: "hello_world",
   database: "hello_world",
-  hostname: "tfb-database"
+  hostname: "localhost"
 
 
 # Do not include metadata nor timestamps in development logs
 # Do not include metadata nor timestamps in development logs
 config :logger, :console, format: "[$level] $message\n"
 config :logger, :console, format: "[$level] $message\n"

+ 4 - 1
frameworks/Elixir/phoenix/config/prod.exs

@@ -8,7 +8,10 @@ config :hello, HelloWeb.Endpoint,
     http_options: [
     http_options: [
       compress: false,
       compress: false,
       log_protocol_errors: false
       log_protocol_errors: false
-    ]
+    ],
+    thousand_island_options: [
+      transport_options: [ backlog: 8192 ]
+    ],
   ],
   ],
   compress: false,
   compress: false,
   check_origin: false,
   check_origin: false,

+ 0 - 3
frameworks/Elixir/phoenix/lib/hello_web.ex

@@ -29,7 +29,6 @@ defmodule HelloWeb do
         log: false
         log: false
 
 
       import Plug.Conn
       import Plug.Conn
-      import HelloWeb.Gettext
 
 
       unquote(verified_routes())
       unquote(verified_routes())
     end
     end
@@ -39,8 +38,6 @@ defmodule HelloWeb do
     quote do
     quote do
       use Phoenix.Component
       use Phoenix.Component
 
 
-      import HelloWeb.Gettext
-
       # Routes generation with the ~p sigil
       # Routes generation with the ~p sigil
       unquote(verified_routes())
       unquote(verified_routes())
     end
     end

+ 1 - 1
frameworks/Elixir/phoenix/lib/hello_web/controllers/page_controller.ex

@@ -78,7 +78,7 @@ defmodule HelloWeb.PageController do
     json(conn, world_updates)
     json(conn, world_updates)
   end
   end
 
 
-   def plaintext(conn, _params) do
+  def plaintext(conn, _params) do
     conn
     conn
     |> put_resp_header("content-type", "text/plain")
     |> put_resp_header("content-type", "text/plain")
     |> send_resp(200, "Hello, World!")
     |> send_resp(200, "Hello, World!")

+ 0 - 24
frameworks/Elixir/phoenix/lib/hello_web/gettext.ex

@@ -1,24 +0,0 @@
-defmodule HelloWeb.Gettext do
-  @moduledoc """
-  A module providing Internationalization with a gettext-based API.
-
-  By using [Gettext](https://hexdocs.pm/gettext),
-  your module gains a set of macros for translations, for example:
-
-      import HelloWeb.Gettext
-
-      # Simple translation
-      gettext("Here is the string to translate")
-
-      # Plural translation
-      ngettext("Here is the string to translate",
-               "Here are the strings to translate",
-               3)
-
-      # Domain-based translation
-      dgettext("errors", "Here is the error message to translate")
-
-  See the [Gettext Docs](https://hexdocs.pm/gettext) for detailed usage.
-  """
-  use Gettext, otp_app: :hello
-end

+ 1 - 3
frameworks/Elixir/phoenix/mix.exs

@@ -29,15 +29,13 @@ defmodule Hello.Mixfile do
   # Type `mix help deps` for examples and options
   # Type `mix help deps` for examples and options
   defp deps do
   defp deps do
     [
     [
-      {:bandit, "1.5.7"},
-      {:gettext, "~> 0.20"},
+      {:bandit, "~> 1.6.1"},
       {:ecto_sql, "~> 3.10"},
       {:ecto_sql, "~> 3.10"},
       {:jason, "~> 1.2"},
       {:jason, "~> 1.2"},
       {:phoenix, "~> 1.7"},
       {:phoenix, "~> 1.7"},
       {:phoenix_live_view, "~> 0.18"},
       {:phoenix_live_view, "~> 0.18"},
       {:phoenix_ecto, "~> 4.4"},
       {:phoenix_ecto, "~> 4.4"},
       {:phoenix_html, "~> 4.1"},
       {:phoenix_html, "~> 4.1"},
-      {:plug_cowboy, "~> 2.5"},
       {:postgrex, ">= 0.0.0"},
       {:postgrex, ">= 0.0.0"},
       {:nebulex, "~> 2.6"}
       {:nebulex, "~> 2.6"}
     ]
     ]

+ 11 - 18
frameworks/Elixir/phoenix/mix.lock

@@ -1,32 +1,25 @@
 %{
 %{
-  "bandit": {:hex, :bandit, "1.5.7", "6856b1e1df4f2b0cb3df1377eab7891bec2da6a7fd69dc78594ad3e152363a50", [:mix], [{:hpax, "~> 1.0.0", [hex: :hpax, repo: "hexpm", optional: false]}, {:plug, "~> 1.14", [hex: :plug, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}, {:thousand_island, "~> 1.0", [hex: :thousand_island, repo: "hexpm", optional: false]}, {:websock, "~> 0.5", [hex: :websock, repo: "hexpm", optional: false]}], "hexpm", "f2dd92ae87d2cbea2fa9aa1652db157b6cba6c405cb44d4f6dd87abba41371cd"},
-  "castore": {:hex, :castore, "1.0.8", "dedcf20ea746694647f883590b82d9e96014057aff1d44d03ec90f36a5c0dc6e", [:mix], [], "hexpm", "0b2b66d2ee742cb1d9cb8c8be3b43c3a70ee8651f37b75a8b982e036752983f1"},
-  "cowboy": {:hex, :cowboy, "2.12.0", "f276d521a1ff88b2b9b4c54d0e753da6c66dd7be6c9fca3d9418b561828a3731", [:make, :rebar3], [{:cowlib, "2.13.0", [hex: :cowlib, repo: "hexpm", optional: false]}, {:ranch, "1.8.0", [hex: :ranch, repo: "hexpm", optional: false]}], "hexpm", "8a7abe6d183372ceb21caa2709bec928ab2b72e18a3911aa1771639bef82651e"},
-  "cowboy_telemetry": {:hex, :cowboy_telemetry, "0.4.0", "f239f68b588efa7707abce16a84d0d2acf3a0f50571f8bb7f56a15865aae820c", [:rebar3], [{:cowboy, "~> 2.7", [hex: :cowboy, repo: "hexpm", optional: false]}, {:telemetry, "~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "7d98bac1ee4565d31b62d59f8823dfd8356a169e7fcbb83831b8a5397404c9de"},
-  "cowlib": {:hex, :cowlib, "2.13.0", "db8f7505d8332d98ef50a3ef34b34c1afddec7506e4ee4dd4a3a266285d282ca", [:make, :rebar3], [], "hexpm", "e1e1284dc3fc030a64b1ad0d8382ae7e99da46c3246b815318a4b848873800a4"},
+  "bandit": {:hex, :bandit, "1.6.1", "9e01b93d72ddc21d8c576a704949e86ee6cde7d11270a1d3073787876527a48f", [:mix], [{:hpax, "~> 1.0", [hex: :hpax, repo: "hexpm", optional: false]}, {:plug, "~> 1.14", [hex: :plug, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}, {:thousand_island, "~> 1.0", [hex: :thousand_island, repo: "hexpm", optional: false]}, {:websock, "~> 0.5", [hex: :websock, repo: "hexpm", optional: false]}], "hexpm", "5a904bf010ea24b67979835e0507688e31ac873d4ffc8ed0e5413e8d77455031"},
+  "castore": {:hex, :castore, "1.0.10", "43bbeeac820f16c89f79721af1b3e092399b3a1ecc8df1a472738fd853574911", [:mix], [], "hexpm", "1b0b7ea14d889d9ea21202c43a4fa015eb913021cb535e8ed91946f4b77a8848"},
   "db_connection": {:hex, :db_connection, "2.7.0", "b99faa9291bb09892c7da373bb82cba59aefa9b36300f6145c5f201c7adf48ec", [:mix], [{:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "dcf08f31b2701f857dfc787fbad78223d61a32204f217f15e881dd93e4bdd3ff"},
   "db_connection": {:hex, :db_connection, "2.7.0", "b99faa9291bb09892c7da373bb82cba59aefa9b36300f6145c5f201c7adf48ec", [:mix], [{:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "dcf08f31b2701f857dfc787fbad78223d61a32204f217f15e881dd93e4bdd3ff"},
-  "decimal": {:hex, :decimal, "2.1.1", "5611dca5d4b2c3dd497dec8f68751f1f1a54755e8ed2a966c2633cf885973ad6", [:mix], [], "hexpm", "53cfe5f497ed0e7771ae1a475575603d77425099ba5faef9394932b35020ffcc"},
-  "ecto": {:hex, :ecto, "3.12.4", "267c94d9f2969e6acc4dd5e3e3af5b05cdae89a4d549925f3008b2b7eb0b93c3", [:mix], [{:decimal, "~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "ef04e4101688a67d061e1b10d7bc1fbf00d1d13c17eef08b71d070ff9188f747"},
+  "decimal": {:hex, :decimal, "2.2.0", "df3d06bb9517e302b1bd265c1e7f16cda51547ad9d99892049340841f3e15836", [:mix], [], "hexpm", "af8daf87384b51b7e611fb1a1f2c4d4876b65ef968fa8bd3adf44cff401c7f21"},
+  "ecto": {:hex, :ecto, "3.12.5", "4a312960ce612e17337e7cefcf9be45b95a3be6b36b6f94dfb3d8c361d631866", [:mix], [{:decimal, "~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "6eb18e80bef8bb57e17f5a7f068a1719fbda384d40fc37acb8eb8aeca493b6ea"},
   "ecto_sql": {:hex, :ecto_sql, "3.12.1", "c0d0d60e85d9ff4631f12bafa454bc392ce8b9ec83531a412c12a0d415a3a4d0", [:mix], [{:db_connection, "~> 2.4.1 or ~> 2.5", [hex: :db_connection, repo: "hexpm", optional: false]}, {:ecto, "~> 3.12", [hex: :ecto, repo: "hexpm", optional: false]}, {:myxql, "~> 0.7", [hex: :myxql, repo: "hexpm", optional: true]}, {:postgrex, "~> 0.19 or ~> 1.0", [hex: :postgrex, repo: "hexpm", optional: true]}, {:tds, "~> 2.1.1 or ~> 2.2", [hex: :tds, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4.0 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "aff5b958a899762c5f09028c847569f7dfb9cc9d63bdb8133bff8a5546de6bf5"},
   "ecto_sql": {:hex, :ecto_sql, "3.12.1", "c0d0d60e85d9ff4631f12bafa454bc392ce8b9ec83531a412c12a0d415a3a4d0", [:mix], [{:db_connection, "~> 2.4.1 or ~> 2.5", [hex: :db_connection, repo: "hexpm", optional: false]}, {:ecto, "~> 3.12", [hex: :ecto, repo: "hexpm", optional: false]}, {:myxql, "~> 0.7", [hex: :myxql, repo: "hexpm", optional: true]}, {:postgrex, "~> 0.19 or ~> 1.0", [hex: :postgrex, repo: "hexpm", optional: true]}, {:tds, "~> 2.1.1 or ~> 2.2", [hex: :tds, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4.0 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "aff5b958a899762c5f09028c847569f7dfb9cc9d63bdb8133bff8a5546de6bf5"},
-  "expo": {:hex, :expo, "1.0.0", "647639267e088717232f4d4451526e7a9de31a3402af7fcbda09b27e9a10395a", [:mix], [], "hexpm", "18d2093d344d97678e8a331ca0391e85d29816f9664a25653fd7e6166827827c"},
-  "gettext": {:hex, :gettext, "0.25.0", "98a95a862a94e2d55d24520dd79256a15c87ea75b49673a2e2f206e6ebc42e5d", [:mix], [{:expo, "~> 0.5.1 or ~> 1.0", [hex: :expo, repo: "hexpm", optional: false]}], "hexpm", "38e5d754e66af37980a94fb93bb20dcde1d2361f664b0a19f01e87296634051f"},
-  "hpax": {:hex, :hpax, "1.0.0", "28dcf54509fe2152a3d040e4e3df5b265dcb6cb532029ecbacf4ce52caea3fd2", [:mix], [], "hexpm", "7f1314731d711e2ca5fdc7fd361296593fc2542570b3105595bb0bc6d0fad601"},
+  "hpax": {:hex, :hpax, "1.0.1", "c857057f89e8bd71d97d9042e009df2a42705d6d690d54eca84c8b29af0787b0", [:mix], [], "hexpm", "4e2d5a4f76ae1e3048f35ae7adb1641c36265510a2d4638157fbcb53dda38445"},
   "jason": {:hex, :jason, "1.4.4", "b9226785a9aa77b6857ca22832cffa5d5011a667207eb2a0ad56adb5db443b8a", [:mix], [{:decimal, "~> 1.0 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "c5eb0cab91f094599f94d55bc63409236a8ec69a21a67814529e8d5f6cc90b3b"},
   "jason": {:hex, :jason, "1.4.4", "b9226785a9aa77b6857ca22832cffa5d5011a667207eb2a0ad56adb5db443b8a", [:mix], [{:decimal, "~> 1.0 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "c5eb0cab91f094599f94d55bc63409236a8ec69a21a67814529e8d5f6cc90b3b"},
   "mime": {:hex, :mime, "2.0.6", "8f18486773d9b15f95f4f4f1e39b710045fa1de891fada4516559967276e4dc2", [:mix], [], "hexpm", "c9945363a6b26d747389aac3643f8e0e09d30499a138ad64fe8fd1d13d9b153e"},
   "mime": {:hex, :mime, "2.0.6", "8f18486773d9b15f95f4f4f1e39b710045fa1de891fada4516559967276e4dc2", [:mix], [], "hexpm", "c9945363a6b26d747389aac3643f8e0e09d30499a138ad64fe8fd1d13d9b153e"},
-  "nebulex": {:hex, :nebulex, "2.6.3", "78af348ed9f8a338871b41e0b6de718c1808e627ce03fbe86598cbda2bdda2f5", [:mix], [{:decorator, "~> 1.4", [hex: :decorator, repo: "hexpm", optional: true]}, {:shards, "~> 1.1", [hex: :shards, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: true]}], "hexpm", "09cdcbb62f8463ffcec7cae4936425ce91e25d92a6cd37e48b5dda7c851958d5"},
-  "phoenix": {:hex, :phoenix, "1.7.14", "a7d0b3f1bc95987044ddada111e77bd7f75646a08518942c72a8440278ae7825", [:mix], [{:castore, ">= 0.0.0", [hex: :castore, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:phoenix_pubsub, "~> 2.1", [hex: :phoenix_pubsub, repo: "hexpm", optional: false]}, {:phoenix_template, "~> 1.0", [hex: :phoenix_template, repo: "hexpm", optional: false]}, {:phoenix_view, "~> 2.0", [hex: :phoenix_view, repo: "hexpm", optional: true]}, {:plug, "~> 1.14", [hex: :plug, repo: "hexpm", optional: false]}, {:plug_cowboy, "~> 2.7", [hex: :plug_cowboy, repo: "hexpm", optional: true]}, {:plug_crypto, "~> 1.2 or ~> 2.0", [hex: :plug_crypto, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}, {:websock_adapter, "~> 0.5.3", [hex: :websock_adapter, repo: "hexpm", optional: false]}], "hexpm", "c7859bc56cc5dfef19ecfc240775dae358cbaa530231118a9e014df392ace61a"},
-  "phoenix_ecto": {:hex, :phoenix_ecto, "4.6.2", "3b83b24ab5a2eb071a20372f740d7118767c272db386831b2e77638c4dcc606d", [:mix], [{:ecto, "~> 3.5", [hex: :ecto, repo: "hexpm", optional: false]}, {:phoenix_html, "~> 2.14.2 or ~> 3.0 or ~> 4.1", [hex: :phoenix_html, repo: "hexpm", optional: true]}, {:plug, "~> 1.9", [hex: :plug, repo: "hexpm", optional: false]}, {:postgrex, "~> 0.16 or ~> 1.0", [hex: :postgrex, repo: "hexpm", optional: true]}], "hexpm", "3f94d025f59de86be00f5f8c5dd7b5965a3298458d21ab1c328488be3b5fcd59"},
+  "nebulex": {:hex, :nebulex, "2.6.4", "4b00706e0e676474783d988962abf74614480e13c0a32645acb89bb32b660e09", [:mix], [{:decorator, "~> 1.4", [hex: :decorator, repo: "hexpm", optional: true]}, {:shards, "~> 1.1", [hex: :shards, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: true]}], "hexpm", "25bdabf3fb86035c8151bba60bda20f80f96ae0261db7bd4090878ff63b03581"},
+  "phoenix": {:hex, :phoenix, "1.7.17", "2fcdceecc6fb90bec26fab008f96abbd0fd93bc9956ec7985e5892cf545152ca", [:mix], [{:castore, ">= 0.0.0", [hex: :castore, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:phoenix_pubsub, "~> 2.1", [hex: :phoenix_pubsub, repo: "hexpm", optional: false]}, {:phoenix_template, "~> 1.0", [hex: :phoenix_template, repo: "hexpm", optional: false]}, {:phoenix_view, "~> 2.0", [hex: :phoenix_view, repo: "hexpm", optional: true]}, {:plug, "~> 1.14", [hex: :plug, repo: "hexpm", optional: false]}, {:plug_cowboy, "~> 2.7", [hex: :plug_cowboy, repo: "hexpm", optional: true]}, {:plug_crypto, "~> 1.2 or ~> 2.0", [hex: :plug_crypto, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}, {:websock_adapter, "~> 0.5.3", [hex: :websock_adapter, repo: "hexpm", optional: false]}], "hexpm", "50e8ad537f3f7b0efb1509b2f75b5c918f697be6a45d48e49a30d3b7c0e464c9"},
+  "phoenix_ecto": {:hex, :phoenix_ecto, "4.6.3", "f686701b0499a07f2e3b122d84d52ff8a31f5def386e03706c916f6feddf69ef", [:mix], [{:ecto, "~> 3.5", [hex: :ecto, repo: "hexpm", optional: false]}, {:phoenix_html, "~> 2.14.2 or ~> 3.0 or ~> 4.1", [hex: :phoenix_html, repo: "hexpm", optional: true]}, {:plug, "~> 1.9", [hex: :plug, repo: "hexpm", optional: false]}, {:postgrex, "~> 0.16 or ~> 1.0", [hex: :postgrex, repo: "hexpm", optional: true]}], "hexpm", "909502956916a657a197f94cc1206d9a65247538de8a5e186f7537c895d95764"},
   "phoenix_html": {:hex, :phoenix_html, "4.1.1", "4c064fd3873d12ebb1388425a8f2a19348cef56e7289e1998e2d2fa758aa982e", [:mix], [], "hexpm", "f2f2df5a72bc9a2f510b21497fd7d2b86d932ec0598f0210fed4114adc546c6f"},
   "phoenix_html": {:hex, :phoenix_html, "4.1.1", "4c064fd3873d12ebb1388425a8f2a19348cef56e7289e1998e2d2fa758aa982e", [:mix], [], "hexpm", "f2f2df5a72bc9a2f510b21497fd7d2b86d932ec0598f0210fed4114adc546c6f"},
   "phoenix_live_view": {:hex, :phoenix_live_view, "0.20.17", "f396bbdaf4ba227b82251eb75ac0afa6b3da5e509bc0d030206374237dfc9450", [:mix], [{:floki, "~> 0.36", [hex: :floki, repo: "hexpm", optional: true]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:phoenix, "~> 1.6.15 or ~> 1.7.0", [hex: :phoenix, repo: "hexpm", optional: false]}, {:phoenix_html, "~> 3.3 or ~> 4.0", [hex: :phoenix_html, repo: "hexpm", optional: false]}, {:phoenix_template, "~> 1.0", [hex: :phoenix_template, repo: "hexpm", optional: false]}, {:phoenix_view, "~> 2.0", [hex: :phoenix_view, repo: "hexpm", optional: true]}, {:plug, "~> 1.15", [hex: :plug, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4.2 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "a61d741ffb78c85fdbca0de084da6a48f8ceb5261a79165b5a0b59e5f65ce98b"},
   "phoenix_live_view": {:hex, :phoenix_live_view, "0.20.17", "f396bbdaf4ba227b82251eb75ac0afa6b3da5e509bc0d030206374237dfc9450", [:mix], [{:floki, "~> 0.36", [hex: :floki, repo: "hexpm", optional: true]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:phoenix, "~> 1.6.15 or ~> 1.7.0", [hex: :phoenix, repo: "hexpm", optional: false]}, {:phoenix_html, "~> 3.3 or ~> 4.0", [hex: :phoenix_html, repo: "hexpm", optional: false]}, {:phoenix_template, "~> 1.0", [hex: :phoenix_template, repo: "hexpm", optional: false]}, {:phoenix_view, "~> 2.0", [hex: :phoenix_view, repo: "hexpm", optional: true]}, {:plug, "~> 1.15", [hex: :plug, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4.2 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "a61d741ffb78c85fdbca0de084da6a48f8ceb5261a79165b5a0b59e5f65ce98b"},
   "phoenix_pubsub": {:hex, :phoenix_pubsub, "2.1.3", "3168d78ba41835aecad272d5e8cd51aa87a7ac9eb836eabc42f6e57538e3731d", [:mix], [], "hexpm", "bba06bc1dcfd8cb086759f0edc94a8ba2bc8896d5331a1e2c2902bf8e36ee502"},
   "phoenix_pubsub": {:hex, :phoenix_pubsub, "2.1.3", "3168d78ba41835aecad272d5e8cd51aa87a7ac9eb836eabc42f6e57538e3731d", [:mix], [], "hexpm", "bba06bc1dcfd8cb086759f0edc94a8ba2bc8896d5331a1e2c2902bf8e36ee502"},
   "phoenix_template": {:hex, :phoenix_template, "1.0.4", "e2092c132f3b5e5b2d49c96695342eb36d0ed514c5b252a77048d5969330d639", [:mix], [{:phoenix_html, "~> 2.14.2 or ~> 3.0 or ~> 4.0", [hex: :phoenix_html, repo: "hexpm", optional: true]}], "hexpm", "2c0c81f0e5c6753faf5cca2f229c9709919aba34fab866d3bc05060c9c444206"},
   "phoenix_template": {:hex, :phoenix_template, "1.0.4", "e2092c132f3b5e5b2d49c96695342eb36d0ed514c5b252a77048d5969330d639", [:mix], [{:phoenix_html, "~> 2.14.2 or ~> 3.0 or ~> 4.0", [hex: :phoenix_html, repo: "hexpm", optional: true]}], "hexpm", "2c0c81f0e5c6753faf5cca2f229c9709919aba34fab866d3bc05060c9c444206"},
   "plug": {:hex, :plug, "1.16.1", "40c74619c12f82736d2214557dedec2e9762029b2438d6d175c5074c933edc9d", [:mix], [{:mime, "~> 1.0 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:plug_crypto, "~> 1.1.1 or ~> 1.2 or ~> 2.0", [hex: :plug_crypto, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4.3 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "a13ff6b9006b03d7e33874945b2755253841b238c34071ed85b0e86057f8cddc"},
   "plug": {:hex, :plug, "1.16.1", "40c74619c12f82736d2214557dedec2e9762029b2438d6d175c5074c933edc9d", [:mix], [{:mime, "~> 1.0 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:plug_crypto, "~> 1.1.1 or ~> 1.2 or ~> 2.0", [hex: :plug_crypto, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4.3 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "a13ff6b9006b03d7e33874945b2755253841b238c34071ed85b0e86057f8cddc"},
-  "plug_cowboy": {:hex, :plug_cowboy, "2.7.1", "87677ffe3b765bc96a89be7960f81703223fe2e21efa42c125fcd0127dd9d6b2", [:mix], [{:cowboy, "~> 2.7", [hex: :cowboy, repo: "hexpm", optional: false]}, {:cowboy_telemetry, "~> 0.3", [hex: :cowboy_telemetry, repo: "hexpm", optional: false]}, {:plug, "~> 1.14", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm", "02dbd5f9ab571b864ae39418db7811618506256f6d13b4a45037e5fe78dc5de3"},
   "plug_crypto": {:hex, :plug_crypto, "2.1.0", "f44309c2b06d249c27c8d3f65cfe08158ade08418cf540fd4f72d4d6863abb7b", [:mix], [], "hexpm", "131216a4b030b8f8ce0f26038bc4421ae60e4bb95c5cf5395e1421437824c4fa"},
   "plug_crypto": {:hex, :plug_crypto, "2.1.0", "f44309c2b06d249c27c8d3f65cfe08158ade08418cf540fd4f72d4d6863abb7b", [:mix], [], "hexpm", "131216a4b030b8f8ce0f26038bc4421ae60e4bb95c5cf5395e1421437824c4fa"},
-  "postgrex": {:hex, :postgrex, "0.19.0", "f7d50e50cb42e0a185f5b9a6095125a9ab7e4abccfbe2ab820ab9aa92b71dbab", [:mix], [{:db_connection, "~> 2.1", [hex: :db_connection, repo: "hexpm", optional: false]}, {:decimal, "~> 1.5 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:table, "~> 0.1.0", [hex: :table, repo: "hexpm", optional: true]}], "hexpm", "dba2d2a0a8637defbf2307e8629cb2526388ba7348f67d04ec77a5d6a72ecfae"},
-  "ranch": {:hex, :ranch, "1.8.0", "8c7a100a139fd57f17327b6413e4167ac559fbc04ca7448e9be9057311597a1d", [:make, :rebar3], [], "hexpm", "49fbcfd3682fab1f5d109351b61257676da1a2fdbe295904176d5e521a2ddfe5"},
+  "postgrex": {:hex, :postgrex, "0.19.3", "a0bda6e3bc75ec07fca5b0a89bffd242ca209a4822a9533e7d3e84ee80707e19", [:mix], [{:db_connection, "~> 2.1", [hex: :db_connection, repo: "hexpm", optional: false]}, {:decimal, "~> 1.5 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:table, "~> 0.1.0", [hex: :table, repo: "hexpm", optional: true]}], "hexpm", "d31c28053655b78f47f948c85bb1cf86a9c1f8ead346ba1aa0d0df017fa05b61"},
   "telemetry": {:hex, :telemetry, "1.3.0", "fedebbae410d715cf8e7062c96a1ef32ec22e764197f70cda73d82778d61e7a2", [:rebar3], [], "hexpm", "7015fc8919dbe63764f4b4b87a95b7c0996bd539e0d499be6ec9d7f3875b79e6"},
   "telemetry": {:hex, :telemetry, "1.3.0", "fedebbae410d715cf8e7062c96a1ef32ec22e764197f70cda73d82778d61e7a2", [:rebar3], [], "hexpm", "7015fc8919dbe63764f4b4b87a95b7c0996bd539e0d499be6ec9d7f3875b79e6"},
-  "thousand_island": {:hex, :thousand_island, "1.3.5", "6022b6338f1635b3d32406ff98d68b843ba73b3aa95cfc27154223244f3a6ca5", [:mix], [{:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "2be6954916fdfe4756af3239fb6b6d75d0b8063b5df03ba76fd8a4c87849e180"},
+  "thousand_island": {:hex, :thousand_island, "1.3.7", "1da7598c0f4f5f50562c097a3f8af308ded48cd35139f0e6f17d9443e4d0c9c5", [:mix], [{:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "0139335079953de41d381a6134d8b618d53d084f558c734f2662d1a72818dd12"},
   "websock": {:hex, :websock, "0.5.3", "2f69a6ebe810328555b6fe5c831a851f485e303a7c8ce6c5f675abeb20ebdadc", [:mix], [], "hexpm", "6105453d7fac22c712ad66fab1d45abdf049868f253cf719b625151460b8b453"},
   "websock": {:hex, :websock, "0.5.3", "2f69a6ebe810328555b6fe5c831a851f485e303a7c8ce6c5f675abeb20ebdadc", [:mix], [], "hexpm", "6105453d7fac22c712ad66fab1d45abdf049868f253cf719b625151460b8b453"},
-  "websock_adapter": {:hex, :websock_adapter, "0.5.6", "0437fe56e093fd4ac422de33bf8fc89f7bc1416a3f2d732d8b2c8fd54792fe60", [:mix], [{:bandit, ">= 0.6.0", [hex: :bandit, repo: "hexpm", optional: true]}, {:plug, "~> 1.14", [hex: :plug, repo: "hexpm", optional: false]}, {:plug_cowboy, "~> 2.6", [hex: :plug_cowboy, repo: "hexpm", optional: true]}, {:websock, "~> 0.5", [hex: :websock, repo: "hexpm", optional: false]}], "hexpm", "e04378d26b0af627817ae84c92083b7e97aca3121196679b73c73b99d0d133ea"},
+  "websock_adapter": {:hex, :websock_adapter, "0.5.8", "3b97dc94e407e2d1fc666b2fb9acf6be81a1798a2602294aac000260a7c4a47d", [:mix], [{:bandit, ">= 0.6.0", [hex: :bandit, repo: "hexpm", optional: true]}, {:plug, "~> 1.14", [hex: :plug, repo: "hexpm", optional: false]}, {:plug_cowboy, "~> 2.6", [hex: :plug_cowboy, repo: "hexpm", optional: true]}, {:websock, "~> 0.5", [hex: :websock, repo: "hexpm", optional: false]}], "hexpm", "315b9a1865552212b5f35140ad194e67ce31af45bcee443d4ecb96b5fd3f3782"},
 }
 }

+ 2 - 0
frameworks/Elixir/phoenix/phoenix.dockerfile

@@ -9,6 +9,8 @@ FROM ${BUILDER_IMAGE} AS builder
 
 
 ARG MIX_ENV="prod"
 ARG MIX_ENV="prod"
 
 
+RUN apk add --no-cache git
+
 RUN mix local.hex --force && \
 RUN mix local.hex --force && \
     mix local.rebar --force
     mix local.rebar --force
 
 

+ 4 - 2
frameworks/FSharp/oxpecker/oxpecker.dockerfile

@@ -1,11 +1,13 @@
-FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build
+FROM mcr.microsoft.com/dotnet/sdk:9.0 AS build
 WORKDIR /app
 WORKDIR /app
 COPY src/App .
 COPY src/App .
 RUN dotnet publish -c Release -o out
 RUN dotnet publish -c Release -o out
 
 
-FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS runtime
+FROM mcr.microsoft.com/dotnet/aspnet:9.0 AS runtime
 
 
+ENV DOTNET_GCDynamicAdaptationMode=0
 ENV DOTNET_ReadyToRun 0
 ENV DOTNET_ReadyToRun 0
+ENV DOTNET_HillClimbing_Disable=1
 ENV ASPNETCORE_hostBuilder__reloadConfigOnChange false
 ENV ASPNETCORE_hostBuilder__reloadConfigOnChange false
 
 
 ENV URLS http://+:8080
 ENV URLS http://+:8080

+ 6 - 6
frameworks/FSharp/oxpecker/src/App/App.fsproj

@@ -1,7 +1,7 @@
 <Project Sdk="Microsoft.NET.Sdk.Web">
 <Project Sdk="Microsoft.NET.Sdk.Web">
 
 
   <PropertyGroup>
   <PropertyGroup>
-    <TargetFramework>net8.0</TargetFramework>
+    <TargetFramework>net9.0</TargetFramework>
     <EnableDefaultContentItems>false</EnableDefaultContentItems>
     <EnableDefaultContentItems>false</EnableDefaultContentItems>
   </PropertyGroup>
   </PropertyGroup>
 
 
@@ -13,10 +13,10 @@
   </ItemGroup>
   </ItemGroup>
 
 
   <ItemGroup>
   <ItemGroup>
-    <PackageReference Update="FSharp.Core" Version="8.0.400" />
-    <PackageReference Include="Oxpecker" Version="0.14.1" />
-    <PackageReference Include="Oxpecker.ViewEngine" Version="0.14.0" />
-    <PackageReference Include="Npgsql" Version="8.0.3" />
-    <PackageReference Include="SpanJson" Version="4.2.0" />
+    <PackageReference Update="FSharp.Core" Version="9.0.100" />
+    <PackageReference Include="Oxpecker" Version="1.1.1" />
+    <PackageReference Include="Oxpecker.ViewEngine" Version="1.0.0" />
+    <PackageReference Include="Npgsql" Version="9.0.1" />
+    <PackageReference Include="SpanJson" Version="4.2.1" />
   </ItemGroup>
   </ItemGroup>
 </Project>
 </Project>

+ 4 - 2
frameworks/FSharp/oxpecker/src/App/Common.fs

@@ -9,7 +9,7 @@ module Common =
     [<Struct>]
     [<Struct>]
     [<CLIMutable>]
     [<CLIMutable>]
     type JsonMessage = {
     type JsonMessage = {
-        message : string
+        message: string
     }
     }
 
 
     [<CLIMutable>]
     [<CLIMutable>]
@@ -26,7 +26,9 @@ module Common =
     }
     }
 
 
     [<Literal>]
     [<Literal>]
-    let ConnectionString = "Server=tfb-database;Database=hello_world;User Id=benchmarkdbuser;Password=benchmarkdbpass;Maximum Pool Size=1024;NoResetOnClose=true;Enlist=false;Max Auto Prepare=3"
+    let ConnectionString = "Server=tfb-database;Database=hello_world;User Id=benchmarkdbuser;Password=benchmarkdbpass;Maximum Pool Size=1024;NoResetOnClose=true;Enlist=false;Max Auto Prepare=4"
+    [<Literal>]
+    let MultiplexedConnectionString = ConnectionString + ";Multiplexing=true"
 
 
     let FortuneComparer = {
     let FortuneComparer = {
         new IComparer<Fortune> with
         new IComparer<Fortune> with

+ 15 - 12
frameworks/FSharp/oxpecker/src/App/Db.fs

@@ -2,8 +2,7 @@ namespace App
 
 
 open System
 open System
 open System.Data
 open System.Data
-open System.Data.Common
-open System.Text
+open Microsoft.Extensions.ObjectPool
 open Npgsql
 open Npgsql
 
 
 
 
@@ -31,7 +30,7 @@ module Db =
             TypedValue = Random.Shared.Next(1, 10001)
             TypedValue = Random.Shared.Next(1, 10001)
         )
         )
         cmd.Parameters.Add(id) |> ignore
         cmd.Parameters.Add(id) |> ignore
-        cmd
+        struct(cmd, id)
 
 
     let private readSingleRow (cmd: NpgsqlCommand) =
     let private readSingleRow (cmd: NpgsqlCommand) =
         task {
         task {
@@ -43,19 +42,21 @@ module Db =
     let loadSingleRow () =
     let loadSingleRow () =
         task {
         task {
             use db = new NpgsqlConnection(ConnectionString)
             use db = new NpgsqlConnection(ConnectionString)
+            let struct(cmd', _) = createReadCommand db
+            use cmd = cmd'
             do! db.OpenAsync()
             do! db.OpenAsync()
-            use cmd = createReadCommand db
             return! readSingleRow cmd
             return! readSingleRow cmd
         }
         }
 
 
     let private readMultipleRows (count: int) (conn: NpgsqlConnection) =
     let private readMultipleRows (count: int) (conn: NpgsqlConnection) =
         let result = Array.zeroCreate count
         let result = Array.zeroCreate count
         task {
         task {
-            use cmd = createReadCommand conn
+            let struct(cmd', idParam) = createReadCommand conn
+            use cmd = cmd'
             for i in 0..result.Length-1 do
             for i in 0..result.Length-1 do
-                cmd.Parameters["@Id"].Value <- Random.Shared.Next(1, 10001)
                 let! row = readSingleRow cmd
                 let! row = readSingleRow cmd
                 result[i] <- row
                 result[i] <- row
+                idParam.TypedValue <- Random.Shared.Next(1, 10001)
             return result
             return result
         }
         }
 
 
@@ -68,16 +69,18 @@ module Db =
 
 
     let private maxBatch = 500
     let private maxBatch = 500
     let private queries = Array.zeroCreate (maxBatch + 1)
     let private queries = Array.zeroCreate (maxBatch + 1)
+    let private stringBuilderPool = DefaultObjectPoolProvider().CreateStringBuilderPool()
     let private batchUpdateString batchSize =
     let private batchUpdateString batchSize =
         match queries[batchSize] with
         match queries[batchSize] with
         | null ->
         | null ->
             let lastIndex = batchSize - 1
             let lastIndex = batchSize - 1
-            let sb = StringBuilder()
+            let sb = stringBuilderPool.Get()
             sb.Append("UPDATE world SET randomNumber = temp.randomNumber FROM (VALUES ") |> ignore
             sb.Append("UPDATE world SET randomNumber = temp.randomNumber FROM (VALUES ") |> ignore
             for i in 0..lastIndex-1 do
             for i in 0..lastIndex-1 do
                 sb.AppendFormat("(@Id_{0}, @Rn_{0}), ", i) |> ignore
                 sb.AppendFormat("(@Id_{0}, @Rn_{0}), ", i) |> ignore
             sb.AppendFormat("(@Id_{0}, @Rn_{0}) ORDER BY 1) AS temp(id, randomNumber) WHERE temp.id = world.id", lastIndex) |> ignore
             sb.AppendFormat("(@Id_{0}, @Rn_{0}) ORDER BY 1) AS temp(id, randomNumber) WHERE temp.id = world.id", lastIndex) |> ignore
             let result = sb.ToString()
             let result = sb.ToString()
+            stringBuilderPool.Return(sb)
             queries[batchSize] <- result
             queries[batchSize] <- result
             result
             result
         | q ->
         | q ->
@@ -95,15 +98,15 @@ module Db =
         for i in 0..results.Length-1 do
         for i in 0..results.Length-1 do
             let randomNumber = Random.Shared.Next(1, 10001)
             let randomNumber = Random.Shared.Next(1, 10001)
             let struct(rnParamName, idParamName) = paramNames[i]
             let struct(rnParamName, idParamName) = paramNames[i]
-            let random = NpgsqlParameter<int>(ParameterName = rnParamName, DbType = DbType.Int32, TypedValue = randomNumber)
-            command.Parameters.Add(random) |> ignore
-            let id = NpgsqlParameter<int>(ParameterName = idParamName, DbType = DbType.Int32, TypedValue = results[i].id)
-            command.Parameters.Add(id) |> ignore
+            command.Parameters.Add(NpgsqlParameter<int>(
+                ParameterName = rnParamName, DbType = DbType.Int32, TypedValue = randomNumber)) |> ignore
+            command.Parameters.Add(NpgsqlParameter<int>(
+                ParameterName = idParamName, DbType = DbType.Int32, TypedValue = results[i].id)) |> ignore
             results[i] <- { results[i] with randomnumber = randomNumber }
             results[i] <- { results[i] with randomnumber = randomNumber }
 
 
     let doMultipleUpdates (count: int) =
     let doMultipleUpdates (count: int) =
         task {
         task {
-            use conn = new NpgsqlConnection(ConnectionString)
+            use conn = new NpgsqlConnection(MultiplexedConnectionString)
             do! conn.OpenAsync()
             do! conn.OpenAsync()
             let! results = readMultipleRows count conn
             let! results = readMultipleRows count conn
             use cmd = conn.CreateCommand(CommandText = batchUpdateString count)
             use cmd = conn.CreateCommand(CommandText = batchUpdateString count)

+ 13 - 26
frameworks/FSharp/oxpecker/src/App/Program.fs

@@ -2,13 +2,21 @@ namespace App
 
 
 open System
 open System
 open Oxpecker
 open Oxpecker
-open System.Runtime.InteropServices
 
 
 [<RequireQualifiedAccess>]
 [<RequireQualifiedAccess>]
-module HtmlViews =
+module HttpHandlers =
+    open System.Text
+    open Microsoft.AspNetCore.Http
+    open SpanJson
     open Oxpecker.ViewEngine
     open Oxpecker.ViewEngine
 
 
-    let private head, tail =
+    let private extra =
+        {
+            id = 0
+            message = "Additional fortune added at request time."
+        }
+
+    let private fortunesHeadAndTail =
         (fun (content: HtmlElement) ->
         (fun (content: HtmlElement) ->
             html() {
             html() {
                 head() {
                 head() {
@@ -26,32 +34,11 @@ module HtmlViews =
             } :> HtmlElement
             } :> HtmlElement
         ) |> RenderHelpers.prerender
         ) |> RenderHelpers.prerender
 
 
-    let fortunes (fortunesData: ResizeArray<Fortune>) =
-        let fragment = __()
-        for fortune in CollectionsMarshal.AsSpan fortunesData do
-            tr() {
-                td() { raw <| string fortune.id }
-                td() { fortune.message }
-            }
-            |> fragment.AddChild
-        RenderHelpers.combine head tail fragment
-
-[<RequireQualifiedAccess>]
-module HttpHandlers =
-    open System.Text
-    open Microsoft.AspNetCore.Http
-    open SpanJson
-
-    let private extra =
-        {
-            id      = 0
-            message = "Additional fortune added at request time."
-        }
-
     let rec private renderFortunes (ctx: HttpContext) (data: ResizeArray<Fortune>) =
     let rec private renderFortunes (ctx: HttpContext) (data: ResizeArray<Fortune>) =
         data.Add extra
         data.Add extra
         data.Sort FortuneComparer
         data.Sort FortuneComparer
-        data |> HtmlViews.fortunes |> ctx.WriteHtmlViewChunked
+        RenderHelpers.CombinedElement(fortunesHeadAndTail, data)
+        |> ctx.WriteHtmlViewChunked
 
 
     let fortunes : EndpointHandler =
     let fortunes : EndpointHandler =
         fun ctx ->
         fun ctx ->

+ 20 - 9
frameworks/FSharp/oxpecker/src/App/RenderHelpers.fs

@@ -1,8 +1,27 @@
 module RenderHelpers
 module RenderHelpers
 
 
     open System.Text
     open System.Text
+    open App
     open Oxpecker.ViewEngine
     open Oxpecker.ViewEngine
 
 
+    type HeadAndTail =
+        {
+            Head: string
+            Tail: string
+        }
+
+    [<Struct>]
+    type CombinedElement(ht: HeadAndTail, fortunesData: ResizeArray<Fortune>) =
+        interface HtmlElement with
+            member this.Render(sb) =
+                sb.Append(ht.Head) |> ignore
+                for fortune in fortunesData do
+                    (tr() {
+                        td() { raw <| string fortune.id }
+                        td() { fortune.message }
+                    }).Render(sb)
+                sb.Append(ht.Tail) |> ignore
+
     let prerender (view: HtmlElement -> HtmlElement) =
     let prerender (view: HtmlElement -> HtmlElement) =
         let sb = StringBuilder()
         let sb = StringBuilder()
         let mutable head = ""
         let mutable head = ""
@@ -13,12 +32,4 @@
                  sb.Clear() |> ignore }
                  sb.Clear() |> ignore }
         let readyView = view fakeHole
         let readyView = view fakeHole
         readyView.Render(sb)
         readyView.Render(sb)
-        (head, sb.ToString())
-
-    let inline combine (head: string) (tail: string) (hole: HtmlElement) =
-        { new HtmlElement with
-            member this.Render(sb) =
-                sb.Append(head) |> ignore
-                hole.Render(sb)
-                sb.Append(tail) |> ignore
-        }
+        { Head = head; Tail = sb.ToString() }

+ 4 - 4
frameworks/Go/fiber/src/go.mod

@@ -23,8 +23,8 @@ require (
 	github.com/valyala/bytebufferpool v1.0.0 // indirect
 	github.com/valyala/bytebufferpool v1.0.0 // indirect
 	github.com/valyala/fasthttp v1.55.0 // indirect
 	github.com/valyala/fasthttp v1.55.0 // indirect
 	github.com/valyala/tcplisten v1.0.0 // indirect
 	github.com/valyala/tcplisten v1.0.0 // indirect
-	golang.org/x/crypto v0.27.0 // indirect
-	golang.org/x/sync v0.8.0 // indirect
-	golang.org/x/sys v0.25.0 // indirect
-	golang.org/x/text v0.18.0 // indirect
+	golang.org/x/crypto v0.31.0 // indirect
+	golang.org/x/sync v0.10.0 // indirect
+	golang.org/x/sys v0.28.0 // indirect
+	golang.org/x/text v0.21.0 // indirect
 )
 )

+ 8 - 8
frameworks/Go/fiber/src/go.sum

@@ -44,16 +44,16 @@ github.com/valyala/quicktemplate v1.8.0 h1:zU0tjbIqTRgKQzFY1L42zq0qR3eh4WoQQdIdq
 github.com/valyala/quicktemplate v1.8.0/go.mod h1:qIqW8/igXt8fdrUln5kOSb+KWMaJ4Y8QUsfd1k6L2jM=
 github.com/valyala/quicktemplate v1.8.0/go.mod h1:qIqW8/igXt8fdrUln5kOSb+KWMaJ4Y8QUsfd1k6L2jM=
 github.com/valyala/tcplisten v1.0.0 h1:rBHj/Xf+E1tRGZyWIWwJDiRY0zc1Js+CV5DqwacVSA8=
 github.com/valyala/tcplisten v1.0.0 h1:rBHj/Xf+E1tRGZyWIWwJDiRY0zc1Js+CV5DqwacVSA8=
 github.com/valyala/tcplisten v1.0.0/go.mod h1:T0xQ8SeCZGxckz9qRXTfG43PvQ/mcWh7FwZEA7Ioqkc=
 github.com/valyala/tcplisten v1.0.0/go.mod h1:T0xQ8SeCZGxckz9qRXTfG43PvQ/mcWh7FwZEA7Ioqkc=
-golang.org/x/crypto v0.27.0 h1:GXm2NjJrPaiv/h1tb2UH8QfgC/hOf/+z0p6PT8o1w7A=
-golang.org/x/crypto v0.27.0/go.mod h1:1Xngt8kV6Dvbssa53Ziq6Eqn0HqbZi5Z6R0ZpwQzt70=
-golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ=
-golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
+golang.org/x/crypto v0.31.0 h1:ihbySMvVjLAeSH1IbfcRTkD/iNscyz8rGzjF/E5hV6U=
+golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk=
+golang.org/x/sync v0.10.0 h1:3NQrjDixjgGwUOCaF8w2+VYHv0Ve/vGYSbdkTa98gmQ=
+golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
 golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.25.0 h1:r+8e+loiHxRqhXVl6ML1nO3l1+oFoWbnlu2Ehimmi34=
-golang.org/x/sys v0.25.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
-golang.org/x/text v0.18.0 h1:XvMDiNzPAl0jr17s6W9lcaIhGUfUORdGCNsuLmPG224=
-golang.org/x/text v0.18.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY=
+golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA=
+golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
+golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo=
+golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ=
 gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
 gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
 gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
 gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
 gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
 gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=

+ 1 - 1
frameworks/Go/goravel/src/fiber/go.mod

@@ -65,7 +65,7 @@ require (
 	github.com/gofiber/template v1.8.3 // indirect
 	github.com/gofiber/template v1.8.3 // indirect
 	github.com/gofiber/template/html/v2 v2.1.1 // indirect
 	github.com/gofiber/template/html/v2 v2.1.1 // indirect
 	github.com/gofiber/utils v1.1.0 // indirect
 	github.com/gofiber/utils v1.1.0 // indirect
-	github.com/golang-jwt/jwt/v4 v4.5.0 // indirect
+	github.com/golang-jwt/jwt/v4 v4.5.1 // indirect
 	github.com/golang-jwt/jwt/v5 v5.2.1 // indirect
 	github.com/golang-jwt/jwt/v5 v5.2.1 // indirect
 	github.com/golang-migrate/migrate/v4 v4.17.1 // indirect
 	github.com/golang-migrate/migrate/v4 v4.17.1 // indirect
 	github.com/golang-module/carbon/v2 v2.3.12 // indirect
 	github.com/golang-module/carbon/v2 v2.3.12 // indirect

+ 2 - 1
frameworks/Go/goravel/src/fiber/go.sum

@@ -285,8 +285,9 @@ github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
 github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
 github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
 github.com/golang-jwt/jwt/v4 v4.0.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg=
 github.com/golang-jwt/jwt/v4 v4.0.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg=
 github.com/golang-jwt/jwt/v4 v4.4.3/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0=
 github.com/golang-jwt/jwt/v4 v4.4.3/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0=
-github.com/golang-jwt/jwt/v4 v4.5.0 h1:7cYmW1XlMY7h7ii7UhUyChSgS5wUJEnm9uZVTGqOWzg=
 github.com/golang-jwt/jwt/v4 v4.5.0/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0=
 github.com/golang-jwt/jwt/v4 v4.5.0/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0=
+github.com/golang-jwt/jwt/v4 v4.5.1 h1:JdqV9zKUdtaa9gdPlywC3aeoEsR681PlKC+4F5gQgeo=
+github.com/golang-jwt/jwt/v4 v4.5.1/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0=
 github.com/golang-jwt/jwt/v5 v5.0.0/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk=
 github.com/golang-jwt/jwt/v5 v5.0.0/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk=
 github.com/golang-jwt/jwt/v5 v5.2.1 h1:OuVbFODueb089Lh128TAcimifWaLhJwVflnrgM17wHk=
 github.com/golang-jwt/jwt/v5 v5.2.1 h1:OuVbFODueb089Lh128TAcimifWaLhJwVflnrgM17wHk=
 github.com/golang-jwt/jwt/v5 v5.2.1/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk=
 github.com/golang-jwt/jwt/v5 v5.2.1/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk=

+ 1 - 1
frameworks/Go/goravel/src/gin/go.mod

@@ -65,7 +65,7 @@ require (
 	github.com/go-sql-driver/mysql v1.8.1 // indirect
 	github.com/go-sql-driver/mysql v1.8.1 // indirect
 	github.com/go-stack/stack v1.8.0 // indirect
 	github.com/go-stack/stack v1.8.0 // indirect
 	github.com/goccy/go-json v0.10.2 // indirect
 	github.com/goccy/go-json v0.10.2 // indirect
-	github.com/golang-jwt/jwt/v4 v4.5.0 // indirect
+	github.com/golang-jwt/jwt/v4 v4.5.1 // indirect
 	github.com/golang-jwt/jwt/v5 v5.2.1 // indirect
 	github.com/golang-jwt/jwt/v5 v5.2.1 // indirect
 	github.com/golang-migrate/migrate/v4 v4.17.1 // indirect
 	github.com/golang-migrate/migrate/v4 v4.17.1 // indirect
 	github.com/golang-module/carbon/v2 v2.3.12 // indirect
 	github.com/golang-module/carbon/v2 v2.3.12 // indirect

+ 2 - 1
frameworks/Go/goravel/src/gin/go.sum

@@ -287,8 +287,9 @@ github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
 github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
 github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
 github.com/golang-jwt/jwt/v4 v4.0.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg=
 github.com/golang-jwt/jwt/v4 v4.0.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg=
 github.com/golang-jwt/jwt/v4 v4.4.3/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0=
 github.com/golang-jwt/jwt/v4 v4.4.3/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0=
-github.com/golang-jwt/jwt/v4 v4.5.0 h1:7cYmW1XlMY7h7ii7UhUyChSgS5wUJEnm9uZVTGqOWzg=
 github.com/golang-jwt/jwt/v4 v4.5.0/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0=
 github.com/golang-jwt/jwt/v4 v4.5.0/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0=
+github.com/golang-jwt/jwt/v4 v4.5.1 h1:JdqV9zKUdtaa9gdPlywC3aeoEsR681PlKC+4F5gQgeo=
+github.com/golang-jwt/jwt/v4 v4.5.1/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0=
 github.com/golang-jwt/jwt/v5 v5.0.0/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk=
 github.com/golang-jwt/jwt/v5 v5.0.0/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk=
 github.com/golang-jwt/jwt/v5 v5.2.1 h1:OuVbFODueb089Lh128TAcimifWaLhJwVflnrgM17wHk=
 github.com/golang-jwt/jwt/v5 v5.2.1 h1:OuVbFODueb089Lh128TAcimifWaLhJwVflnrgM17wHk=
 github.com/golang-jwt/jwt/v5 v5.2.1/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk=
 github.com/golang-jwt/jwt/v5 v5.2.1/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk=

+ 4 - 4
frameworks/Go/hertz/go.mod

@@ -28,9 +28,9 @@ require (
 	github.com/tidwall/pretty v1.2.0 // indirect
 	github.com/tidwall/pretty v1.2.0 // indirect
 	github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
 	github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
 	golang.org/x/arch v0.0.0-20210923205945-b76863e36670 // indirect
 	golang.org/x/arch v0.0.0-20210923205945-b76863e36670 // indirect
-	golang.org/x/crypto v0.17.0 // indirect
-	golang.org/x/sync v0.1.0 // indirect
-	golang.org/x/sys v0.15.0 // indirect
-	golang.org/x/text v0.14.0 // indirect
+	golang.org/x/crypto v0.31.0 // indirect
+	golang.org/x/sync v0.10.0 // indirect
+	golang.org/x/sys v0.28.0 // indirect
+	golang.org/x/text v0.21.0 // indirect
 	google.golang.org/protobuf v1.33.0 // indirect
 	google.golang.org/protobuf v1.33.0 // indirect
 )
 )

+ 8 - 8
frameworks/Go/hertz/go.sum

@@ -77,20 +77,20 @@ golang.org/x/arch v0.0.0-20201008161808-52c3e6f60cff/go.mod h1:flIaEI6LNU6xOCD5P
 golang.org/x/arch v0.0.0-20210923205945-b76863e36670 h1:18EFjUmQOcUvxNYSkA6jO9VAiXCnxFY6NyDX0bHDmkU=
 golang.org/x/arch v0.0.0-20210923205945-b76863e36670 h1:18EFjUmQOcUvxNYSkA6jO9VAiXCnxFY6NyDX0bHDmkU=
 golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8=
 golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8=
 golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
 golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
-golang.org/x/crypto v0.17.0 h1:r8bRNjWL3GshPW3gkd+RpvzWrZAwPS49OmTGZ/uhM4k=
-golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4=
+golang.org/x/crypto v0.31.0 h1:ihbySMvVjLAeSH1IbfcRTkD/iNscyz8rGzjF/E5hV6U=
+golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk=
 golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
 golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
 golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
-golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o=
-golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.10.0 h1:3NQrjDixjgGwUOCaF8w2+VYHv0Ve/vGYSbdkTa98gmQ=
+golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
 golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 golang.org/x/sys v0.0.0-20220110181412-a018aaa089fe/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.0.0-20220110181412-a018aaa089fe/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc=
-golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
+golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA=
+golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
 golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
 golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
-golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
-golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
+golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo=
+golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ=
 golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
 golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
 golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
 golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
 golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
 golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=

+ 11 - 0
frameworks/Go/pine/README.md

@@ -0,0 +1,11 @@
+# Pine Benchmarking Test
+
+## Test URLs
+
+### JSON
+
+http://localhost:8080/json
+
+### PLAINTEXT
+
+http://localhost:8080/plaintext

+ 26 - 0
frameworks/Go/pine/benchmark_config.json

@@ -0,0 +1,26 @@
+{
+  "framework": "pine",
+  "tests": [
+    {
+      "default": {
+        "json_url": "/json",
+        "plaintext_url": "/plaintext",
+        "port": 8080,
+        "approach": "Realistic",
+        "classification": "Micro",
+        "database": "None",
+        "framework": "Pine",
+        "language": "Go",
+        "flavor": "None",
+        "orm": "None",
+        "platform": "None",
+        "webserver": "None",
+        "os": "Linux",
+        "database_os": "Linux",
+        "display_name": "Pine",
+        "notes": "",
+        "versus": "go"
+      }
+    }
+  ]
+}

+ 10 - 0
frameworks/Go/pine/pine.dockerfile

@@ -0,0 +1,10 @@
+FROM docker.io/golang:1.23
+
+COPY ./src /pine
+WORKDIR /pine
+
+RUN go mod download
+
+EXPOSE 8080
+
+CMD go run .

+ 5 - 0
frameworks/Go/pine/src/go.mod

@@ -0,0 +1,5 @@
+module pine
+
+go 1.23.0
+
+require github.com/BryanMwangi/pine v1.0.6

+ 2 - 0
frameworks/Go/pine/src/go.sum

@@ -0,0 +1,2 @@
+github.com/BryanMwangi/pine v1.0.6 h1:35JN1FQkStoCikeVQJ2423mO5STLNEPkA/AgnjslAmg=
+github.com/BryanMwangi/pine v1.0.6/go.mod h1:j6+gT+N2HeeJHc9Z60rUOnEmNC+s/Gdmh2e9oB/eScI=

+ 28 - 0
frameworks/Go/pine/src/main.go

@@ -0,0 +1,28 @@
+package main
+
+import (
+	"log"
+
+	"github.com/BryanMwangi/pine"
+)
+
+func plaintextHandler(c *pine.Ctx) error {
+	c.Set("Server", "Pine")
+	return c.SendString("Hello, World!")
+}
+
+func jsonHandler(c *pine.Ctx) error {
+	c.Set("Server", "Pine")
+	return c.JSON(map[string]string{
+		"message": "Hello, World!",
+	})
+}
+
+func main() {
+	app := pine.New()
+	app.Get("/plaintext", plaintextHandler)
+	app.Get("/json", jsonHandler)
+
+	// Start the server on port 3000
+	log.Fatal(app.Start(":8080"))
+}

+ 0 - 8
frameworks/Java/helidon/nima/src/main/java/io/helidon/benchmark/nima/models/DbRepository.java

@@ -1,23 +1,15 @@
 
 
 package io.helidon.benchmark.nima.models;
 package io.helidon.benchmark.nima.models;
 
 
-import java.util.Collections;
 import java.util.List;
 import java.util.List;
 import java.util.concurrent.ThreadLocalRandom;
 import java.util.concurrent.ThreadLocalRandom;
 
 
-import jakarta.json.Json;
-import jakarta.json.JsonBuilderFactory;
-
 public interface DbRepository {
 public interface DbRepository {
 
 
-    JsonBuilderFactory JSON = Json.createBuilderFactory(Collections.emptyMap());
-
     World getWorld(int id);
     World getWorld(int id);
 
 
     List<World> getWorlds(int count);
     List<World> getWorlds(int count);
 
 
-    World updateWorld(World world);
-
     List<World> updateWorlds(int count);
     List<World> updateWorlds(int count);
 
 
     List<Fortune> getFortunes();
     List<Fortune> getFortunes();

+ 0 - 9
frameworks/Java/helidon/nima/src/main/java/io/helidon/benchmark/nima/models/HikariJdbcRepository.java

@@ -80,15 +80,6 @@ public class HikariJdbcRepository implements DbRepository {
         }
         }
     }
     }
 
 
-    @Override
-    public World updateWorld(World world) {
-        try (Connection c = getConnection()) {
-            return updateWorld(world, c);
-        } catch (Exception e) {
-            throw new RuntimeException(e);
-        }
-    }
-
     @Override
     @Override
     public List<World> updateWorlds(int count) {
     public List<World> updateWorlds(int count) {
         try (Connection c = getConnection()) {
         try (Connection c = getConnection()) {

Some files were not shown because too many files changed in this diff