Browse Source

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

jaguililla 11 months ago
parent
commit
2ae467e110
51 changed files with 222 additions and 464 deletions
  1. 5 4
      frameworks/C++/userver/README.md
  2. 0 24
      frameworks/C++/userver/benchmark_config.json
  3. 0 18
      frameworks/C++/userver/config.toml
  4. 0 29
      frameworks/C++/userver/userver-bare.dockerfile
  5. 1 1
      frameworks/C++/userver/userver.dockerfile
  6. 2 17
      frameworks/C++/userver/userver_benchmark/userver_techempower.cpp
  7. 0 3
      frameworks/C++/userver/userver_configs/static_config.yaml
  8. 8 2
      frameworks/Elixir/phoenix/config/prod.exs
  9. 1 1
      frameworks/Elixir/phoenix/mix.exs
  10. 3 3
      frameworks/Elixir/phoenix/mix.lock
  11. 1 1
      frameworks/Java/micronaut/micronaut-data-jdbc.dockerfile
  12. 1 1
      frameworks/Java/micronaut/micronaut-data-mongodb.dockerfile
  13. 1 1
      frameworks/Java/micronaut/micronaut-data-r2dbc.dockerfile
  14. 1 1
      frameworks/Java/micronaut/micronaut-graalvm.dockerfile
  15. 1 1
      frameworks/Java/micronaut/micronaut-jdbc-graalvm.dockerfile
  16. 1 1
      frameworks/Java/micronaut/micronaut-jdbc.dockerfile
  17. 1 1
      frameworks/Java/micronaut/micronaut-r2dbc-graalvm.dockerfile
  18. 1 1
      frameworks/Java/micronaut/micronaut-r2dbc.dockerfile
  19. 1 2
      frameworks/PHP/swoole/10-opcache.ini
  20. 5 3
      frameworks/PHP/swoole/swoole-async-mysql.dockerfile
  21. 5 3
      frameworks/PHP/swoole/swoole-async-postgres.dockerfile
  22. 5 3
      frameworks/PHP/swoole/swoole-sync-mysql.dockerfile
  23. 5 3
      frameworks/PHP/swoole/swoole-sync-postgres.dockerfile
  24. 2 2
      frameworks/Pascal/mormot/setup_and_build.sh
  25. 1 1
      frameworks/Ruby/hanami/app/actions/db/index.rb
  26. 1 1
      frameworks/Ruby/rack/Gemfile.lock
  27. 1 1
      frameworks/Ruby/rage/Gemfile
  28. 1 1
      frameworks/Ruby/rage/rage.dockerfile
  29. 1 1
      frameworks/Ruby/sinatra-sequel/sinatra-sequel-postgres.dockerfile
  30. 3 8
      frameworks/Rust/ntex/Cargo.toml
  31. 11 16
      frameworks/Rust/ntex/src/db.rs
  32. 31 38
      frameworks/Rust/xitca-web/Cargo.lock
  33. 2 2
      frameworks/Rust/xitca-web/Cargo.toml
  34. 16 27
      frameworks/Rust/xitca-web/src/db.rs
  35. 31 18
      frameworks/Rust/xitca-web/src/db_diesel.rs
  36. 10 4
      frameworks/Rust/xitca-web/src/main.rs
  37. 9 75
      frameworks/Rust/xitca-web/src/main_iou.rs
  38. 4 8
      frameworks/Rust/xitca-web/src/ser.rs
  39. 37 13
      frameworks/Rust/xitca-web/src/util.rs
  40. 1 1
      frameworks/Rust/xitca-web/xitca-web-axum.dockerfile
  41. 1 1
      frameworks/Rust/xitca-web/xitca-web-iou.dockerfile
  42. 1 1
      frameworks/Rust/xitca-web/xitca-web-sync.dockerfile
  43. 1 1
      frameworks/Rust/xitca-web/xitca-web-wasm.dockerfile
  44. 1 1
      frameworks/Rust/xitca-web/xitca-web.dockerfile
  45. 1 47
      frameworks/Scala/otavia/benchmark_config.json
  46. 2 2
      frameworks/Scala/otavia/build.sc
  47. 1 35
      frameworks/Scala/otavia/config.toml
  48. 0 16
      frameworks/Scala/otavia/otavia-equalization-offgc.dockerfile
  49. 0 16
      frameworks/Scala/otavia/otavia-offgc.dockerfile
  50. 2 2
      frameworks/Scala/otavia/otavia-overshoot.dockerfile
  51. 1 1
      frameworks/Scala/otavia/otavia.dockerfile

+ 5 - 4
frameworks/C++/userver/README.md

@@ -2,14 +2,11 @@
 
 This is the [userver](https://github.com/userver-framework/userver) portion of a [benchmarking test suite](https://github.com/TechEmpower/FrameworkBenchmarks) comparing a variety of web development platforms.
 
-This benchmarks comes in two configurations: **userver** and **userver-bare**, where both configurations use exactly the same handlers code, but **userver-bare** replaces default http implementation of **userver** with custom one.  
-You see, **userver** being feature-rich framework widely used in production comes with a lot of useful functionality built-in (metrics, dynamic configuring, logging/tracing, congestion control etc...) none of which is of any use in benchmarks; although most of that can be disabled via configs, some parts remain, and these parts aren't free.  
-The aim of **userver-bare** is to explore practical limits of lower-level **userver** functionality when performance is an absolute must, while still being idiomatic userver code.
-
 ### Test Type Implementation Source Code
 
 * [Plaintext](userver_benchmark/controllers/plaintext/handler.cpp)
 * [Json](userver_benchmark/controllers/json/handler.cpp)
+* [Fortunes](userver_benchmark/controllers/fortunes/handler.cpp)
 * [Single Database Query](userver_benchmark/controllers/single_query/handler.cpp)
 * [Multiple Database Queries](userver_benchmark/controllers/multiple_queries/handler.cpp)
 * [Database Updates](userver_benchmark/controllers/updates/handler.cpp)
@@ -24,6 +21,10 @@ http://localhost:8080/plaintext
 
 http://localhost:8080/json
 
+### Fortunes
+
+http://localhost:8080/fortunes
+
 ### Single Database Query
 
 http://localhost:8080/db

+ 0 - 24
frameworks/C++/userver/benchmark_config.json

@@ -25,30 +25,6 @@
         "display_name": "userver",
         "notes": "",
         "versus": "None"
-      },
-      "bare": {
-        "json_url": "/json",
-        "plaintext_url": "/plaintext",
-        "db_url": "/db",
-        "query_url": "/queries?queries=",
-        "update_url": "/updates?queries=",
-        "cached_query_url": "/cached-queries?count=",
-	"fortune_url": "/fortunes",
-        "port": 8081,
-        "approach": "Realistic",
-        "classification": "Micro",
-        "database": "postgres",
-        "framework": "userver",
-        "language": "C++",
-        "flavor": "None",
-        "orm": "Micro",
-        "platform": "None",
-        "webserver": "None",
-        "os": "Linux",
-        "database_os": "Linux",
-        "display_name": "userver[bare]",
-        "notes": "",
-        "versus": "None"
       }
     }
   ]

+ 0 - 18
frameworks/C++/userver/config.toml

@@ -18,21 +18,3 @@ orm = "Micro"
 platform = "None"
 webserver = "None"
 versus = "None"
-
-[bare]
-urls.plaintext = "/plaintext"
-urls.json = "/json"
-urls.db = "/db"
-urls.query = "/queries?queries="
-urls.update = "/updates?queries="
-urls.cached_query = "/cached-queries?count="
-urls.fortune = "/fortunes"
-approach = "Realistic"
-classification = "Micro"
-database = "Postgres"
-database_os = "Linux"
-os = "Linux"
-orm = "Micro"
-platform = "None"
-webserver = "None"
-versus = "None"

+ 0 - 29
frameworks/C++/userver/userver-bare.dockerfile

@@ -1,29 +0,0 @@
-FROM ghcr.io/userver-framework/ubuntu-22.04-userver-pg AS builder
-
-RUN apt update && \
-    apt install -y lsb-release wget software-properties-common gnupg && \
-        wget https://apt.llvm.org/llvm.sh && chmod +x llvm.sh && ./llvm.sh 16
-
-WORKDIR /src
-RUN git clone https://github.com/userver-framework/userver.git && \
-    cd userver && git checkout bdd5e1e03921ff378b062f86a189c3cfa3d66332
-
-COPY userver_benchmark/ ./
-RUN mkdir build && cd build && \
-    cmake -DUSERVER_IS_THE_ROOT_PROJECT=0 -DUSERVER_FEATURE_CRYPTOPP_BLAKE2=0 \
-          -DUSERVER_FEATURE_UTEST=0 \
-          -DUSERVER_FEATURE_POSTGRESQL=1 \
-          -DUSERVER_FEATURE_ERASE_LOG_WITH_LEVEL=warning \
-          -DCMAKE_BUILD_TYPE=Release -DCMAKE_CXX_FLAGS="-march=native -flto=thin" -DCMAKE_C_FLAGS="-march=native -flto=thin" \
-          -DCMAKE_CXX_COMPILER=clang++-16 -DCMAKE_C_COMPILER=clang-16 -DUSERVER_USE_LD=lld-16 \
-          -DUSERVER_LTO=0 .. && \
-    make -j $(nproc)
-
-FROM builder AS runner
-WORKDIR /app
-COPY userver_configs/* ./
-COPY --from=builder /src/build/userver_techempower ./
-
-EXPOSE 8081
-CMD ./userver_techempower -c ./static_config.yaml
-

+ 1 - 1
frameworks/C++/userver/userver.dockerfile

@@ -14,7 +14,7 @@ RUN mkdir build && cd build && \
           -DUSERVER_FEATURE_UTEST=0 \
           -DUSERVER_FEATURE_POSTGRESQL=1 \
           -DUSERVER_FEATURE_ERASE_LOG_WITH_LEVEL=warning \
-          -DCMAKE_BUILD_TYPE=Release -DCMAKE_CXX_FLAGS="-march=native -flto=thin" -DCMAKE_C_FLAGS="-march=native -flto=thin" \
+          -DCMAKE_BUILD_TYPE=Release -DCMAKE_CXX_FLAGS="-march=native" -DCMAKE_C_FLAGS="-march=native" \
           -DCMAKE_CXX_COMPILER=clang++-16 -DCMAKE_C_COMPILER=clang-16 -DUSERVER_USE_LD=lld-16 \
           -DUSERVER_LTO=0 .. && \
     make -j $(nproc)

+ 2 - 17
frameworks/C++/userver/userver_benchmark/userver_techempower.cpp

@@ -46,20 +46,6 @@ class NoopTracingManager final
       userver::server::http::HttpResponse&) const final {}
 };
 
-class MinimalMiddlewarePipelineBuilder final
-    : public userver::server::middlewares::PipelineBuilder {
- public:
-  static constexpr std::string_view kName{
-      "minimal-middleware-pipeline-builder"};
-  using userver::server::middlewares::PipelineBuilder::PipelineBuilder;
-
- private:
-  userver::server::middlewares::MiddlewaresList BuildPipeline(
-      userver::server::middlewares::MiddlewaresList) const override {
-    return {"userver-unknown-exceptions-handling-middleware"};
-  }
-};
-
 int Main(int argc, char* argv[]) {
   auto component_list =
       userver::components::MinimalServerComponentList()
@@ -78,10 +64,9 @@ int Main(int argc, char* argv[]) {
           .Append<cached_queries::WorldCacheComponent>()  // cache component
           .Append<cached_queries::Handler>()
           .Append<fortunes::Handler>()
-          // tracing and metrics tweaks
+          // tracing tweaks
           .Append<NoopTracingManager>()
-          .Append<MinimalMiddlewarePipelineBuilder>()
-          // bare
+          // bare (not used in the benchmark currently)
           .Append<bare::SimpleRouter>()
           .Append<bare::SimpleServer>();
 

+ 0 - 3
frameworks/C++/userver/userver_configs/static_config.yaml

@@ -13,7 +13,6 @@ components_manager:
             thread_name: main-worker    # OS will show the threads of this task processor with 'main-worker' prefix.
             worker_threads: 48
             guess-cpu-limit: true
-            task-processor-queue: work-stealing-task-queue
 
         fs-task-processor:              # Make a separate task processor for filesystem bound tasks.
             thread_name: fs-worker
@@ -29,7 +28,6 @@ components_manager:
                 handler-defaults:
                     set_tracing_headers: false
             server-name: us
-            middleware-pipeline-builder: minimal-middleware-pipeline-builder
         simple-router:
         simple-server:
             port: 8081
@@ -63,7 +61,6 @@ components_manager:
         noop-tracing-manager:
         tracing-manager-locator:
             component-name: noop-tracing-manager
-        minimal-middleware-pipeline-builder:
 
         plaintext-handler:
             path: /plaintext

+ 8 - 2
frameworks/Elixir/phoenix/config/prod.exs

@@ -2,8 +2,14 @@ import Config
 
 config :hello, HelloWeb.Endpoint,
   adapter: Bandit.PhoenixAdapter,
-  http: [port: 8080, ip: {0, 0, 0, 0}],
-  http_options: [log_protocol_errors: false],
+  http: [
+    port: 8080,
+    ip: {0, 0, 0, 0},
+    http_options: [
+      compress: false,
+      log_protocol_errors: false
+    ]
+  ],
   compress: false,
   check_origin: false,
   debug_errors: false,

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

@@ -29,7 +29,7 @@ defmodule Hello.Mixfile do
   # Type `mix help deps` for examples and options
   defp deps do
     [
-      {:bandit, "~> 1.0.0"},
+      {:bandit, "1.5.7"},
       {:gettext, "~> 0.20"},
       {:ecto_sql, "~> 3.10"},
       {:jason, "~> 1.2"},

+ 3 - 3
frameworks/Elixir/phoenix/mix.lock

@@ -1,5 +1,5 @@
 %{
-  "bandit": {:hex, :bandit, "1.0.0", "2bd87bbf713d0eed0090f2fa162cd1676198122e6c2b68a201c706e354a6d5e5", [:mix], [{:hpax, "~> 0.1.1", [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", "32acf6ac030fee1f99fd9c3fcf81671911ae8637e0a61c98111861b466efafdb"},
+  "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"},
@@ -10,7 +10,7 @@
   "ecto_sql": {:hex, :ecto_sql, "3.11.3", "4eb7348ff8101fbc4e6bbc5a4404a24fecbe73a3372d16569526b0cf34ebc195", [:mix], [{:db_connection, "~> 2.4.1 or ~> 2.5", [hex: :db_connection, repo: "hexpm", optional: false]}, {:ecto, "~> 3.11.0", [hex: :ecto, repo: "hexpm", optional: false]}, {:myxql, "~> 0.6", [hex: :myxql, repo: "hexpm", optional: true]}, {:postgrex, "~> 0.16 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", "e5f36e3d736b99c7fee3e631333b8394ade4bafe9d96d35669fca2d81c2be928"},
   "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, "0.1.2", "09a75600d9d8bbd064cdd741f21fc06fc1f4cf3d0fcc335e5aa19be1a7235c84", [:mix], [], "hexpm", "2c87843d5a23f5f16748ebe77969880e29809580efdaccd615cd3bed628a8c13"},
+  "hpax": {:hex, :hpax, "1.0.0", "28dcf54509fe2152a3d040e4e3df5b265dcb6cb532029ecbacf4ce52caea3fd2", [:mix], [], "hexpm", "7f1314731d711e2ca5fdc7fd361296593fc2542570b3105595bb0bc6d0fad601"},
   "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"},
   "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"},
@@ -25,7 +25,7 @@
   "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"},
-  "telemetry": {:hex, :telemetry, "1.2.1", "68fdfe8d8f05a8428483a97d7aab2f268aaff24b49e0f599faa091f1d4e7f61c", [:rebar3], [], "hexpm", "dad9ce9d8effc621708f99eac538ef1cbe05d6a874dd741de2e689c47feafed5"},
+  "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"},
   "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"},

+ 1 - 1
frameworks/Java/micronaut/micronaut-data-jdbc.dockerfile

@@ -3,7 +3,7 @@ COPY --chown=gradle:gradle . /home/gradle/src
 WORKDIR /home/gradle/src
 RUN gradle micronaut-data-jdbc:build -x test -x internalStartTestResourcesService --no-daemon
 
-FROM openjdk:21
+FROM openjdk:23
 WORKDIR /micronaut
 COPY --from=build /home/gradle/src/micronaut-data-jdbc/build/libs/micronaut-data-jdbc-all.jar micronaut.jar
 COPY run_benchmark.sh run_benchmark.sh

+ 1 - 1
frameworks/Java/micronaut/micronaut-data-mongodb.dockerfile

@@ -3,7 +3,7 @@ COPY --chown=gradle:gradle . /home/gradle/src
 WORKDIR /home/gradle/src
 RUN gradle micronaut-data-mongodb:build -x test -x internalStartTestResourcesService --no-daemon
 
-FROM openjdk:21
+FROM openjdk:23
 WORKDIR /micronaut
 COPY --from=build /home/gradle/src/micronaut-data-mongodb/build/libs/micronaut-data-mongodb-all.jar micronaut.jar
 COPY run_benchmark.sh run_benchmark.sh

+ 1 - 1
frameworks/Java/micronaut/micronaut-data-r2dbc.dockerfile

@@ -3,7 +3,7 @@ COPY --chown=gradle:gradle . /home/gradle/src
 WORKDIR /home/gradle/src
 RUN gradle micronaut-data-r2dbc:build -x test -x internalStartTestResourcesService --no-daemon
 
-FROM openjdk:21
+FROM openjdk:23
 WORKDIR /micronaut
 COPY --from=build /home/gradle/src/micronaut-data-r2dbc/build/libs/micronaut-data-r2dbc-all.jar micronaut.jar
 COPY run_benchmark.sh run_benchmark.sh

+ 1 - 1
frameworks/Java/micronaut/micronaut-graalvm.dockerfile

@@ -1,4 +1,4 @@
-FROM container-registry.oracle.com/graalvm/native-image:22
+FROM container-registry.oracle.com/graalvm/native-image:23
 RUN microdnf install findutils # Gradle 8.7 requires xargs
 COPY . /home/gradle/src
 WORKDIR /home/gradle/src

+ 1 - 1
frameworks/Java/micronaut/micronaut-jdbc-graalvm.dockerfile

@@ -1,4 +1,4 @@
-FROM container-registry.oracle.com/graalvm/native-image:22
+FROM container-registry.oracle.com/graalvm/native-image:23
 RUN microdnf install findutils # Gradle 8.7 requires xargs
 COPY . /home/gradle/src
 WORKDIR /home/gradle/src

+ 1 - 1
frameworks/Java/micronaut/micronaut-jdbc.dockerfile

@@ -3,7 +3,7 @@ COPY --chown=gradle:gradle . /home/gradle/src
 WORKDIR /home/gradle/src
 RUN gradle micronaut-jdbc:build -x test -x internalStartTestResourcesService --no-daemon
 
-FROM openjdk:21
+FROM openjdk:23
 WORKDIR /micronaut
 COPY --from=build /home/gradle/src/micronaut-jdbc/build/libs/micronaut-jdbc-all.jar micronaut.jar
 COPY run_benchmark.sh run_benchmark.sh

+ 1 - 1
frameworks/Java/micronaut/micronaut-r2dbc-graalvm.dockerfile

@@ -1,4 +1,4 @@
-FROM container-registry.oracle.com/graalvm/native-image:22
+FROM container-registry.oracle.com/graalvm/native-image:23
 RUN microdnf install findutils # Gradle 8.7 requires xargs
 COPY . /home/gradle/src
 WORKDIR /home/gradle/src

+ 1 - 1
frameworks/Java/micronaut/micronaut-r2dbc.dockerfile

@@ -3,7 +3,7 @@ COPY --chown=gradle:gradle . /home/gradle/src
 WORKDIR /home/gradle/src
 RUN gradle micronaut-r2dbc:build -x test -x internalStartTestResourcesService --no-daemon
 
-FROM openjdk:21
+FROM openjdk:23
 WORKDIR /micronaut
 COPY --from=build /home/gradle/src/micronaut-r2dbc/build/libs/micronaut-r2dbc-all.jar micronaut.jar
 COPY run_benchmark.sh run_benchmark.sh

+ 1 - 2
frameworks/PHP/swoole/php.ini → frameworks/PHP/swoole/10-opcache.ini

@@ -2,9 +2,8 @@ zend_extension=opcache.so
 opcache.enable=1
 opcache.enable_cli=1
 opcache.validate_timestamps=0
+opcache.save_comments=0
 opcache.enable_file_override=1
 opcache.huge_code_pages=1
-memory_limit=1024M
-
 opcache.jit_buffer_size=128M
 opcache.jit=1225

+ 5 - 3
frameworks/PHP/swoole/swoole-async-mysql.dockerfile

@@ -18,15 +18,17 @@ RUN apt update -yqq > /dev/null \
     && ./configure > /dev/null \
     && make -j8 > /dev/null \
     && make install > /dev/null \
-    && echo "extension=swoole.so" > /etc/php/8.3/cli/conf.d/50-swoole.ini
+    && echo "extension=swoole.so" > /etc/php/8.3/cli/conf.d/50-swoole.ini \
+    && echo "memory_limit=1024M" >> /etc/php/8.3/cli/php.ini \
+    && php -m
 
 WORKDIR /swoole
 
 ADD ./swoole-server.php /swoole
-ADD ./php.ini /swoole
+ADD 10-opcache.ini /swoole
 ADD ./database.php /swoole
 
-RUN cat /swoole/php.ini >> /etc/php/8.3/cli/php.ini
+COPY 10-opcache.ini /etc/php/8.3/cli/conf.d/10-opcache.ini
 
 EXPOSE 8080
 CMD php /swoole/swoole-server.php

+ 5 - 3
frameworks/PHP/swoole/swoole-async-postgres.dockerfile

@@ -18,15 +18,17 @@ RUN apt update -yqq > /dev/null \
     && ./configure --enable-swoole-pgsql > /dev/null \
     && make -j8 > /dev/null \
     && make install > /dev/null \
-    && echo "extension=swoole.so" > /etc/php/8.3/cli/conf.d/50-swoole.ini
+    && echo "extension=swoole.so" > /etc/php/8.3/cli/conf.d/50-swoole.ini \
+    && echo "memory_limit=1024M" >> /etc/php/8.3/cli/php.ini \
+    && php -m
 
 WORKDIR /swoole
 
 ADD ./swoole-server.php /swoole
-ADD ./php.ini /swoole
+ADD 10-opcache.ini /swoole
 ADD ./database.php /swoole
 
-RUN cat /swoole/php.ini >> /etc/php/8.3/cli/php.ini
+COPY 10-opcache.ini /etc/php/8.3/cli/conf.d/10-opcache.ini
 
 EXPOSE 8080
 CMD php /swoole/swoole-server.php

+ 5 - 3
frameworks/PHP/swoole/swoole-sync-mysql.dockerfile

@@ -18,15 +18,17 @@ RUN apt update -yqq > /dev/null \
     && ./configure > /dev/null \
     && make -j8 > /dev/null \
     && make install > /dev/null \
-    && echo "extension=swoole.so" > /etc/php/8.3/cli/conf.d/50-swoole.ini
+    && echo "extension=swoole.so" > /etc/php/8.3/cli/conf.d/50-swoole.ini \
+    && echo "memory_limit=1024M" >> /etc/php/8.3/cli/php.ini \
+    && php -m
 
 WORKDIR /swoole
 
 ADD ./swoole-server.php /swoole
-ADD ./php.ini /swoole
+ADD 10-opcache.ini /swoole
 ADD ./database.php /swoole
 
-RUN cat /swoole/php.ini >> /etc/php/8.3/cli/php.ini
+COPY 10-opcache.ini /etc/php/8.3/cli/conf.d/10-opcache.ini
 
 EXPOSE 8080
 CMD php /swoole/swoole-server.php

+ 5 - 3
frameworks/PHP/swoole/swoole-sync-postgres.dockerfile

@@ -18,15 +18,17 @@ RUN apt update -yqq > /dev/null \
     && ./configure > /dev/null \
     && make -j8 > /dev/null \
     && make install > /dev/null \
-    && echo "extension=swoole.so" > /etc/php/8.3/cli/conf.d/50-swoole.ini
+    && echo "extension=swoole.so" > /etc/php/8.3/cli/conf.d/50-swoole.ini \
+    && echo "memory_limit=1024M" >> /etc/php/8.3/cli/php.ini \
+    && php -m
 
 WORKDIR /swoole
 
 ADD ./swoole-server.php /swoole
-ADD ./php.ini /swoole
+ADD 10-opcache.ini /swoole
 ADD ./database.php /swoole
 
-RUN cat /swoole/php.ini >> /etc/php/8.3/cli/php.ini
+COPY 10-opcache.ini /etc/php/8.3/cli/conf.d/10-opcache.ini
 
 EXPOSE 8080
 CMD php /swoole/swoole-server.php

+ 2 - 2
frameworks/Pascal/mormot/setup_and_build.sh

@@ -35,7 +35,7 @@ echo "Download statics from $URL ..."
 wget -qO- "$URL" | tar -xz -C ./libs/mORMot/static
 
 # uncomment for fixed commit URL
-URL=https://github.com/synopse/mORMot2/tarball/a0dda41833c3d32531080d1eeb5a1627540d62e9
+URL=https://github.com/synopse/mORMot2/tarball/6dc09ceca456931384857b383ed61b63f11f3be7
 #URL="https://api.github.com/repos/synopse/mORMot2/tarball/$USED_TAG"
 echo "Download and unpacking mORMot sources from $URL ..."
 wget -qO- "$URL" | tar -xz -C ./libs/mORMot  --strip-components=1
@@ -80,7 +80,7 @@ fpc -MDelphi -Sci -Ci -O3 -g -gl -gw2 -Xg -k'-rpath=$ORIGIN' -k-L$BIN \
   -Fu"$MSRC/core" -Fu"$MSRC/db" -Fu"$MSRC/rest" -Fu"$MSRC/crypt" \
     -Fu"$MSRC/app" -Fu"$MSRC/net" -Fu"$MSRC/lib" -Fu"$MSRC/orm" -Fu"$MSRC/soa" \
   -FU"$BIN/fpc-$ARCH_TG/.dcu" -FE"$BIN/fpc-$ARCH_TG" -o"$BIN/fpc-$ARCH_TG/$dest_fn" \
-  -dFPC_LIBCMM -dFPC_LIBCMM_NOMSIZE \
+  -dFPC_X64MM -dFPCMM_SERVER \
   -B -Se1 "./src/raw.pas" | grep "[Warning|Error|Fatal]:"
 
 script_successful

+ 1 - 1
frameworks/Ruby/hanami/app/actions/db/index.rb

@@ -2,7 +2,7 @@
 
 module HelloWorld
   module Actions
-    module Db
+    module DB
       class Index < HelloWorld::Action
         QUERY_RANGE = 1..10_000    # range of IDs in the Fortune DB
         include Deps["persistence.rom"]

+ 1 - 1
frameworks/Ruby/rack/Gemfile.lock

@@ -77,7 +77,7 @@ GEM
     protocol-rack (0.6.0)
       protocol-http (~> 0.23)
       rack (>= 1.0)
-    puma (6.4.2)
+    puma (6.4.3)
       nio4r (~> 2.0)
     racc (1.8.0)
     rack (3.1.6)

+ 1 - 1
frameworks/Ruby/rage/Gemfile

@@ -3,7 +3,7 @@ source "https://rubygems.org"
 gem "rage-rb", "~> 1.3"
 
 gem "pg", "~> 1.0"
-gem "activerecord", "~> 7.0.0", require: "active_record"
+gem "activerecord", "~> 7.2.0", require: "active_record"
 
 # Build JSON APIs with ease
 # gem "alba"

+ 1 - 1
frameworks/Ruby/rage/rage.dockerfile

@@ -1,4 +1,4 @@
-FROM ruby:3.3
+FROM ruby:3.4-rc
 
 EXPOSE 8080
 WORKDIR /rage

+ 1 - 1
frameworks/Ruby/sinatra-sequel/sinatra-sequel-postgres.dockerfile

@@ -1,4 +1,4 @@
-FROM ruby:3.3
+FROM ruby:3.4-rc
 
 ENV RUBY_YJIT_ENABLE=1
 

+ 3 - 8
frameworks/Rust/ntex/Cargo.toml

@@ -34,10 +34,11 @@ default = []
 tokio = ["ntex/tokio"]
 
 # compio runtime
-compio = ["ntex/compio"]
+compio = ["ntex/compio", ]
 
 [dependencies]
 ntex = "2.4"
+ntex-compio = "0.1.2"
 ntex-bytes = { version = "0.1.21", features=["simd"] }
 mimalloc = { version = "0.1.25", default-features = false }
 snmalloc-rs = { version = "0.3.3", features = ["native-cpu"] }
@@ -52,6 +53,7 @@ futures = "0.3"
 serde = { version = "1.0", features = ["derive"] }
 serde_json = "1.0"
 log = { version = "0.4", features = ["release_max_level_off"] }
+compio-driver = { version = "0.4", features = ["io-uring", "io-uring-socket"]}
 tok_io = {version = "1", package = "tokio" }
 tokio-postgres = { git="https://github.com/fafhrd91/postgres.git", branch="ntex-2" }
 
@@ -63,10 +65,3 @@ lto = "thin"
 debug = false
 incremental = false
 overflow-checks = false
-
-[patch.crates-io]
-ntex = { git = "https://github.com/ntex-rs/ntex.git", branch = "compio" }
-ntex-io = { git = "https://github.com/ntex-rs/ntex.git", branch = "compio" }
-ntex-rt = { git = "https://github.com/ntex-rs/ntex.git", branch = "compio" }
-ntex-net = { git = "https://github.com/ntex-rs/ntex.git", branch = "compio" }
-ntex-compio = { git = "https://github.com/ntex-rs/ntex.git", branch = "compio" }

+ 11 - 16
frameworks/Rust/ntex/src/db.rs

@@ -68,7 +68,7 @@ impl PgConnection {
             world,
             updates,
             rng: WyRand::new(),
-            buf: RefCell::new(BytesMut::with_capacity(65535)),
+            buf: RefCell::new(BytesMut::with_capacity(10 * 1024 * 1024)),
         }
     }
 }
@@ -80,7 +80,7 @@ impl PgConnection {
         let row = self.cl.query_one(&self.world, &[&random_id]).await.unwrap();
 
         let mut body = self.buf.borrow_mut();
-        utils::reserve(&mut body, 8 * 1024);
+        utils::reserve(&mut body, 1024);
         World {
             id: row.get(0),
             randomnumber: row.get(1),
@@ -107,7 +107,7 @@ impl PgConnection {
         }
 
         let mut body = self.buf.borrow_mut();
-        utils::reserve(&mut body, 8 * 1024);
+        utils::reserve(&mut body, 2 * 1024);
         body.put_u8(b'[');
         worlds.iter().for_each(|w| {
             w.to_bytes_mut(&mut *body);
@@ -119,7 +119,7 @@ impl PgConnection {
     }
 
     pub async fn update(&self, num: usize) -> Bytes {
-        let mut rng = self.rng.clone();
+        let mut rng = nanorand::tls_rng();
         let mut queries = SmallVec::<[_; 32]>::new();
         (0..num).for_each(|_| {
             let w_id = (rng.generate::<u32>() % 10_000 + 1) as i32;
@@ -146,7 +146,7 @@ impl PgConnection {
         let _ = self.cl.query(&self.updates[num - 1], &params).await;
 
         let mut body = self.buf.borrow_mut();
-        utils::reserve(&mut body, 8 * 1024);
+        utils::reserve(&mut body, 2 * 1024);
         body.put_u8(b'[');
         worlds.iter().for_each(|w| {
             w.to_bytes_mut(&mut *body);
@@ -158,25 +158,20 @@ impl PgConnection {
     }
 
     pub async fn tell_fortune(&self) -> Bytes {
-        let fut = self.cl.query_raw(&self.fortune, &[]);
+        let rows = self.cl.query_raw(&self.fortune, &[]).await.unwrap();
 
-        let rows = fut.await.unwrap();
         let mut fortunes: SmallVec<[_; 32]> = smallvec::smallvec![Fortune {
             id: 0,
             message: Cow::Borrowed("Additional fortune added at request time."),
         }];
-
-        for row in rows {
-            fortunes.push(Fortune {
-                id: row.get(0),
-                message: Cow::Owned(row.get(1)),
-            });
-        }
-
+        fortunes.extend(rows.iter().map(|row| Fortune {
+            id: row.get(0),
+            message: Cow::Owned(row.get(1)),
+        }));
         fortunes.sort_by(|it, next| it.message.cmp(&next.message));
 
         let mut body = std::mem::replace(&mut *self.buf.borrow_mut(), BytesMut::new());
-        utils::reserve(&mut body, 8 * 1024);
+        utils::reserve(&mut body, 4 * 1024);
         ywrite_html!(body, "{{> fortune }}");
         let result = body.split().freeze();
         let _ = std::mem::replace(&mut *self.buf.borrow_mut(), body);

+ 31 - 38
frameworks/Rust/xitca-web/Cargo.lock

@@ -4,18 +4,18 @@ version = 3
 
 [[package]]
 name = "addr2line"
-version = "0.22.0"
+version = "0.24.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6e4503c46a5c0c7844e948c9a4d6acd9f50cccb4de1c48eb9e291ea17470c678"
+checksum = "f5fb1d8e4442bd405fdfd1dacb42792696b0cf9cb15882e5d097b742a676d375"
 dependencies = [
  "gimli",
 ]
 
 [[package]]
-name = "adler"
-version = "1.0.2"
+name = "adler2"
+version = "2.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
+checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627"
 
 [[package]]
 name = "async-trait"
@@ -95,17 +95,17 @@ dependencies = [
 
 [[package]]
 name = "backtrace"
-version = "0.3.73"
+version = "0.3.74"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5cc23269a4f8976d0a4d2e7109211a419fe30e8d88d677cd60b6bc79c5732e0a"
+checksum = "8d82cb332cdfaed17ae235a638438ac4d4839913cc2af585c3c6746e8f8bee1a"
 dependencies = [
  "addr2line",
- "cc",
  "cfg-if",
  "libc",
  "miniz_oxide",
  "object",
  "rustc-demangle",
+ "windows-targets",
 ]
 
 [[package]]
@@ -149,9 +149,9 @@ checksum = "8318a53db07bb3f8dca91a600466bdb3f2eaadeedfdbcf02e1accbad9271ba50"
 
 [[package]]
 name = "cc"
-version = "1.1.16"
+version = "1.1.18"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e9d013ecb737093c0e86b151a7b837993cf9ec6c502946cfb44bedc392421e0b"
+checksum = "b62ac837cdb5cb22e10a256099b4fc502b1dfe560cb282963a974d7abd80e476"
 dependencies = [
  "shlex",
 ]
@@ -164,9 +164,9 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
 
 [[package]]
 name = "cpufeatures"
-version = "0.2.13"
+version = "0.2.14"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "51e852e6dc9a5bed1fae92dd2375037bf2b768725bf3be87811edee3249d09ad"
+checksum = "608697df725056feaccfa42cffdaeeec3fccc4ffc38358ecd19b243e716a78e0"
 dependencies = [
  "libc",
 ]
@@ -364,9 +364,9 @@ dependencies = [
 
 [[package]]
 name = "gimli"
-version = "0.29.0"
+version = "0.31.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "40ecd4077b5ae9fd2e9e169b102c6c330d0605168eb0e8bf79952b256dbefffd"
+checksum = "32085ea23f3234fc7846555e85283ba4de91e21016dc0455a16286d87a292d64"
 
 [[package]]
 name = "heck"
@@ -554,11 +554,11 @@ checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a"
 
 [[package]]
 name = "miniz_oxide"
-version = "0.7.4"
+version = "0.8.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b8a240ddb74feaf34a79a7add65a741f3167852fba007066dcac1ca548d89c08"
+checksum = "e2d80299ef12ff69b16a84bb182e3b9df68b5a91574d3d4fa6e41b65deec4df1"
 dependencies = [
- "adler",
+ "adler2",
 ]
 
 [[package]]
@@ -572,12 +572,6 @@ dependencies = [
  "windows-sys 0.52.0",
 ]
 
-[[package]]
-name = "nanorand"
-version = "0.7.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6a51313c5820b0b02bd422f4b44776fbf47961755c74ce64afc73bfad10226c3"
-
 [[package]]
 name = "num-traits"
 version = "0.2.19"
@@ -721,9 +715,9 @@ dependencies = [
 
 [[package]]
 name = "pq-sys"
-version = "0.6.1"
+version = "0.6.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a24ff9e4cf6945c988f0db7005d87747bf72864965c3529d259ad155ac41d584"
+checksum = "a92c30dd81695321846d4dfe348da67b1752ebb61cd1549d203a7b57e323c435"
 dependencies = [
  "vcpkg",
 ]
@@ -789,9 +783,9 @@ dependencies = [
 
 [[package]]
 name = "redox_syscall"
-version = "0.5.3"
+version = "0.5.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2a908a6e00f1fdd0dfd9c0eb08ce85126f6d8bbda50017e74bc4a4b7d4a926a4"
+checksum = "0884ad60e090bf1345b93da0a5de8923c93884cd03f40dfcfddd3b4bee661853"
 dependencies = [
  "bitflags 2.6.0",
 ]
@@ -867,18 +861,18 @@ checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
 
 [[package]]
 name = "serde"
-version = "1.0.209"
+version = "1.0.210"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "99fce0ffe7310761ca6bf9faf5115afbc19688edd00171d81b1bb1b116c63e09"
+checksum = "c8e3592472072e6e22e0a54d5904d9febf8508f65fb8552499a1abc7d1078c3a"
 dependencies = [
  "serde_derive",
 ]
 
 [[package]]
 name = "serde_derive"
-version = "1.0.209"
+version = "1.0.210"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a5831b979fd7b5439637af1752d535ff49f4860c0f341d1baeb6faf0f4242170"
+checksum = "243902eda00fad750862fc144cea25caca5e20d615af0a81bee94ca738f1df1f"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -1155,9 +1149,9 @@ checksum = "08f95100a766bf4f8f28f90d77e0a5461bbdb219042e7679bebe79004fed8d75"
 
 [[package]]
 name = "unicode-ident"
-version = "1.0.12"
+version = "1.0.13"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
+checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe"
 
 [[package]]
 name = "unicode-normalization"
@@ -1330,9 +1324,9 @@ dependencies = [
 
 [[package]]
 name = "xitca-io"
-version = "0.4.0"
+version = "0.4.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "376a4849eef1f3475a6b7a5c474dac278c320a28f6e2abc07be57048b35cc5df"
+checksum = "19b91b7a5ff9e3bed167b7e3bcc7b4462d2cb16d05e3ae913dbc384e463fdd7f"
 dependencies = [
  "bytes",
  "tokio",
@@ -1343,7 +1337,7 @@ dependencies = [
 [[package]]
 name = "xitca-postgres"
 version = "0.1.0"
-source = "git+https://github.com/HFQR/xitca-web.git?rev=9835c0b#9835c0b79ebd77f01b74e3ccb1c9893f022db9f3"
+source = "git+https://github.com/HFQR/xitca-web.git?rev=0cda225#0cda2254f98b40f21bc3170dd8983f16444f0bd0"
 dependencies = [
  "fallible-iterator",
  "percent-encoding",
@@ -1353,7 +1347,6 @@ dependencies = [
  "tokio",
  "tracing",
  "xitca-io",
- "xitca-service",
  "xitca-unsafe-collection",
 ]
 
@@ -1406,7 +1399,7 @@ dependencies = [
  "futures-core",
  "http-body",
  "mimalloc",
- "nanorand",
+ "rand",
  "sailfish",
  "serde",
  "serde_json",

+ 2 - 2
frameworks/Rust/xitca-web/Cargo.toml

@@ -85,7 +85,7 @@ mimalloc = { version = "0.1", default-features = false, optional = true }
 # stuff can not be used or not needed in wasi target
 [target.'cfg(not(target_family = "wasm"))'.dependencies]
 futures-core = { version = "0.3", default-features = false }
-nanorand = { version = "0.7", default-features = false, features = ["tls"] }
+rand = { version = "0.8", features = ["small_rng"] }
 tokio = "1"
 
 [profile.release]
@@ -95,5 +95,5 @@ codegen-units = 1
 panic = "abort"
 
 [patch.crates-io]
-xitca-postgres = { git = "https://github.com/HFQR/xitca-web.git", rev = "9835c0b" }
+xitca-postgres = { git = "https://github.com/HFQR/xitca-web.git", rev = "0cda225" }
 mio = { git = "https://github.com/fakeshadow/mio", rev = "9bae6012b7ecfc6083350785f71a5e8265358178" }

+ 16 - 27
frameworks/Rust/xitca-web/src/db.rs

@@ -1,11 +1,12 @@
-use std::fmt::Write;
+// clippy is dumb and have no idea what should be lazy or not
+#![allow(clippy::unnecessary_lazy_evaluations)]
 
 use xitca_io::bytes::BytesMut;
-use xitca_postgres::{pipeline::Pipeline, AsyncLendingIterator, Pool, Type};
+use xitca_postgres::{pipeline::Pipeline, pool::Pool, AsyncLendingIterator, Type};
 
 use super::{
     ser::{Fortune, Fortunes, World},
-    util::{HandleResult, Rand, DB_URL},
+    util::{bulk_update_gen, HandleResult, Rand, DB_URL},
 };
 
 pub struct Client {
@@ -28,19 +29,14 @@ const WORLD_SQL: &str = "SELECT * FROM world WHERE id=$1";
 const WORLD_SQL_TYPES: &[Type] = &[Type::INT4];
 
 fn update_query(num: usize) -> Box<str> {
-    const PREFIX: &str = "UPDATE world SET randomNumber = w.r FROM (VALUES ";
-    const SUFFIX: &str = ") AS w (i,r) WHERE world.id = w.i";
-
-    let (_, mut query) = (1..=num).fold((1, String::from(PREFIX)), |(idx, mut query), _| {
-        write!(query, "(${}::int,${}::int),", idx, idx + 1).unwrap();
-        (idx + 2, query)
-    });
-
-    query.pop();
-
-    query.push_str(SUFFIX);
-
-    query.into_boxed_str()
+    bulk_update_gen(|query| {
+        use std::fmt::Write;
+        (1..=num).fold((1, query), |(idx, query), _| {
+            write!(query, "(${}::int,${}::int),", idx, idx + 1).unwrap();
+            (idx + 2, query)
+        });
+    })
+    .into_boxed_str()
 }
 
 pub async fn create() -> HandleResult<Client> {
@@ -50,14 +46,7 @@ pub async fn create() -> HandleResult<Client> {
 
     let updates = core::iter::once(Box::from(""))
         .chain((1..=500).map(update_query))
-        .collect::<Box<[Box<str>]>>();
-
-    {
-        let mut conn = pool.get().await?;
-        for update in updates.iter().skip(1) {
-            conn.prepare(update, &[]).await?;
-        }
-    }
+        .collect();
 
     Ok(Client {
         pool,
@@ -120,7 +109,7 @@ impl Client {
 
         let mut conn = self.pool.get().await?;
         let world_stmt = conn.prepare(WORLD_SQL, WORLD_SQL_TYPES).await?;
-        let update_stmt = conn.prepare(&update, &[]).await?;
+        let update_stmt = conn.prepare(update, &[]).await?;
 
         let mut params = Vec::with_capacity(len);
 
@@ -169,8 +158,8 @@ impl Client {
     }
 }
 
-fn sort_update_params(params: &Vec<[i32; 2]>) -> impl ExactSizeIterator<Item = i32> {
-    let mut params = params.clone();
+fn sort_update_params(params: &[[i32; 2]]) -> impl ExactSizeIterator<Item = i32> {
+    let mut params = params.to_owned();
     params.sort_by(|a, b| a[0].cmp(&b[0]));
 
     struct ParamIter<I>(I);

+ 31 - 18
frameworks/Rust/xitca-web/src/db_diesel.rs

@@ -1,10 +1,13 @@
-use std::sync::{Arc, Mutex};
+use std::{
+    io,
+    sync::{Arc, Mutex},
+};
 
 use diesel::{prelude::*, r2d2};
 
 use crate::{
     ser::{Fortune, Fortunes, World},
-    util::{Error, HandleResult, Rand, DB_URL},
+    util::{bulk_update_gen, Error, HandleResult, Rand, DB_URL},
 };
 
 pub type Pool = Arc<_Pool>;
@@ -14,7 +17,7 @@ pub struct _Pool {
     rng: Mutex<Rand>,
 }
 
-pub fn create() -> std::io::Result<Arc<_Pool>> {
+pub fn create() -> io::Result<Arc<_Pool>> {
     r2d2::Builder::new()
         .max_size(100)
         .min_idle(Some(100))
@@ -22,7 +25,7 @@ pub fn create() -> std::io::Result<Arc<_Pool>> {
         .idle_timeout(None)
         .max_lifetime(None)
         .build(r2d2::ConnectionManager::new(DB_URL))
-        .map_err(std::io::Error::other)
+        .map_err(io::Error::other)
         .map(|pool| {
             Arc::new(_Pool {
                 pool,
@@ -65,33 +68,32 @@ impl _Pool {
     pub fn update(&self, num: u16) -> HandleResult<Vec<World>> {
         use crate::schema::world::dsl::*;
 
+        let mut rngs = {
+            let mut rng = self.rng.lock().unwrap();
+            (0..num).map(|_| (rng.gen_id(), rng.gen_id())).collect::<Vec<_>>()
+        };
+
+        rngs.sort_by(|(a, _), (b, _)| a.cmp(b));
+
         let mut worlds = {
             let mut conn = self.pool.get()?;
-            let worlds = (0..num)
-                .map(|_| {
-                    let mut rng = self.rng.lock().unwrap();
-                    let w_id = rng.gen_id();
-                    let r_id = rng.gen_id();
-                    drop(rng);
+
+            let worlds = rngs
+                .iter()
+                .map(|(w_id, num)| {
                     world
                         .filter(id.eq(w_id))
                         .load::<World>(&mut conn)?
                         .pop()
                         .map(|mut w| {
-                            w.randomnumber = r_id;
+                            w.randomnumber = *num;
                             w
                         })
                         .ok_or_else(not_found)
                 })
                 .collect::<HandleResult<Vec<_>>>()?;
 
-            worlds.iter().try_for_each(|w| {
-                diesel::update(world)
-                    .filter(id.eq(w.id))
-                    .set(randomnumber.eq(w.randomnumber))
-                    .execute(&mut conn)
-                    .map(|_| ())
-            })?;
+            diesel::sql_query(update_query(&rngs)).execute(&mut conn)?;
 
             worlds
         };
@@ -115,3 +117,14 @@ impl _Pool {
         Ok(Fortunes::new(items))
     }
 }
+
+// diesel does not support high level bulk update api. use raw sql to bypass the limitation.
+// relate discussion: https://github.com/diesel-rs/diesel/discussions/2879
+fn update_query(ids: &[(i32, i32)]) -> String {
+    bulk_update_gen(|query| {
+        use std::fmt::Write;
+        ids.iter().for_each(|(w_id, num)| {
+            write!(query, "({}::int,{}::int),", w_id, num).unwrap();
+        });
+    })
+}

+ 10 - 4
frameworks/Rust/xitca-web/src/main.rs

@@ -39,16 +39,22 @@ async fn middleware<S>(service: &S, req: Ctx<'_>) -> Result<Response, core::conv
 where
     S: for<'c> Service<Ctx<'c>, Response = Response, Error = RouterError<util::Error>>,
 {
-    let mut res = service.call(req).await.unwrap_or_else(|e| match e {
+    let mut res = service.call(req).await.unwrap_or_else(error_handler);
+    res.headers_mut().insert(SERVER, SERVER_HEADER_VALUE);
+    Ok(res)
+}
+
+#[cold]
+#[inline(never)]
+fn error_handler(e: RouterError<util::Error>) -> Response {
+    match e {
         RouterError::Match(_) => error_response(StatusCode::NOT_FOUND),
         RouterError::NotAllowed(_) => error_response(StatusCode::METHOD_NOT_ALLOWED),
         RouterError::Service(e) => {
             println!("{e}");
             error_response(StatusCode::INTERNAL_SERVER_ERROR)
         }
-    });
-    res.headers_mut().insert(SERVER, SERVER_HEADER_VALUE);
-    Ok(res)
+    }
 }
 
 async fn plain_text(ctx: Ctx<'_>) -> HandleResult<Response> {

+ 9 - 75
frameworks/Rust/xitca-web/src/main_iou.rs

@@ -8,43 +8,31 @@ mod db;
 mod ser;
 mod util;
 
-use std::{convert::Infallible, fmt, future::poll_fn, io, pin::pin};
+use std::{convert::Infallible, io};
 
-use futures_core::stream::Stream;
 use xitca_http::{
-    date::DateTimeService,
-    h1::proto::context::Context,
-    http::{header::SERVER, StatusCode},
+    body::ResponseBody,
+    http::{self, header::SERVER, StatusCode},
+    HttpServiceBuilder,
 };
-use xitca_io::{
-    bytes::BytesMut,
-    io_uring::BoundedBuf,
-    net::{io_uring::TcpStream as IOUTcpStream, TcpStream},
-};
-use xitca_service::{fn_build, fn_service, middleware::UncheckedReady, Service, ServiceExt};
+use xitca_service::{fn_service, ServiceExt};
 
 use self::{
-    ser::{error_response, IntoResponse, Message, Request, Response},
+    ser::{error_response, IntoResponse, Message, Request},
     util::{context_mw, Ctx, QueryParse, SERVER_HEADER_VALUE},
 };
 
 fn main() -> io::Result<()> {
     let service = fn_service(handler)
         .enclosed(context_mw())
-        .enclosed(fn_build(|res: Result<_, _>| async {
-            res.map(|service| Http1IOU {
-                service,
-                date: DateTimeService::new(),
-            })
-        }))
-        .enclosed(UncheckedReady);
+        .enclosed(HttpServiceBuilder::h1().io_uring());
     xitca_server::Builder::new()
         .bind("xitca-iou", "0.0.0.0:8080", service)?
         .build()
         .wait()
 }
 
-async fn handler(ctx: Ctx<'_, Request<()>>) -> Result<Response, Infallible> {
+async fn handler<B>(ctx: Ctx<'_, Request<B>>) -> Result<http::Response<ResponseBody>, Infallible> {
     let (req, state) = ctx.into_parts();
     let mut res = match req.uri().path() {
         "/plaintext" => req.text_response().unwrap(),
@@ -71,59 +59,5 @@ async fn handler(ctx: Ctx<'_, Request<()>>) -> Result<Response, Infallible> {
         _ => error_response(StatusCode::NOT_FOUND),
     };
     res.headers_mut().insert(SERVER, SERVER_HEADER_VALUE);
-    Ok(res)
-}
-
-struct Http1IOU<S> {
-    service: S,
-    date: DateTimeService,
-}
-
-// runner for http service.
-impl<S> Service<TcpStream> for Http1IOU<S>
-where
-    S: Service<Request<()>, Response = Response>,
-    S::Error: fmt::Debug,
-{
-    type Response = ();
-    type Error = io::Error;
-
-    async fn call(&self, stream: TcpStream) -> Result<Self::Response, Self::Error> {
-        let std = stream.into_std()?;
-        let stream = IOUTcpStream::from_std(std);
-
-        let mut ctx = Context::<_, 8>::new(self.date.get());
-        let mut read_buf = BytesMut::new();
-        let mut write_buf = BytesMut::with_capacity(4096);
-
-        loop {
-            let len = read_buf.len();
-            let rem = read_buf.capacity() - len;
-            if rem < 4096 {
-                read_buf.reserve(4096 - rem);
-            }
-
-            let (res, buf) = stream.read(read_buf.slice(len..)).await;
-            read_buf = buf.into_inner();
-            if res? == 0 {
-                break;
-            }
-
-            while let Some((req, _)) = ctx.decode_head::<{ usize::MAX }>(&mut read_buf).unwrap() {
-                let (parts, body) = self.service.call(req).await.unwrap().into_parts();
-                let mut encoder = ctx.encode_head(parts, &body, &mut write_buf).unwrap();
-                let mut body = pin!(body);
-                let chunk = poll_fn(|cx| body.as_mut().poll_next(cx)).await.unwrap().unwrap();
-                encoder.encode(chunk, &mut write_buf);
-                encoder.encode_eof(&mut write_buf);
-            }
-
-            let (res, b) = stream.write_all(write_buf).await;
-            write_buf = b;
-            write_buf.clear();
-            res?;
-        }
-
-        stream.shutdown(std::net::Shutdown::Both)
-    }
+    Ok(res.map(Into::into))
 }

+ 4 - 8
frameworks/Rust/xitca-web/src/ser.rs

@@ -62,7 +62,7 @@ impl Fortune {
     }
 }
 
-// TODO: use another template engine with faster compile time.(perferably with no proc macro)
+// TODO: use another template engine with faster compile time.(preferably with no proc macro)
 #[cfg_attr(
     feature = "template",
     derive(sailfish::TemplateOnce),
@@ -84,11 +84,11 @@ impl<'de> Deserialize<'de> for Num {
     where
         D: Deserializer<'de>,
     {
-        use core::{cmp, fmt};
+        use core::fmt;
 
         use serde::de::{Error, MapAccess, Visitor};
 
-        const FIELDS: &'static [&'static str] = &["q"];
+        const FIELDS: &[&str] = &["q"];
 
         struct Field;
 
@@ -135,9 +135,7 @@ impl<'de> Deserialize<'de> for Num {
                 V: MapAccess<'de>,
             {
                 map.next_key::<Field>()?.ok_or_else(|| Error::missing_field("q"))?;
-                let q = map.next_value::<u16>().unwrap_or(1);
-                let q = cmp::min(500, cmp::max(1, q));
-                Ok(Num(q))
+                Ok(Num(map.next_value().unwrap_or(1).clamp(1, 500)))
             }
         }
 
@@ -201,8 +199,6 @@ impl<Ext> IntoResponse for Request<Ext> {
     }
 }
 
-#[cold]
-#[inline(never)]
 pub fn error_response(status: StatusCode) -> Response {
     http::Response::builder()
         .status(status)

+ 37 - 13
frameworks/Rust/xitca-web/src/util.rs

@@ -1,6 +1,6 @@
 #![allow(dead_code)]
 
-use core::{cell::RefCell, cmp};
+use core::cell::RefCell;
 
 use xitca_http::{bytes::BytesMut, http::header::HeaderValue};
 
@@ -10,16 +10,34 @@ pub trait QueryParse {
 
 impl QueryParse for Option<&str> {
     fn parse_query(self) -> u16 {
-        let num = self
-            .and_then(|this| {
-                use atoi::FromRadix10;
-                this.find('q')
-                    .map(|pos| u16::from_radix_10(this.split_at(pos + 2).1.as_ref()).0)
-            })
-            .unwrap_or(1);
+        self.and_then(|this| {
+            use atoi::FromRadix10;
+            this.find('q')
+                .map(|pos| u16::from_radix_10(this.split_at(pos + 2).1.as_ref()).0)
+        })
+        .unwrap_or(1)
+        .clamp(1, 500)
+    }
+}
+
+pub fn bulk_update_gen<F>(func: F) -> String
+where
+    F: FnOnce(&mut String),
+{
+    const PREFIX: &str = "UPDATE world SET randomNumber = w.r FROM (VALUES ";
+    const SUFFIX: &str = ") AS w (i,r) WHERE world.id = w.i";
+
+    let mut query = String::from(PREFIX);
+
+    func(&mut query);
 
-        cmp::min(500, cmp::max(1, num))
+    if query.ends_with(',') {
+        query.pop();
     }
+
+    query.push_str(SUFFIX);
+
+    query
 }
 
 #[allow(clippy::declare_interior_mutable_const)]
@@ -38,14 +56,20 @@ pub struct State<DB> {
 
 #[cfg(not(target_arch = "wasm32"))]
 mod non_wasm {
-    #[derive(Default)]
-    pub struct Rand(nanorand::WyRand);
+    use rand::{rngs::SmallRng, Rng, SeedableRng};
+
+    pub struct Rand(SmallRng);
+
+    impl Default for Rand {
+        fn default() -> Self {
+            Self(SmallRng::from_entropy())
+        }
+    }
 
     impl Rand {
         #[inline]
         pub fn gen_id(&mut self) -> i32 {
-            use nanorand::Rng;
-            (self.0.generate::<u32>() % 10_000 + 1) as _
+            self.0.gen_range(1..=10000)
         }
     }
 

+ 1 - 1
frameworks/Rust/xitca-web/xitca-web-axum.dockerfile

@@ -1,4 +1,4 @@
-FROM rust:1.79
+FROM rust:1.81
 
 ADD ./ /xitca-web
 WORKDIR /xitca-web

+ 1 - 1
frameworks/Rust/xitca-web/xitca-web-iou.dockerfile

@@ -1,4 +1,4 @@
-FROM rust:1.79
+FROM rust:1.81
 
 ADD ./ /xitca-web
 WORKDIR /xitca-web

+ 1 - 1
frameworks/Rust/xitca-web/xitca-web-sync.dockerfile

@@ -1,4 +1,4 @@
-FROM rust:1.79
+FROM rust:1.81
 
 ADD ./ /xitca-web
 WORKDIR /xitca-web

+ 1 - 1
frameworks/Rust/xitca-web/xitca-web-wasm.dockerfile

@@ -1,7 +1,7 @@
 ARG WASMTIME_VERSION=15.0.0
 ARG WASM_TARGET=wasm32-wasip1-threads
 
-FROM rust:1.79 AS compile
+FROM rust:1.81 AS compile
 
 ARG WASMTIME_VERSION
 ARG WASM_TARGET

+ 1 - 1
frameworks/Rust/xitca-web/xitca-web.dockerfile

@@ -1,4 +1,4 @@
-FROM rust:1.79
+FROM rust:1.81
 
 ADD ./ /xitca-web
 WORKDIR /xitca-web

+ 1 - 47
frameworks/Scala/otavia/benchmark_config.json

@@ -25,53 +25,7 @@
         "notes": "",
         "versus": "Otavia"
       },
-      "equalization": {
-        "json_url": "/json",
-        "plaintext_url": "/plaintext",
-        "db_url": "/db",
-        "query_url": "/queries?queries=",
-        "fortune_url": "/fortunes",
-        "update_url": "/updates?queries=",
-        "port": 8080,
-        "approach": "Realistic",
-        "classification": "Micro",
-        "database": "Postgres",
-        "framework": "otavia",
-        "language": "Scala",
-        "flavor": "None",
-        "orm": "Micro",
-        "platform": "Otavia",
-        "webserver": "None",
-        "os": "Linux",
-        "database_os": "Linux",
-        "display_name": "otavia",
-        "notes": "",
-        "versus": "Otavia"
-      },
-      "equalization-offgc": {
-        "json_url": "/json",
-        "plaintext_url": "/plaintext",
-        "db_url": "/db",
-        "query_url": "/queries?queries=",
-        "fortune_url": "/fortunes",
-        "update_url": "/updates?queries=",
-        "port": 8080,
-        "approach": "Realistic",
-        "classification": "Micro",
-        "database": "Postgres",
-        "framework": "otavia",
-        "language": "Scala",
-        "flavor": "None",
-        "orm": "Micro",
-        "platform": "Otavia",
-        "webserver": "None",
-        "os": "Linux",
-        "database_os": "Linux",
-        "display_name": "otavia",
-        "notes": "",
-        "versus": "Otavia"
-      },
-      "offgc": {
+      "overshoot": {
         "json_url": "/json",
         "plaintext_url": "/plaintext",
         "db_url": "/db",

+ 2 - 2
frameworks/Scala/otavia/build.sc

@@ -1,11 +1,11 @@
 import mill._
 import mill.scalalib._
 
-def otaviaVersion = "0.4.3"
+def otaviaVersion = "0.4.5"
 
 object benchmark extends ScalaModule {
 
-    override def scalaVersion = "3.3.1"
+    override def scalaVersion = "3.3.3"
 
     override def ivyDeps = Agg(
       ivy"cc.otavia::otavia-codec-http:$otaviaVersion",

+ 1 - 35
frameworks/Scala/otavia/config.toml

@@ -18,41 +18,7 @@ platform = "Otavia"
 webserver = "None"
 versus = "Otavia"
 
-[equalization]
-urls.plaintext = "/plaintext"
-urls.json = "/json"
-urls.db = "/db"
-urls.query = "/queries?queries="
-urls.update = "/updates?queries="
-urls.fortune = "/fortunes"
-approach = "Realistic"
-classification = "Micro"
-database = "Postgres"
-database_os = "Linux"
-os = "Linux"
-orm = "Micro"
-platform = "Otavia"
-webserver = "None"
-versus = "Otavia"
-
-[equalization-offgc]
-urls.plaintext = "/plaintext"
-urls.json = "/json"
-urls.db = "/db"
-urls.query = "/queries?queries="
-urls.update = "/updates?queries="
-urls.fortune = "/fortunes"
-approach = "Realistic"
-classification = "Micro"
-database = "Postgres"
-database_os = "Linux"
-os = "Linux"
-orm = "Micro"
-platform = "Otavia"
-webserver = "None"
-versus = "Otavia"
-
-[offgc]
+[overshoot]
 urls.plaintext = "/plaintext"
 urls.json = "/json"
 urls.db = "/db"

+ 0 - 16
frameworks/Scala/otavia/otavia-equalization-offgc.dockerfile

@@ -1,16 +0,0 @@
-FROM nightscape/scala-mill:eclipse-temurin-17.0.8.1_1-jdk-focal_0.11.6_3.3.0
-WORKDIR /otavia
-COPY benchmark benchmark
-COPY build.sc build.sc
-ENV COURSIER_REPOSITORIES=ivy2Local|central
-RUN mill benchmark.assembly
-
-EXPOSE 8080
-
-CMD java -server \
-    -Dcc.otavia.actor.worker.size=56 -Dcc.otavia.nio.worker.size=56 \
-    -Dcc.otavia.system.gc.aggressive=false \
-    -jar \
-    out/benchmark/assembly.dest/out.jar \
-    jdbc:postgresql://tfb-database:5432/hello_world \
-    benchmarkdbuser benchmarkdbpass 56

+ 0 - 16
frameworks/Scala/otavia/otavia-offgc.dockerfile

@@ -1,16 +0,0 @@
-FROM nightscape/scala-mill:eclipse-temurin-17.0.8.1_1-jdk-focal_0.11.6_3.3.0
-WORKDIR /otavia
-COPY benchmark benchmark
-COPY build.sc build.sc
-ENV COURSIER_REPOSITORIES=ivy2Local|central
-RUN mill benchmark.assembly
-
-EXPOSE 8080
-
-CMD java -server \
-    -Dcc.otavia.actor.worker.size=28 -Dcc.otavia.nio.worker.size=56 \
-    -Dcc.otavia.system.gc.aggressive=false \
-    -jar \
-    out/benchmark/assembly.dest/out.jar \
-    jdbc:postgresql://tfb-database:5432/hello_world \
-    benchmarkdbuser benchmarkdbpass 56

+ 2 - 2
frameworks/Scala/otavia/otavia-equalization.dockerfile → frameworks/Scala/otavia/otavia-overshoot.dockerfile

@@ -8,8 +8,8 @@ RUN mill benchmark.assembly
 EXPOSE 8080
 
 CMD java -server \
-    -Dcc.otavia.actor.worker.size=56 -Dcc.otavia.nio.worker.size=56 \
+    -Dcc.otavia.actor.worker.size=64 \
     -jar \
     out/benchmark/assembly.dest/out.jar \
     jdbc:postgresql://tfb-database:5432/hello_world \
-    benchmarkdbuser benchmarkdbpass 56
+    benchmarkdbuser benchmarkdbpass 64

+ 1 - 1
frameworks/Scala/otavia/otavia.dockerfile

@@ -8,7 +8,7 @@ RUN mill benchmark.assembly
 EXPOSE 8080
 
 CMD java -server \
-    -Dcc.otavia.actor.worker.size=28 -Dcc.otavia.nio.worker.size=56 \
+    -Dcc.otavia.actor.worker.size=56 \
     -jar \
     out/benchmark/assembly.dest/out.jar \
     jdbc:postgresql://tfb-database:5432/hello_world \