From b129c92a1f5a93b06e44dc7c104b1293d64e869b Mon Sep 17 00:00:00 2001 From: iapicca Date: Thu, 1 Jan 2026 17:40:22 +0200 Subject: [PATCH 01/28] add readme, analysis, config and ignore files --- frameworks/Dart/dart3_aot/.dockerignore | 9 +++++++ frameworks/Dart/dart3_aot/.gitignore | 5 ++++ frameworks/Dart/dart3_aot/README.md | 26 +++++++++++++++++++ .../Dart/dart3_aot/analysis_options.yaml | 1 + .../Dart/dart3_aot/benchmark_config.json | 26 +++++++++++++++++++ 5 files changed, 67 insertions(+) create mode 100644 frameworks/Dart/dart3_aot/.dockerignore create mode 100644 frameworks/Dart/dart3_aot/.gitignore create mode 100644 frameworks/Dart/dart3_aot/README.md create mode 100644 frameworks/Dart/dart3_aot/analysis_options.yaml create mode 100644 frameworks/Dart/dart3_aot/benchmark_config.json diff --git a/frameworks/Dart/dart3_aot/.dockerignore b/frameworks/Dart/dart3_aot/.dockerignore new file mode 100644 index 00000000000..6a6cc8727a7 --- /dev/null +++ b/frameworks/Dart/dart3_aot/.dockerignore @@ -0,0 +1,9 @@ +# From https://hub.docker.com/_/dart +.dockerignore +Dockerfile +build/ +.dart_tool/ +.git/ +.github/ +.gitignore +.packages diff --git a/frameworks/Dart/dart3_aot/.gitignore b/frameworks/Dart/dart3_aot/.gitignore new file mode 100644 index 00000000000..27fe9f77a4b --- /dev/null +++ b/frameworks/Dart/dart3_aot/.gitignore @@ -0,0 +1,5 @@ +# https://dart.dev/guides/libraries/private-files +# Created by `dart pub` +.dart_tool/ +*.lock +!bin diff --git a/frameworks/Dart/dart3_aot/README.md b/frameworks/Dart/dart3_aot/README.md new file mode 100644 index 00000000000..fff485a80f8 --- /dev/null +++ b/frameworks/Dart/dart3_aot/README.md @@ -0,0 +1,26 @@ +# Dart 3 AOT Benchmarking Test + +### Test Type Implementation Source Code + +- [JSON](server.dart) +- [PLAINTEXT](server.dart) + +## Important Libraries + +The tests were run with: + +- [Dart v3.10.3](https://dart.dev/) + +## Test URLs + +### JSON + +http://localhost:8080/json + +### PLAINTEXT + +http://localhost:8080/plaintext + +## Why testing AOT? + +In the current version Dart, when compiled to a self-contained executable, cannot fully take advantage of all the available threads available in TechEmpower Web Framework Benchmarks' [environment](https://www.techempower.com/benchmarks/#section=environment), see this [issue](https://github.com/dart-lang/sdk/issues/60815) for more details. \ No newline at end of file diff --git a/frameworks/Dart/dart3_aot/analysis_options.yaml b/frameworks/Dart/dart3_aot/analysis_options.yaml new file mode 100644 index 00000000000..572dd239d09 --- /dev/null +++ b/frameworks/Dart/dart3_aot/analysis_options.yaml @@ -0,0 +1 @@ +include: package:lints/recommended.yaml diff --git a/frameworks/Dart/dart3_aot/benchmark_config.json b/frameworks/Dart/dart3_aot/benchmark_config.json new file mode 100644 index 00000000000..059fb368d0e --- /dev/null +++ b/frameworks/Dart/dart3_aot/benchmark_config.json @@ -0,0 +1,26 @@ +{ + "framework": "dart3", + "tests": [ + { + "default": { + "json_url": "/json", + "plaintext_url": "/plaintext", + "port": 8080, + "approach": "Stripped", + "classification": "Platform", + "database": "None", + "framework": "None", + "language": "Dart", + "flavor": "None", + "orm": "None", + "platform": "None", + "webserver": "None", + "os": "Linux", + "database_os": "Linux", + "display_name": "dart3", + "notes": "", + "versus": "None" + } + } + ] +} From 3a470133ba3f1a67c448f04532033b7d977ae7bc Mon Sep 17 00:00:00 2001 From: iapicca Date: Thu, 1 Jan 2026 18:03:55 +0200 Subject: [PATCH 02/28] cp bin from dart3 and add aot specific dockerfile --- frameworks/Dart/dart3_aot/bin/server.dart | 83 ++++++++++++++++++++++ frameworks/Dart/dart3_aot/dart3.dockerfile | 28 ++++++++ frameworks/Dart/dart3_aot/pubspec.yaml | 7 ++ 3 files changed, 118 insertions(+) create mode 100755 frameworks/Dart/dart3_aot/bin/server.dart create mode 100644 frameworks/Dart/dart3_aot/dart3.dockerfile create mode 100644 frameworks/Dart/dart3_aot/pubspec.yaml diff --git a/frameworks/Dart/dart3_aot/bin/server.dart b/frameworks/Dart/dart3_aot/bin/server.dart new file mode 100755 index 00000000000..5859cc51f82 --- /dev/null +++ b/frameworks/Dart/dart3_aot/bin/server.dart @@ -0,0 +1,83 @@ +import 'dart:convert'; +import 'dart:io'; +import 'dart:isolate'; + +void main(List args) async { + /// Create an [Isolate] containing an [HttpServer] + /// for each processor after the first + for (var i = 1; i < Platform.numberOfProcessors; i++) { + await Isolate.spawn(_startServer, args); + } + + /// Create a [HttpServer] for the first processor + await _startServer(args); +} + +/// Creates and setup a [HttpServer] +Future _startServer(List _) async { + /// Binds the [HttpServer] on `0.0.0.0:8080`. + final server = await HttpServer.bind( + InternetAddress.anyIPv4, + 8080, + shared: true, + ); + + /// Sets [HttpServer]'s [serverHeader]. + server + ..defaultResponseHeaders.clear() + ..serverHeader = 'dart'; + + /// Handles [HttpRequest]'s from [HttpServer]. + await for (final request in server) { + switch (request.uri.path) { + case '/json': + _jsonTest(request); + break; + case '/plaintext': + _plaintextTest(request); + break; + default: + _sendResponse(request, HttpStatus.notFound); + } + } +} + +/// Completes the given [request] by writing the [bytes] with the given +/// [statusCode] and [type]. +void _sendResponse( + HttpRequest request, + int statusCode, { + ContentType? type, + List bytes = const [], +}) => request.response + ..statusCode = statusCode + ..headers.contentType = type + ..headers.date = DateTime.now() + ..contentLength = bytes.length + ..add(bytes) + ..close(); + +/// Completes the given [request] by writing the [response] as JSON. +void _sendJson(HttpRequest request, Object response) => _sendResponse( + request, + HttpStatus.ok, + type: ContentType.json, + bytes: _jsonEncoder.convert(response), +); + +/// Completes the given [request] by writing the [response] as plain text. +void _sendText(HttpRequest request, String response) => _sendResponse( + request, + HttpStatus.ok, + type: ContentType.text, + bytes: utf8.encode(response), +); + +/// Responds with the JSON test to the [request]. +void _jsonTest(HttpRequest request) => + _sendJson(request, const {'message': 'Hello, World!'}); + +/// Responds with the plaintext test to the [request]. +void _plaintextTest(HttpRequest request) => _sendText(request, 'Hello, World!'); + +final _jsonEncoder = JsonUtf8Encoder(); diff --git a/frameworks/Dart/dart3_aot/dart3.dockerfile b/frameworks/Dart/dart3_aot/dart3.dockerfile new file mode 100644 index 00000000000..3f15d1c657d --- /dev/null +++ b/frameworks/Dart/dart3_aot/dart3.dockerfile @@ -0,0 +1,28 @@ +# ---------- Build stage ---------- +FROM dart:stable AS build + +WORKDIR /app + +COPY pubspec.yaml . +RUN dart pub get + +COPY bin bin + +RUN dart compile aot-snapshot bin/server.dart -o server.aot + + +# ---------- Runtime stage ---------- +FROM gcr.io/distroless/base-debian12 + +# Copy Dart AOT runtime +COPY --from=build /usr/lib/dart/bin/dartaotruntime /usr/lib/dart/bin/dartaotruntime + +# Copy snapshot +COPY --from=build /app/server.aot /app/server.aot + +WORKDIR /app + +EXPOSE 8080 + +# Distroless requires absolute paths +ENTRYPOINT ["/usr/lib/dart/bin/dartaotruntime", "/app/server.aot"] diff --git a/frameworks/Dart/dart3_aot/pubspec.yaml b/frameworks/Dart/dart3_aot/pubspec.yaml new file mode 100644 index 00000000000..af799860827 --- /dev/null +++ b/frameworks/Dart/dart3_aot/pubspec.yaml @@ -0,0 +1,7 @@ +name: dartbenchmark +description: A benchmark of dart +environment: + sdk: ^3.10.3 + +dev_dependencies: + lints: ^6.0.0 \ No newline at end of file From e6acf044ef09d1877b5e52ff56f54b2ba0fa3864 Mon Sep 17 00:00:00 2001 From: iapicca Date: Thu, 1 Jan 2026 18:57:46 +0200 Subject: [PATCH 03/28] rename dockerfile update pubspec --- .../Dart/dart3_aot/{dart3.dockerfile => dart3_aot.dockerfile} | 0 frameworks/Dart/dart3_aot/pubspec.yaml | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) rename frameworks/Dart/dart3_aot/{dart3.dockerfile => dart3_aot.dockerfile} (100%) diff --git a/frameworks/Dart/dart3_aot/dart3.dockerfile b/frameworks/Dart/dart3_aot/dart3_aot.dockerfile similarity index 100% rename from frameworks/Dart/dart3_aot/dart3.dockerfile rename to frameworks/Dart/dart3_aot/dart3_aot.dockerfile diff --git a/frameworks/Dart/dart3_aot/pubspec.yaml b/frameworks/Dart/dart3_aot/pubspec.yaml index af799860827..3c6591c0c7f 100644 --- a/frameworks/Dart/dart3_aot/pubspec.yaml +++ b/frameworks/Dart/dart3_aot/pubspec.yaml @@ -1,4 +1,4 @@ -name: dartbenchmark +name: dart3_aot_benchmark description: A benchmark of dart environment: sdk: ^3.10.3 From 26e7104947d9d033bc39cb4000125ce0acab4383 Mon Sep 17 00:00:00 2001 From: iapicca Date: Fri, 2 Jan 2026 00:39:17 +0200 Subject: [PATCH 04/28] implement multi-group isolate scaling for AOT deployment --- frameworks/Dart/dart3_aot/README.md | 8 ++-- frameworks/Dart/dart3_aot/bin/server.dart | 46 ++++++++++++++++++++--- 2 files changed, 45 insertions(+), 9 deletions(-) diff --git a/frameworks/Dart/dart3_aot/README.md b/frameworks/Dart/dart3_aot/README.md index fff485a80f8..3f82485c9a4 100644 --- a/frameworks/Dart/dart3_aot/README.md +++ b/frameworks/Dart/dart3_aot/README.md @@ -1,6 +1,6 @@ # Dart 3 AOT Benchmarking Test -### Test Type Implementation Source Code +## Test Type Implementation Source Code - [JSON](server.dart) - [PLAINTEXT](server.dart) @@ -15,12 +15,12 @@ The tests were run with: ### JSON -http://localhost:8080/json +`http://localhost:8080/json` ### PLAINTEXT -http://localhost:8080/plaintext +`http://localhost:8080/plaintext` ## Why testing AOT? -In the current version Dart, when compiled to a self-contained executable, cannot fully take advantage of all the available threads available in TechEmpower Web Framework Benchmarks' [environment](https://www.techempower.com/benchmarks/#section=environment), see this [issue](https://github.com/dart-lang/sdk/issues/60815) for more details. \ No newline at end of file +In the current version Dart, when compiled to a self-contained executable, cannot fully take advantage of all the available threads available in TechEmpower Web Framework Benchmarks' [environment](https://www.techempower.com/benchmarks/#section=environment), see this [issue](https://github.com/dart-lang/sdk/issues/60815) for more details. diff --git a/frameworks/Dart/dart3_aot/bin/server.dart b/frameworks/Dart/dart3_aot/bin/server.dart index 5859cc51f82..b492b829c5a 100755 --- a/frameworks/Dart/dart3_aot/bin/server.dart +++ b/frameworks/Dart/dart3_aot/bin/server.dart @@ -2,19 +2,55 @@ import 'dart:convert'; import 'dart:io'; import 'dart:isolate'; +/// The maximum number of isolates managed by a single OS process group. +const _isolatesPerGroup = 8; + +/// Internal token used to notify newly spawned processes that they +/// belong to a secondary "worker group". +const _workerGroupTag = '--workerGroup'; + void main(List args) async { - /// Create an [Isolate] containing an [HttpServer] - /// for each processor after the first - for (var i = 1; i < Platform.numberOfProcessors; i++) { + /// Determine if this process instance was initialized as a worker group. + final isWorkerGroup = args.contains(_workerGroupTag); + if (isWorkerGroup) { + /// Sanitize the argument list to ensure the internal token does not + /// interfere with application-level argument parsing. + args.removeAt(args.indexOf(_workerGroupTag)); + } + + /// Calculate the number of secondary worker groups required + /// to fully utilize the available hardware capacity. + /// + /// Each group serves as a container for multiple isolates, + /// helping to bypass internal VM scaling bottlenecks. + final workerGroups = Platform.numberOfProcessors ~/ _isolatesPerGroup - 1; + if (!isWorkerGroup) { + for (var i = 0; i < workerGroups; i++) { + /// [Platform.script] identifies the AOT snapshot or executable. + /// [Isolate.spawnUri] bootstraps an entirely new group by re-executing [main()]. + Isolate.spawnUri(Platform.script, [_workerGroupTag], null); + } + } + + /// Determine the isolate quota for the current group. + /// Secondary worker groups run a full set defined by [_isolatesPerGroup]; + /// the primary group manages the remaining available cores. + final currentGroupIsolates = isWorkerGroup + ? _isolatesPerGroup + : Platform.numberOfProcessors - workerGroups * _isolatesPerGroup; + + /// Create an [Isolate] for the "Local Group" containing an [HttpServer] + /// for each processor available in this group after the first + for (var i = 1; i < currentGroupIsolates; i++) { await Isolate.spawn(_startServer, args); } - /// Create a [HttpServer] for the first processor + /// Initialize the server instance for the group's lead isolate. await _startServer(args); } /// Creates and setup a [HttpServer] -Future _startServer(List _) async { +Future _startServer(List args) async { /// Binds the [HttpServer] on `0.0.0.0:8080`. final server = await HttpServer.bind( InternetAddress.anyIPv4, From 7bf4b013ddbb6ce1ce2b6b2bec85d2d3793a7765 Mon Sep 17 00:00:00 2001 From: iapicca Date: Fri, 2 Jan 2026 15:47:53 +0200 Subject: [PATCH 05/28] fix 'framework' and 'display_name' in 'benchmark_config' --- frameworks/Dart/dart3_aot/benchmark_config.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/frameworks/Dart/dart3_aot/benchmark_config.json b/frameworks/Dart/dart3_aot/benchmark_config.json index 059fb368d0e..b2b7412ef28 100644 --- a/frameworks/Dart/dart3_aot/benchmark_config.json +++ b/frameworks/Dart/dart3_aot/benchmark_config.json @@ -1,5 +1,5 @@ { - "framework": "dart3", + "framework": "dart3_aot", "tests": [ { "default": { @@ -17,7 +17,7 @@ "webserver": "None", "os": "Linux", "database_os": "Linux", - "display_name": "dart3", + "display_name": "dart3_aot", "notes": "", "versus": "None" } From 19e07a8f6df73f80adf398bb70095adcfcb46ddd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=B0=A4=E9=9B=A8=E4=B8=9C?= Date: Sat, 3 Jan 2026 06:57:17 +0800 Subject: [PATCH 06/28] Update hyperlane (#10480) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * lock: toml * lock: toml * lock: toml * lock: toml * lock: toml * lock: toml * lock: toml * lock: toml * lock: toml * lock: toml * lock: toml * lock: toml * lock: toml * feat: runtime * feat: runtime * feat: runtime * lock: toml * lock: toml * lock: toml * lock: toml * lock: toml * lock: toml * lock: toml * lock: toml * feat: update * Merge remote-tracking branch 'upstream/master' * feat: update * feat: update * feat: update * feat: update * feat: update * feat: update * feat: update * feat: update * feat: update * feat: update * feat: update * feat: update * feat: update * feat: update * feat: update * feat: update * feat: update * feat: update * feat: update * feat: update * feat: update * feat: update * feat: update * Merge remote-tracking branch 'upstream/master' * feat: hyperlane * feat: update * docs: readme * feat: update * Merge remote-tracking branch 'upstream/master' * feat: update * feat: update * feat: update * Merge remote-tracking branch 'upstream/master' * feat: update * feat: update * feat: update * feat: update * feat: update * feat: update * feat: lock * feat: use super * feat: update lock * feat: update * feat: update lock * feat: update lock * feat: update lock * feat: lock * feat: update lock * feat: update lock * feat: update lock * feat: update lock * feat: update lock * feat: update lock * feat: update lock * feat: update lock * feat: update lock * feat: update lock * feat: update lock * feat: update lock * feat: update lock * Merge remote-tracking branch 'upstream/master' * feat: update * feat: utf8 * feat: utf8 * feat: lock * feat: update * feat: update * feat: update * feat: update * feat: update * feat: update * feat: update * feat: update * feat: update * feat: update * feat: update * feat: update * update: code * feat: update * feat: update * feat: update * feat: update * feat: update * feat: update * feat: update * Merge remote-tracking branch 'upstream/master' * feat: update version * feat: update version * update: code * Merge remote-tracking branch 'upstream/master' * feat: lock * feat: lock * feat: lock * feat: lock * feat: lock * feat: lock * feat: lock * feat: error handle * feat: dep * feat: get_thread_count * update: code * feat: lock * feat: speed * feat: speed * update: code * feat: speed * update: code * feat: lock * fix: Framework hyperlane does not define a default test in benchmark_config.json * feat: hyperlane http version * feat: hyperlane http version * feat: toml * feat: toml * feat: toml * feat: toml * feat: v0.1.0 * feat: toml * feat: v6 * feat: v6 * feat: v6 * feat: v6 * feat: v6 * debug: test cache * debug: test cache * feat: v6 * feat: send unwrap * feat: v6 * feat: v6 * feat: v0.1.0 * feat: toml * feat: toml * feat: db * feat: toml * feat: toml * feat: toml * feat: toml * feat: dir update * feat: toml * feat: toml * feat: toml * feat: toml * feat: toml * feat: toml * feat: toml * feat: toml * feat: toml * feat: toml * feat: toml * feat: toml * feat: toml * feat: toml * feat: toml * feat: 2025-10-24 12:22:32 * feat: v0.1.0 * Merge branch 'master' of github.com:TechEmpower/FrameworkBenchmarks * feat: v0.1.0 * Merge branch 'master' of github.com:TechEmpower/FrameworkBenchmarks * feat: 2025-11-09 18:38:22 * feat: toml * feat: toml * feat: buffer * feat: toml * feat: toml * feat: toml * feat: toml * feat: toml * feat: toml * feat: inline * feat: toml * feat: toml * feat: toml * feat: toml * feat: toml * feat: toml * feat: toml * feat: toml * 更新依赖项:升级 hyperlane 到 10.19.0,serde_json 到 1.0.147,http-constant 到 1.78.0,http-type 到 5.20.0 * 修正 README.md 中的标题格式 * feat: v0.1.0 * feat: toml * feat: v0.1.0 * feat: v0.1.0 * feat: v0.1.0 * feat: v0.1.0 * feat: v0.1.0 * feat: v0.1.0 --- frameworks/Rust/hyperlane/Cargo.lock | 16 ++++++++-------- frameworks/Rust/hyperlane/Cargo.toml | 2 +- frameworks/Rust/hyperlane/src/route/impl.rs | 18 +++++++----------- 3 files changed, 16 insertions(+), 20 deletions(-) diff --git a/frameworks/Rust/hyperlane/Cargo.lock b/frameworks/Rust/hyperlane/Cargo.lock index 066c6b02637..4378479e493 100644 --- a/frameworks/Rust/hyperlane/Cargo.lock +++ b/frameworks/Rust/hyperlane/Cargo.lock @@ -531,9 +531,9 @@ checksum = "c894fa5134967b007f4eb7d1204240ab3ba52707ef98ccdb49f5adc37076499f" [[package]] name = "http-type" -version = "5.26.2" +version = "5.30.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a6318004b422e63ac965a662de8810c5df2c8a1fee15bad87e69b53b54d5094" +checksum = "ee45bdeebd66330e42df03d5a9d2adbd915612a2948ac87549573711465177ea" dependencies = [ "hex", "http-compress", @@ -549,9 +549,9 @@ dependencies = [ [[package]] name = "hyperlane" -version = "10.23.6" +version = "10.25.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed2bb0815fca7e5f15786ad32ec48c8797a93819cb1d6ea9dae8bf31bce8cb63" +checksum = "133c225e583113dc0afd03cb9f8c5470584117b63b9c40d596f2b6e3f28c4575" dependencies = [ "http-type", "inventory", @@ -773,9 +773,9 @@ checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897" [[package]] name = "lombok-macros" -version = "1.13.18" +version = "1.13.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f0304bd5bbf8dbdaf33068cf13c37bade7e050d403ccc30dfb9808254c07c2e" +checksum = "c13a953bf01bc24da932ef6d1be7a27a3c42c36d2b18050f9051656369b4d317" dependencies = [ "proc-macro2", "quote", @@ -1521,9 +1521,9 @@ checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" [[package]] name = "syn" -version = "2.0.111" +version = "2.0.112" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "390cc9a294ab71bdb1aa2e99d13be9c753cd2d7bd6560c77118597410c4d2e87" +checksum = "21f182278bf2d2bcb3c88b1b08a37df029d71ce3d3ae26168e3c653b213b99d4" dependencies = [ "proc-macro2", "quote", diff --git a/frameworks/Rust/hyperlane/Cargo.toml b/frameworks/Rust/hyperlane/Cargo.toml index b5e1d6004bb..6351ce16c22 100644 --- a/frameworks/Rust/hyperlane/Cargo.toml +++ b/frameworks/Rust/hyperlane/Cargo.toml @@ -13,7 +13,7 @@ exclude = ["target", "Cargo.lock", "sh", ".github", "logs", "**/*.log"] [dependencies] futures = "0.3.31" -hyperlane = "10.23.6" +hyperlane = "10.25.5" hyperlane-time = "0.7.15" num_cpus = "1.17.0" once_cell = "1.21.3" diff --git a/frameworks/Rust/hyperlane/src/route/impl.rs b/frameworks/Rust/hyperlane/src/route/impl.rs index 64a7091e4df..17a76e5c906 100644 --- a/frameworks/Rust/hyperlane/src/route/impl.rs +++ b/frameworks/Rust/hyperlane/src/route/impl.rs @@ -12,7 +12,7 @@ impl ServerHook for JsonRoute { let run = || async { ctx.set_response_body(&serde_json::to_vec(&json).unwrap_or_default()) .await; - ctx.send().await.unwrap(); + ctx.send().await; }; run().await; while ctx.http_from_stream(RequestConfig::default()).await.is_ok() { @@ -31,7 +31,7 @@ impl ServerHook for PlaintextRoute { ctx.set_response_header(CONTENT_TYPE, TEXT_PLAIN).await; ctx.set_response_body(&RESPONSEDATA_BIN).await; let run = || async { - ctx.send().await.unwrap(); + ctx.send().await; }; run().await; while ctx.http_from_stream(RequestConfig::default()).await.is_ok() { @@ -53,8 +53,7 @@ impl ServerHook for DbRoute { ctx.set_response_body(&serde_json::to_vec(&query_row).unwrap_or_default()) .await .send() - .await - .unwrap(); + .await; }; run().await; while ctx.http_from_stream(RequestConfig::default()).await.is_ok() { @@ -83,8 +82,7 @@ impl ServerHook for QueryRoute { ctx.set_response_body(&serde_json::to_vec(&data).unwrap_or_default()) .await .send() - .await - .unwrap(); + .await; }; run().await; while ctx.http_from_stream(RequestConfig::default()).await.is_ok() { @@ -120,7 +118,7 @@ impl ServerHook for FortunesRoute { )); fortunes_list.sort_by(|it, next| it.message.cmp(&next.message)); let res: String = FortunesTemplate::new(fortunes_list).to_string(); - ctx.set_response_body(&res).await.send().await.unwrap(); + ctx.set_response_body(&res).await.send().await; }; run().await; while ctx.http_from_stream(RequestConfig::default()).await.is_ok() { @@ -148,8 +146,7 @@ impl ServerHook for UpdateRoute { ctx.set_response_body(&serde_json::to_vec(&res).unwrap_or_default()) .await .send() - .await - .unwrap(); + .await; }; run().await; while ctx.http_from_stream(RequestConfig::default()).await.is_ok() { @@ -177,8 +174,7 @@ impl ServerHook for CachedQueryRoute { ctx.set_response_body(&serde_json::to_vec(&res).unwrap_or_default()) .await .send() - .await - .unwrap(); + .await; }; run().await; while ctx.http_from_stream(RequestConfig::default()).await.is_ok() { From ed0fa57893620d230753df19738bb8aacdf3014c Mon Sep 17 00:00:00 2001 From: Nigro Simone Date: Fri, 2 Jan 2026 23:58:39 +0100 Subject: [PATCH 07/28] Express: optimize some slower/poor implementation (#10481) * chore: optimize express * perf: promise.all * perf: optimize postgres * fix: fast-json-stringify --- frameworks/JavaScript/express/app.js | 5 +- .../JavaScript/express/graphql-mongodb-app.js | 5 +- .../JavaScript/express/graphql-mysql-app.js | 5 +- .../express/graphql-postgres-app.js | 6 +- frameworks/JavaScript/express/mongodb-app.js | 9 +-- frameworks/JavaScript/express/mysql-app.js | 8 +- frameworks/JavaScript/express/package.json | 5 +- .../JavaScript/express/postgresql-app.js | 6 +- .../JavaScript/express/resolver-mongo.js | 17 ++--- .../JavaScript/express/resolver-postgres.js | 54 ++++++------- frameworks/JavaScript/express/resolver.js | 76 +++++++++---------- .../express/src/database/postgres.mjs | 12 +-- frameworks/JavaScript/express/src/server.mjs | 14 ++-- frameworks/JavaScript/express/src/utils.mjs | 33 ++++++-- 14 files changed, 126 insertions(+), 129 deletions(-) diff --git a/frameworks/JavaScript/express/app.js b/frameworks/JavaScript/express/app.js index 9f1039e2179..af0494d29fa 100755 --- a/frameworks/JavaScript/express/app.js +++ b/frameworks/JavaScript/express/app.js @@ -7,7 +7,6 @@ const cluster = require('cluster'), numCPUs = require('os').cpus().length, express = require('express'); -const bodyParser = require('body-parser'); if (cluster.isPrimary) { console.log(`Primary ${process.pid} is running`); @@ -23,8 +22,8 @@ if (cluster.isPrimary) { } else { const app = module.exports = express(); - // Configuration - app.use(bodyParser.urlencoded({ extended: true })); + app.set('x-powered-by', false); + app.set('etag', false) // Set headers for all routes app.use((req, res, next) => { diff --git a/frameworks/JavaScript/express/graphql-mongodb-app.js b/frameworks/JavaScript/express/graphql-mongodb-app.js index 4e02143a2c4..5170396e939 100644 --- a/frameworks/JavaScript/express/graphql-mongodb-app.js +++ b/frameworks/JavaScript/express/graphql-mongodb-app.js @@ -3,7 +3,6 @@ const numCPUs = require('os').cpus().length const express = require('express'); const mongoose = require('mongoose'); const app = express(); -const bodyParser = require('body-parser'); const port = 8080; mongoose.Promise = global.Promise; @@ -23,8 +22,8 @@ if (cluster.isPrimary) { cluster.on('exit', (worker, code, signal) => console.log('worker ' + worker.pid + ' died')); } else { - app.use(bodyParser.urlencoded({ extended:false })); - app.use(bodyParser.json()); + app.set('x-powered-by', false); + app.set('etag', false) const resolvers = require('./resolver-mongo'); diff --git a/frameworks/JavaScript/express/graphql-mysql-app.js b/frameworks/JavaScript/express/graphql-mysql-app.js index d63e9c3fd70..0c0d73ba9d6 100644 --- a/frameworks/JavaScript/express/graphql-mysql-app.js +++ b/frameworks/JavaScript/express/graphql-mysql-app.js @@ -2,7 +2,6 @@ const cluster = require('cluster') const numCPUs = require('os').cpus().length const express = require('express'); const app = express(); -const bodyParser = require('body-parser'); const port = 8080; if (cluster.isPrimary) { @@ -14,8 +13,8 @@ if (cluster.isPrimary) { cluster.on('exit', (worker, code, signal) => console.log('worker ' + worker.pid + ' died')); } else { - app.use(bodyParser.urlencoded({ extended:false })); - app.use(bodyParser.json()); + app.set('x-powered-by', false); + app.set('etag', false) const resolvers = require('./resolver'); diff --git a/frameworks/JavaScript/express/graphql-postgres-app.js b/frameworks/JavaScript/express/graphql-postgres-app.js index f05490fcabc..471d9f0486e 100644 --- a/frameworks/JavaScript/express/graphql-postgres-app.js +++ b/frameworks/JavaScript/express/graphql-postgres-app.js @@ -2,7 +2,6 @@ const cluster = require('cluster') const numCPUs = require('os').cpus().length const express = require('express'); const app = express(); -const bodyParser = require('body-parser'); const port = 8080; if (cluster.isPrimary) { @@ -14,9 +13,8 @@ if (cluster.isPrimary) { cluster.on('exit', (worker, code, signal) => console.log('worker ' + worker.pid + ' died')); } else { - - app.use(bodyParser.urlencoded({ extended:false })); - app.use(bodyParser.json()); + app.set('x-powered-by', false); + app.set('etag', false) const resolvers = require('./resolver-postgres'); diff --git a/frameworks/JavaScript/express/mongodb-app.js b/frameworks/JavaScript/express/mongodb-app.js index 534fddc63f5..e6fd208efa0 100644 --- a/frameworks/JavaScript/express/mongodb-app.js +++ b/frameworks/JavaScript/express/mongodb-app.js @@ -8,9 +8,6 @@ const express = require('express'); const mongoose = require('mongoose'); const connection = mongoose.createConnection('mongodb://tfb-database/hello_world'); -// Middleware -const bodyParser = require('body-parser'); - /** * Note! The benchmarks say we should use "id" as a property name. * However, Mongo provides a default index on "_id", so to be equivalent to the other tests, we use @@ -43,6 +40,9 @@ if (cluster.isPrimary) { } else { const app = module.exports = express(); + app.set('x-powered-by', false); + app.set('etag', false) + const randomTfbNumber = () => Math.floor(Math.random() * 10000) + 1; const toClientWorld = (world) => { if (world) { @@ -52,9 +52,6 @@ if (cluster.isPrimary) { return world; }; - // Configuration - app.use(bodyParser.urlencoded({extended: true})); - // Set headers for all routes app.use((req, res, next) => { res.setHeader("Server", "Express"); diff --git a/frameworks/JavaScript/express/mysql-app.js b/frameworks/JavaScript/express/mysql-app.js index 7e277f0e695..c247c8269a2 100644 --- a/frameworks/JavaScript/express/mysql-app.js +++ b/frameworks/JavaScript/express/mysql-app.js @@ -8,9 +8,6 @@ const cluster = require('cluster'), express = require('express'), Sequelize = require('sequelize'); -// Middleware -const bodyParser = require('body-parser'); - const sequelize = new Sequelize('hello_world', 'benchmarkdbuser', 'benchmarkdbpass', { host: 'tfb-database', dialect: 'mysql', @@ -59,9 +56,8 @@ if (cluster.isPrimary) { } else { const app = module.exports = express(); - // Configuration - // https://github.com/expressjs/method-override#custom-logic - app.use(bodyParser.urlencoded({ extended: true })); + app.set('x-powered-by', false); + app.set('etag', false) // Set headers for all routes app.use((req, res, next) => { diff --git a/frameworks/JavaScript/express/package.json b/frameworks/JavaScript/express/package.json index 4f770fb8d35..f68d5dbc3da 100644 --- a/frameworks/JavaScript/express/package.json +++ b/frameworks/JavaScript/express/package.json @@ -3,17 +3,16 @@ "version": "0.0.1", "private": true, "dependencies": { - "body-parser": "2.2.1", "dateformat": "5.0.3", "escape-html": "1.0.3", "express": "5.2.1", + "fast-json-stringify": "^6.1.1", "mongoose": "9.1.1", "mysql2": "3.16.0", "pg": "8.16.3", "pg-promise": "12.3.0", - "pug": "3.0.3", "postgres": "^3.4.7", - "slow-json-stringify": "^2.0.1", + "pug": "3.0.3", "sequelize": "6.37.7" } } diff --git a/frameworks/JavaScript/express/postgresql-app.js b/frameworks/JavaScript/express/postgresql-app.js index 38d1cfbdb7d..af0858f2471 100644 --- a/frameworks/JavaScript/express/postgresql-app.js +++ b/frameworks/JavaScript/express/postgresql-app.js @@ -6,9 +6,6 @@ const cluster = require('cluster'), express = require('express'), helper = require('./helper'); -// Middleware -const bodyParser = require('body-parser'); - const Sequelize = require('sequelize'); const sequelize = new Sequelize('hello_world', 'benchmarkdbuser', 'benchmarkdbpass', { host: 'tfb-database', @@ -62,7 +59,8 @@ if (cluster.isPrimary) { } else { const app = module.exports = express(); - app.use(bodyParser.urlencoded({ extended: true })); + app.set('x-powered-by', false); + app.set('etag', false) // Set headers for all routes app.use((req, res, next) => { diff --git a/frameworks/JavaScript/express/resolver-mongo.js b/frameworks/JavaScript/express/resolver-mongo.js index 6d7aed41d2a..8ed0d2c4193 100644 --- a/frameworks/JavaScript/express/resolver-mongo.js +++ b/frameworks/JavaScript/express/resolver-mongo.js @@ -31,7 +31,7 @@ async function getRandomWorld() { // Methods -async function arrayOfRandomWorlds(totalWorldsToReturn) { +function arrayOfRandomWorlds(totalWorldsToReturn) { const totalIterations = helper.sanititizeTotal(totalWorldsToReturn); const promises = []; @@ -39,7 +39,7 @@ async function arrayOfRandomWorlds(totalWorldsToReturn) { promises.push(getRandomWorld()); } - return await Promise.all(promises); + return Promise.all(promises); } async function getAndUpdateRandomWorld() { @@ -56,7 +56,7 @@ async function getAndUpdateRandomWorld() { return toClientWorld(world); } -async function updateRandomWorlds(totalToUpdate) { +function updateRandomWorlds(totalToUpdate) { const totalIterations = helper.sanititizeTotal(totalToUpdate); const promises = []; @@ -64,7 +64,7 @@ async function updateRandomWorlds(totalToUpdate) { promises.push(getAndUpdateRandomWorld()); } - return await Promise.all(promises); + return Promise.all(promises); } const sayHello = () => { @@ -81,14 +81,13 @@ module.exports = { multipleDatabaseQueries: async (parent, args) => await arrayOfRandomWorlds(args.total), getWorldById: async (parent, args) => toClientWorld(await World.findById(args.id).lean().exec()), getAllFortunes: async () => toClientWorld(await Fortune.find({}).lean().exec()), - getRandomAndUpdate: async (parent, args) => await updateRandomWorlds(args.total) + getRandomAndUpdate: (parent, args) => updateRandomWorlds(args.total) }, Mutation: { - createWorld: async (parent, args) => { - const randInt = helper.randomizeNum(); - return await World.create({_id: null, randomNumber: randInt}); + createWorld: (parent, args) => { + return World.create({_id: null, randomNumber: helper.randomizeNum()}); }, - updateWorld: async (parent, args) => { + updateWorld: (parent, args) => { return World.updateOne({_id: args.id}, { randomNumber: args.randomNumber }).exec(); diff --git a/frameworks/JavaScript/express/resolver-postgres.js b/frameworks/JavaScript/express/resolver-postgres.js index 3fc272e1533..66837973eaf 100644 --- a/frameworks/JavaScript/express/resolver-postgres.js +++ b/frameworks/JavaScript/express/resolver-postgres.js @@ -13,35 +13,28 @@ const connection = { const db = pgp(`postgres://${connection.username}:${connection.password}@${connection.host}:5432/${connection.db}`); -async function arrayOfRandomWorlds(totalWorldsToReturn) { +function arrayOfRandomWorlds(totalWorldsToReturn) { - var totalIterations = helper.sanititizeTotal(totalWorldsToReturn); - var arr = []; + const totalIterations = helper.sanititizeTotal(totalWorldsToReturn); + const arr = []; - return new Promise(async(resolve, reject) => { + for(let i = 0; i < totalIterations; i++) { + arr.push(getRandomWorld()); + } - for(var i = 0; i < totalIterations; i++) { - arr.push(await getRandomWorld()); - } - - if(arr.length == totalIterations) { - resolve(arr); - } - }); + return Promise.all(arr); }; -async function updateRandomWorlds(totalToUpdate) { +function updateRandomWorlds(totalToUpdate) { const total = helper.sanititizeTotal(totalToUpdate); - var arr = []; + const arr = []; - return new Promise(async(resolve, reject) => { - for(var i = 0; i < total; i++) { - arr.push(await updateRandomWorld()); - } + for(let i = 0; i < total; i++) { + arr.push(updateRandomWorld()); + } - if(arr.length === total) resolve(arr) - }); + return Promise.all(arr); }; const getRandomWorld = async () => { @@ -56,25 +49,24 @@ const updateRandomWorld = async () => { return {"id": world.id, "randomNumber": world.randomnumber}; }; -const getAllFortunes = async () => { - - return await db.many('select * from fortune', [true]); +const getAllFortunes = () => { + return db.many('select * from fortune', [true]); }; module.exports = { Query: { - singleDatabaseQuery: async() => await getRandomWorld(), - multipleDatabaseQueries: async(parent, args) => await arrayOfRandomWorlds(args.total), - getAllFortunes: async() => await getAllFortunes(), - getRandomAndUpdate: async(parent, args) => await updateRandomWorlds(args.total) + singleDatabaseQuery: () => getRandomWorld(), + multipleDatabaseQueries: (parent, args) => arrayOfRandomWorlds(args.total), + getAllFortunes: () => getAllFortunes(), + getRandomAndUpdate: (parent, args) => updateRandomWorlds(args.total) }, Mutation: { - createWorld: async(parent, args) => { + createWorld: (parent, args) => { let randInt = Math.floor(Math.random() * 1000) + 1; - return await World.create({ id: null, randomNumber: randInt }); + return World.create({ id: null, randomNumber: randInt }); }, - updateWorld: async(parent, args) => { - return await World.update({id: args.id, randomNumber: args.randomNumber}); + updateWorld: (parent, args) => { + return World.update({id: args.id, randomNumber: args.randomNumber}); } } } \ No newline at end of file diff --git a/frameworks/JavaScript/express/resolver.js b/frameworks/JavaScript/express/resolver.js index f396f502441..29fe902d52c 100644 --- a/frameworks/JavaScript/express/resolver.js +++ b/frameworks/JavaScript/express/resolver.js @@ -48,67 +48,61 @@ const Fortune = sequelize.define('fortune', { freezeTableName: true }); -async function arrayOfRandomWorlds(totalWorldToReturn) { +function arrayOfRandomWorlds(totalWorldToReturn) { - var totalIterations = helper.sanititizeTotal(totalWorldToReturn); - var arr = []; + const totalIterations = helper.sanititizeTotal(totalWorldToReturn); + const arr = []; - return new Promise(async (resolve, reject) => { - for(var i = 0; i < totalIterations; i++) { - let world = await World.findByPk(helper.randomizeNum()); - arr.push(world); - } - if(arr.length == totalIterations) { - resolve(arr); - } - }); + for(let i = 0; i < totalIterations; i++) { + arr.push(World.findByPk(helper.randomizeNum())); + } + + return Promise.all(arr); }; async function updateRandomWorlds(totalToUpdate) { const total = helper.sanititizeTotal(totalToUpdate); - var arr = []; + const arr = []; - return new Promise(async (resolve, reject) => { - for(var i = 0; i < total; i++) { + for(let i = 0; i < total; i++) { + arr.push(World.findByPk(helper.randomizeNum())); + } - const world = await World.findByPk(helper.randomizeNum()); - world.updateAttributes({ - randomNumber: helper.randomizeNum() - }) - arr.push(world); - } - if(arr.length == total) { - resolve(arr); - } - }); -}; + const results = await Promise.all(arr); -const sayHello = () => { + const updates = []; + for(const world of results){ + updates.push(world.updateAttributes({ + randomNumber: helper.randomizeNum() + })); + } - var helloWorld = new Object; - helloWorld.message = "Hello, World!"; + await Promise.all(updates); - return JSON.stringify(helloWorld); + return results; +} + +const sayHello = () => { + return JSON.stringify({ message:"Hello, World!" }); }; module.exports = { Query: { helloWorld: () => sayHello(), - getAllWorlds: async() => await World.findAll(), - singleDatabaseQuery: async() => await World.findByPk(helper.randomizeNum()), - multipleDatabaseQueries: async(parent, args) => await arrayOfRandomWorlds(args.total), - getWorldById: async(parent, args) => await World.findByPk(args.id), - getAllFortunes: async() => await Fortune.findAll(), - getRandomAndUpdate: async(parent, args) => await updateRandomWorlds(args.total) + getAllWorlds: () => World.findAll(), + singleDatabaseQuery: () => World.findByPk(helper.randomizeNum()), + multipleDatabaseQueries: (parent, args) => arrayOfRandomWorlds(args.total), + getWorldById: (parent, args) => World.findByPk(args.id), + getAllFortunes: () => Fortune.findAll(), + getRandomAndUpdate: (parent, args) => updateRandomWorlds(args.total) }, Mutation: { - createWorld: async(parent, args) => { - let randInt = Math.floor(Math.random() * 1000) + 1; - return await World.create({ id: null, randomNumber: randInt }); + createWorld: (parent, args) => { + return World.create({ id: null, randomNumber: Math.floor(Math.random() * 1000) + 1 }); }, - updateWorld: async(parent, args) => { - return await World.update({id: args.id, randomNumber: args.randomNumber}); + updateWorld: (parent, args) => { + return World.update({id: args.id, randomNumber: args.randomNumber}); } } } diff --git a/frameworks/JavaScript/express/src/database/postgres.mjs b/frameworks/JavaScript/express/src/database/postgres.mjs index 5f22801d234..755f4133bfa 100644 --- a/frameworks/JavaScript/express/src/database/postgres.mjs +++ b/frameworks/JavaScript/express/src/database/postgres.mjs @@ -8,12 +8,14 @@ const sql = postgres({ max: 1, }); -export const fortunes = async () => await sql`SELECT id, message FROM fortune`; +export const fortunes = () => sql`SELECT id, message FROM fortune`; -export const find = async (id) => - await sql`SELECT id, randomNumber FROM world WHERE id = ${id}`.then( - (arr) => arr[0] - ); +export const find = async (id) => { + const arr = await sql`SELECT id, randomNumber FROM world WHERE id = ${id}` + return arr[0] +}; + +export const getAllWorlds = () => sql`SELECT id, randomNumber FROM world` export const bulkUpdate = async (worlds) => { const sorted = sql( diff --git a/frameworks/JavaScript/express/src/server.mjs b/frameworks/JavaScript/express/src/server.mjs index b83b5590ebf..ab1512640ad 100644 --- a/frameworks/JavaScript/express/src/server.mjs +++ b/frameworks/JavaScript/express/src/server.mjs @@ -6,6 +6,7 @@ import { escape, jsonSerializer, worldObjectSerializer, + worldsObjectSerializer, sortByMessage, writeResponse, headerTypes, @@ -40,12 +41,13 @@ if (db) { app.get("/queries", async (req, res) => { try { - const queriesCount = getQueriesCount(req); - const databaseJobs = new Array(queriesCount) - .fill() - .map(() => db.find(generateRandomNumber())); - const worldObjects = await Promise.all(databaseJobs); - writeResponse(res, JSON.stringify(worldObjects)); + const queries = getQueriesCount(req); + const worldPromises = new Array(queries); + for (let i = 0; i < queries; i++) { + worldPromises[i] = db.find(generateRandomNumber()); + } + const worlds = await Promise.all(worldPromises); + writeResponse(res, worldsObjectSerializer(worlds)); } catch (error) { handleError(error, res); } diff --git a/frameworks/JavaScript/express/src/utils.mjs b/frameworks/JavaScript/express/src/utils.mjs index 1acf96b0d51..47b1fcfbfc0 100644 --- a/frameworks/JavaScript/express/src/utils.mjs +++ b/frameworks/JavaScript/express/src/utils.mjs @@ -1,4 +1,4 @@ -import { sjs, attr } from "slow-json-stringify"; +import fjs from 'fast-json-stringify'; export const GREETING = "Hello, World!"; @@ -47,10 +47,33 @@ export function escape(text) { }); } -export const jsonSerializer = sjs({ message: attr("string") }); -export const worldObjectSerializer = sjs({ - id: attr("number"), - randomnumber: attr("number"), +export const jsonSerializer = fjs({ + type: 'object', + properties: { + message: { + type: 'string', + format: 'unsafe', + } + } +}); + +export const worldObjectSerializer = fjs({ + type: 'object', + properties: { + id: { type: 'integer' }, + randomnumber: { type: 'integer' } + } +}); + +export const worldsObjectSerializer = fjs({ + type: 'array', + items: { + type: 'object', + properties: { + id: { type: 'integer' }, + randomnumber: { type: 'integer' } + } + } }); export function sortByMessage(arr) { From 6cb08a0ed7e5eaf346f1532627c83d96ced2fc0e Mon Sep 17 00:00:00 2001 From: Petrik de Heus Date: Sat, 3 Jan 2026 00:01:15 +0100 Subject: [PATCH 08/28] [ruby] Move database logic to seperate files for clarity (#10484) boot.rb contains Bundler initialization, constant definitions, database connections and model definitions. Extracting the database connection and model definition to a separate db.rb makes it more explicit what belongs where. It also makes it easier to compare the models and database setup across frameworks. --- frameworks/Ruby/rack-app/app.rb | 4 ++++ frameworks/Ruby/rack-app/config.ru | 1 - frameworks/Ruby/rack-app/{boot.rb => db.rb} | 10 ---------- frameworks/Ruby/rack-sequel/config.ru | 3 ++- .../Ruby/rack-sequel/{boot.rb => db.rb} | 3 --- frameworks/Ruby/rack-sequel/hello_world.rb | 6 +++++- frameworks/Ruby/rack/hello_world.rb | 2 +- frameworks/Ruby/roda-sequel/config.ru | 3 ++- .../Ruby/roda-sequel/{boot.rb => db.rb} | 19 +------------------ frameworks/Ruby/roda-sequel/hello_world.rb | 19 +++++++++++++++++++ frameworks/Ruby/sinatra-sequel/config.ru | 3 ++- .../Ruby/sinatra-sequel/{boot.rb => db.rb} | 10 ---------- frameworks/Ruby/sinatra-sequel/hello_world.rb | 13 +++++++++++++ frameworks/Ruby/sinatra/config.ru | 3 ++- frameworks/Ruby/sinatra/config/puma.rb | 3 +++ frameworks/Ruby/sinatra/{boot.rb => db.rb} | 13 ------------- frameworks/Ruby/sinatra/hello_world.rb | 13 +++++++++++++ 17 files changed, 67 insertions(+), 61 deletions(-) rename frameworks/Ruby/rack-app/{boot.rb => db.rb} (86%) rename frameworks/Ruby/rack-sequel/{boot.rb => db.rb} (95%) rename frameworks/Ruby/roda-sequel/{boot.rb => db.rb} (81%) rename frameworks/Ruby/sinatra-sequel/{boot.rb => db.rb} (88%) create mode 100644 frameworks/Ruby/sinatra/config/puma.rb rename frameworks/Ruby/sinatra/{boot.rb => db.rb} (84%) diff --git a/frameworks/Ruby/rack-app/app.rb b/frameworks/Ruby/rack-app/app.rb index e5310fc012d..1aa40e4a7bd 100644 --- a/frameworks/Ruby/rack-app/app.rb +++ b/frameworks/Ruby/rack-app/app.rb @@ -1,8 +1,12 @@ # frozen_string_literal: true +require 'bundler/setup' +Bundler.require(:default) # Load core modules require 'rack/app' require 'rack/app/front_end' +require_relative 'db' require 'json' +require 'time' class App < Rack::App MAX_PK = 10_000 diff --git a/frameworks/Ruby/rack-app/config.ru b/frameworks/Ruby/rack-app/config.ru index 27540c2f4ee..b61a5d5003e 100644 --- a/frameworks/Ruby/rack-app/config.ru +++ b/frameworks/Ruby/rack-app/config.ru @@ -1,5 +1,4 @@ # frozen_string_literal: true -require_relative 'boot' require_relative 'app' run App diff --git a/frameworks/Ruby/rack-app/boot.rb b/frameworks/Ruby/rack-app/db.rb similarity index 86% rename from frameworks/Ruby/rack-app/boot.rb rename to frameworks/Ruby/rack-app/db.rb index 7711f76a0a1..4d51f8b8109 100644 --- a/frameworks/Ruby/rack-app/boot.rb +++ b/frameworks/Ruby/rack-app/db.rb @@ -1,16 +1,6 @@ # frozen_string_literal: true -require 'bundler/setup' -require 'time' -MAX_PK = 10_000 -ID_RANGE = (1..MAX_PK).freeze -ALL_IDS = ID_RANGE.to_a -QUERIES_MIN = 1 -QUERIES_MAX = 500 SEQUEL_NO_ASSOCIATIONS = true -#SERVER_STRING = "Sinatra" - -Bundler.require(:default) # Load core modules def connect(dbtype) Bundler.require(dbtype) # Load database-specific modules diff --git a/frameworks/Ruby/rack-sequel/config.ru b/frameworks/Ruby/rack-sequel/config.ru index 8fceb7c06fc..9917d37585b 100644 --- a/frameworks/Ruby/rack-sequel/config.ru +++ b/frameworks/Ruby/rack-sequel/config.ru @@ -1,4 +1,5 @@ -require_relative 'boot' +# frozen_string_literal: true require_relative 'hello_world' + use Rack::ContentLength run HelloWorld.new diff --git a/frameworks/Ruby/rack-sequel/boot.rb b/frameworks/Ruby/rack-sequel/db.rb similarity index 95% rename from frameworks/Ruby/rack-sequel/boot.rb rename to frameworks/Ruby/rack-sequel/db.rb index 91594951944..5e6d6289500 100644 --- a/frameworks/Ruby/rack-sequel/boot.rb +++ b/frameworks/Ruby/rack-sequel/db.rb @@ -1,10 +1,7 @@ # frozen_string_literal: true -require 'bundler/setup' SEQUEL_NO_ASSOCIATIONS = true -Bundler.require(:default) # Load core modules - def connect(dbtype) Bundler.require(dbtype) # Load database-specific modules diff --git a/frameworks/Ruby/rack-sequel/hello_world.rb b/frameworks/Ruby/rack-sequel/hello_world.rb index f51e83740fc..e14198c47e7 100644 --- a/frameworks/Ruby/rack-sequel/hello_world.rb +++ b/frameworks/Ruby/rack-sequel/hello_world.rb @@ -1,4 +1,8 @@ # frozen_string_literal: true +require 'bundler/setup' +Bundler.require(:default) # Load core modules + +require_relative 'db' require 'time' # Our Rack application to be executed by rackup @@ -8,8 +12,8 @@ class HelloWorld ALL_IDS = ID_RANGE.to_a QUERIES_MIN = 1 QUERIES_MAX = 500 + CONTENT_TYPE = 'Content-Type' - CONTENT_LENGTH = 'Content-Length' JSON_TYPE = 'application/json' HTML_TYPE = 'text/html; charset=utf-8' PLAINTEXT_TYPE = 'text/plain' diff --git a/frameworks/Ruby/rack/hello_world.rb b/frameworks/Ruby/rack/hello_world.rb index 41a81aa193e..44b9fc759c9 100644 --- a/frameworks/Ruby/rack/hello_world.rb +++ b/frameworks/Ruby/rack/hello_world.rb @@ -19,8 +19,8 @@ class HelloWorld ALL_IDS = QUERY_RANGE.to_a # enumeration of all the IDs in fortune DB MIN_QUERIES = 1 # min number of records that can be retrieved MAX_QUERIES = 500 # max number of records that can be retrieved + CONTENT_TYPE = 'Content-Type' - CONTENT_LENGTH = 'Content-Length' JSON_TYPE = 'application/json' HTML_TYPE = 'text/html; charset=utf-8' PLAINTEXT_TYPE = 'text/plain' diff --git a/frameworks/Ruby/roda-sequel/config.ru b/frameworks/Ruby/roda-sequel/config.ru index 58f0ca7496a..bc64c3d5fbc 100644 --- a/frameworks/Ruby/roda-sequel/config.ru +++ b/frameworks/Ruby/roda-sequel/config.ru @@ -1,3 +1,4 @@ -require_relative 'boot' +# frozen_string_literal: true require_relative 'hello_world' + run HelloWorld.freeze.app diff --git a/frameworks/Ruby/roda-sequel/boot.rb b/frameworks/Ruby/roda-sequel/db.rb similarity index 81% rename from frameworks/Ruby/roda-sequel/boot.rb rename to frameworks/Ruby/roda-sequel/db.rb index 6d2d2e44e9f..be0ed03c2a6 100644 --- a/frameworks/Ruby/roda-sequel/boot.rb +++ b/frameworks/Ruby/roda-sequel/db.rb @@ -1,23 +1,6 @@ # frozen_string_literal: true -require "bundler/setup" -require "time" -MAX_PK = 10_000 -QUERY_RANGE = (1..MAX_PK).freeze -ALL_IDS = QUERY_RANGE.to_a -QUERIES_MIN = 1 -QUERIES_MAX = 500 -SEQUEL_NO_ASSOCIATIONS = true - -SERVER_STRING = "roda" -Bundler.require(:default) # Load core modules - -CONTENT_TYPE = 'Content-Type' -JSON_TYPE = 'application/json' -HTML_TYPE = 'text/html; charset=utf-8' -PLAINTEXT_TYPE = 'text/plain' -DATE_HEADER = 'Date' -SERVER_HEADER = 'Server' +SEQUEL_NO_ASSOCIATIONS = true def connect(dbtype) Bundler.require(dbtype) # Load database-specific modules diff --git a/frameworks/Ruby/roda-sequel/hello_world.rb b/frameworks/Ruby/roda-sequel/hello_world.rb index 81b08c6bdd9..3c3845187f2 100644 --- a/frameworks/Ruby/roda-sequel/hello_world.rb +++ b/frameworks/Ruby/roda-sequel/hello_world.rb @@ -1,7 +1,26 @@ # frozen_string_literal: true +require 'bundler/setup' +Bundler.require(:default) # Load core modules + +require_relative 'db' +require 'time' # Our Rack application to be executed by rackup class HelloWorld < Roda + MAX_PK = 10_000 + QUERY_RANGE = (1..MAX_PK).freeze + ALL_IDS = QUERY_RANGE.to_a + QUERIES_MIN = 1 + QUERIES_MAX = 500 + + CONTENT_TYPE = 'Content-Type' + JSON_TYPE = 'application/json' + HTML_TYPE = 'text/html; charset=utf-8' + PLAINTEXT_TYPE = 'text/plain' + DATE_HEADER = 'Date' + SERVER_HEADER = 'Server' + SERVER_STRING = 'roda' + plugin :hooks plugin :render, escape: true, layout_opts: { cache_key: "default_layout" } plugin :default_headers, SERVER_HEADER => SERVER_STRING diff --git a/frameworks/Ruby/sinatra-sequel/config.ru b/frameworks/Ruby/sinatra-sequel/config.ru index a8b9b9cdc91..f615b59a80e 100644 --- a/frameworks/Ruby/sinatra-sequel/config.ru +++ b/frameworks/Ruby/sinatra-sequel/config.ru @@ -1,3 +1,4 @@ -require_relative 'boot' +# frozen_string_literal: true require_relative 'hello_world' + run HelloWorld.new diff --git a/frameworks/Ruby/sinatra-sequel/boot.rb b/frameworks/Ruby/sinatra-sequel/db.rb similarity index 88% rename from frameworks/Ruby/sinatra-sequel/boot.rb rename to frameworks/Ruby/sinatra-sequel/db.rb index 58cdb0c25cb..9e3346c5758 100644 --- a/frameworks/Ruby/sinatra-sequel/boot.rb +++ b/frameworks/Ruby/sinatra-sequel/db.rb @@ -1,16 +1,6 @@ # frozen_string_literal: true -require 'bundler/setup' -require 'time' -MAX_PK = 10_000 -ID_RANGE = (1..MAX_PK).freeze -ALL_IDS = ID_RANGE.to_a -QUERIES_MIN = 1 -QUERIES_MAX = 500 SEQUEL_NO_ASSOCIATIONS = true -SERVER_STRING = "Sinatra" - -Bundler.require(:default) # Load core modules def connect(dbtype) Bundler.require(dbtype) # Load database-specific modules diff --git a/frameworks/Ruby/sinatra-sequel/hello_world.rb b/frameworks/Ruby/sinatra-sequel/hello_world.rb index 0b259e142b8..7764bcf25ab 100644 --- a/frameworks/Ruby/sinatra-sequel/hello_world.rb +++ b/frameworks/Ruby/sinatra-sequel/hello_world.rb @@ -1,7 +1,20 @@ # frozen_string_literal: true +require 'bundler/setup' +Bundler.require(:default) # Load core modules + +require_relative 'db' +require 'time' # Our Rack application to be executed by rackup class HelloWorld < Sinatra::Base + MAX_PK = 10_000 + ID_RANGE = (1..MAX_PK).freeze + ALL_IDS = ID_RANGE.to_a + QUERIES_MIN = 1 + QUERIES_MAX = 500 + + SERVER_STRING = 'Sinatra' + configure do # Static file serving is ostensibly disabled in modular mode but Sinatra # still calls an expensive Proc on every request... diff --git a/frameworks/Ruby/sinatra/config.ru b/frameworks/Ruby/sinatra/config.ru index a8b9b9cdc91..f615b59a80e 100644 --- a/frameworks/Ruby/sinatra/config.ru +++ b/frameworks/Ruby/sinatra/config.ru @@ -1,3 +1,4 @@ -require_relative 'boot' +# frozen_string_literal: true require_relative 'hello_world' + run HelloWorld.new diff --git a/frameworks/Ruby/sinatra/config/puma.rb b/frameworks/Ruby/sinatra/config/puma.rb new file mode 100644 index 00000000000..e7a9219ba9c --- /dev/null +++ b/frameworks/Ruby/sinatra/config/puma.rb @@ -0,0 +1,3 @@ +before_fork do + ActiveRecord::Base.connection_handler.clear_active_connections! +end diff --git a/frameworks/Ruby/sinatra/boot.rb b/frameworks/Ruby/sinatra/db.rb similarity index 84% rename from frameworks/Ruby/sinatra/boot.rb rename to frameworks/Ruby/sinatra/db.rb index 33843258016..fd08b235d06 100644 --- a/frameworks/Ruby/sinatra/boot.rb +++ b/frameworks/Ruby/sinatra/db.rb @@ -1,15 +1,4 @@ # frozen_string_literal: true -require 'bundler/setup' -require 'time' - -MAX_PK = 10_000 -ID_RANGE = (1..MAX_PK).freeze -ALL_IDS = ID_RANGE.to_a -QUERIES_MIN = 1 -QUERIES_MAX = 500 -SERVER_STRING = "Sinatra" - -Bundler.require(:default) # Load core modules def connect(dbtype) Bundler.require(dbtype) # Load database-specific modules @@ -64,5 +53,3 @@ def self.upsert_all(attributes, on_duplicate: :update, update_only: nil, returni class Fortune < ActiveRecord::Base self.table_name = name end - -ActiveRecord::Base.connection_handler.clear_active_connections! diff --git a/frameworks/Ruby/sinatra/hello_world.rb b/frameworks/Ruby/sinatra/hello_world.rb index 5841e433176..7c51c0dc0b3 100644 --- a/frameworks/Ruby/sinatra/hello_world.rb +++ b/frameworks/Ruby/sinatra/hello_world.rb @@ -1,7 +1,20 @@ # frozen_string_literal: true +require 'bundler/setup' +Bundler.require(:default) # Load core modules + +require_relative 'db' +require 'time' # Our Rack application to be executed by rackup class HelloWorld < Sinatra::Base + MAX_PK = 10_000 + ID_RANGE = (1..MAX_PK).freeze + ALL_IDS = ID_RANGE.to_a + QUERIES_MIN = 1 + QUERIES_MAX = 500 + + SERVER_STRING = 'Sinatra' + configure do # Static file serving is ostensibly disabled in modular mode but Sinatra # still calls an expensive Proc on every request... From d173d1914a487c48cb022f1bf7a4efc971c541a2 Mon Sep 17 00:00:00 2001 From: Petrik de Heus Date: Sat, 3 Jan 2026 00:01:30 +0100 Subject: [PATCH 09/28] [ruby/grape] Update to 3.0 (#10485) --- frameworks/Ruby/grape/Gemfile | 2 +- frameworks/Ruby/grape/Gemfile.lock | 10 +++++++--- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/frameworks/Ruby/grape/Gemfile b/frameworks/Ruby/grape/Gemfile index bf086715fdb..6b7751d9ee3 100644 --- a/frameworks/Ruby/grape/Gemfile +++ b/frameworks/Ruby/grape/Gemfile @@ -2,7 +2,7 @@ source 'https://rubygems.org' gem 'trilogy', '~> 2.9' gem 'activerecord', '~> 8.1.0', :require => 'active_record' -gem 'grape', '~> 2.4' +gem 'grape', '~> 3.0' gem 'json', '~> 2.9' group :iodine, optional: true do diff --git a/frameworks/Ruby/grape/Gemfile.lock b/frameworks/Ruby/grape/Gemfile.lock index 87896970257..215970c3c73 100644 --- a/frameworks/Ruby/grape/Gemfile.lock +++ b/frameworks/Ruby/grape/Gemfile.lock @@ -25,6 +25,9 @@ GEM concurrent-ruby (1.3.5) connection_pool (2.5.5) drb (2.2.3) + dry-configurable (1.3.0) + dry-core (~> 1.1) + zeitwerk (~> 2.6) dry-core (1.1.0) concurrent-ruby (~> 1.0) logger @@ -42,8 +45,9 @@ GEM dry-inflector (~> 1.0) dry-logic (~> 1.4) zeitwerk (~> 2.6) - grape (2.4.0) - activesupport (>= 6.1) + grape (3.0.1) + activesupport (>= 7.0) + dry-configurable dry-types (>= 1.1) mustermann-grape (~> 1.1.0) rack (>= 2) @@ -78,7 +82,7 @@ PLATFORMS DEPENDENCIES activerecord (~> 8.1.0) - grape (~> 2.4) + grape (~> 3.0) iodine (~> 0.7) json (~> 2.9) puma (~> 7.1) From b39651da2cdca3cbd7606c77df9a41c90e7428e9 Mon Sep 17 00:00:00 2001 From: Petrik de Heus Date: Sat, 3 Jan 2026 00:01:50 +0100 Subject: [PATCH 10/28] [ruby/rack] Try ZJIT (#10486) ZJIT is the successor JIT compiler to YJIT. --- frameworks/Ruby/rack/benchmark_config.json | 21 +++++++++++++++++ frameworks/Ruby/rack/rack-zjit.dockerfile | 26 ++++++++++++++++++++++ 2 files changed, 47 insertions(+) create mode 100644 frameworks/Ruby/rack/rack-zjit.dockerfile diff --git a/frameworks/Ruby/rack/benchmark_config.json b/frameworks/Ruby/rack/benchmark_config.json index 031e00dc5e9..1e439f626c4 100644 --- a/frameworks/Ruby/rack/benchmark_config.json +++ b/frameworks/Ruby/rack/benchmark_config.json @@ -148,6 +148,27 @@ "database_os": "Linux", "display_name": "rack [pitchfork]", "notes": "" + }, + "zjit": { + "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": "Platform", + "orm": "raw", + "database": "Postgres", + "framework": "rack", + "language": "Ruby", + "platform": "Mri", + "webserver": "Pitchfork", + "os": "Linux", + "database_os": "Linux", + "display_name": "rack [puma, zjit]", + "notes": "" } } ] diff --git a/frameworks/Ruby/rack/rack-zjit.dockerfile b/frameworks/Ruby/rack/rack-zjit.dockerfile new file mode 100644 index 00000000000..2751a8eb5ac --- /dev/null +++ b/frameworks/Ruby/rack/rack-zjit.dockerfile @@ -0,0 +1,26 @@ +FROM ruby:4.0 + +ENV RUBY_ZJIT_ENABLE=1 +ENV RUBY_MN_THREADS=1 + +# Use Jemalloc +RUN apt-get update && \ + apt-get install -y --no-install-recommends libjemalloc2 +ENV LD_PRELOAD=libjemalloc.so.2 + +WORKDIR /rack + +COPY Gemfile* ./ + +ENV BUNDLE_FORCE_RUBY_PLATFORM=true +RUN bundle config set with 'puma' +RUN bundle install --jobs=8 + +COPY . . + +ENV MAX_THREADS=5 + +EXPOSE 8080 + +CMD export WEB_CONCURRENCY=$(($(nproc)*5/4)) && \ + bundle exec puma -C config/puma.rb -b tcp://0.0.0.0:8080 -e production From f593e18f203e1746a0e89a7538539b9df26cf86e Mon Sep 17 00:00:00 2001 From: Petrik de Heus Date: Sat, 3 Jan 2026 00:02:08 +0100 Subject: [PATCH 11/28] [ruby/rack-sequel] Increase threads instead of workers (#10487) Try more 1.25 more threads instead of 1.25 more workers. --- frameworks/Ruby/rack-sequel/rack-sequel-postgres.dockerfile | 4 ++-- frameworks/Ruby/rack-sequel/rack-sequel.dockerfile | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/frameworks/Ruby/rack-sequel/rack-sequel-postgres.dockerfile b/frameworks/Ruby/rack-sequel/rack-sequel-postgres.dockerfile index 735a87df70a..a7c719e29a0 100644 --- a/frameworks/Ruby/rack-sequel/rack-sequel-postgres.dockerfile +++ b/frameworks/Ruby/rack-sequel/rack-sequel-postgres.dockerfile @@ -17,9 +17,9 @@ RUN bundle install --jobs=4 --gemfile=/rack-sequel/Gemfile ENV DBTYPE=postgresql -ENV MAX_THREADS=5 +ENV MAX_THREADS=8 EXPOSE 8080 -CMD export WEB_CONCURRENCY=$(($(nproc)*5/4)) && \ +CMD export WEB_CONCURRENCY=auto && \ bundle exec puma -C config/puma.rb -b tcp://0.0.0.0:8080 -e production diff --git a/frameworks/Ruby/rack-sequel/rack-sequel.dockerfile b/frameworks/Ruby/rack-sequel/rack-sequel.dockerfile index 08ed6159d26..3233527aee4 100644 --- a/frameworks/Ruby/rack-sequel/rack-sequel.dockerfile +++ b/frameworks/Ruby/rack-sequel/rack-sequel.dockerfile @@ -17,9 +17,9 @@ RUN bundle install --jobs=4 --gemfile=/rack-sequel/Gemfile ENV DBTYPE=mysql -ENV MAX_THREADS=5 +ENV MAX_THREADS=8 EXPOSE 8080 -CMD export WEB_CONCURRENCY=$(($(nproc)*5/4)) && \ +CMD export WEB_CONCURRENCY=auto && \ bundle exec puma -C config/puma.rb -b tcp://0.0.0.0:8080 -e production From 942a46c323345125929505ff2c76a1cf3cacf6e2 Mon Sep 17 00:00:00 2001 From: Petrik de Heus Date: Sat, 3 Jan 2026 00:02:36 +0100 Subject: [PATCH 12/28] [ruby] Set puma workers to 1.25 * nproc (#10488) WEB_CONCURRENCY=auto sets the number of workers to the number of processors. Setting it to 1.25 the number of processors seems to perform better. --- frameworks/Ruby/hanami/hanami.dockerfile | 4 ++-- frameworks/Ruby/rails/rails-mysql.dockerfile | 4 ++-- frameworks/Ruby/rails/rails.dockerfile | 4 ++-- frameworks/Ruby/roda-sequel/roda-sequel-postgres.dockerfile | 4 ++-- frameworks/Ruby/roda-sequel/roda-sequel.dockerfile | 4 ++-- .../Ruby/sinatra-sequel/sinatra-sequel-postgres.dockerfile | 4 ++-- frameworks/Ruby/sinatra-sequel/sinatra-sequel.dockerfile | 4 ++-- frameworks/Ruby/sinatra/sinatra-postgres.dockerfile | 1 - frameworks/Ruby/sinatra/sinatra.dockerfile | 4 ++-- 9 files changed, 16 insertions(+), 17 deletions(-) diff --git a/frameworks/Ruby/hanami/hanami.dockerfile b/frameworks/Ruby/hanami/hanami.dockerfile index 756e58610f5..ad30b7f9765 100644 --- a/frameworks/Ruby/hanami/hanami.dockerfile +++ b/frameworks/Ruby/hanami/hanami.dockerfile @@ -1,7 +1,6 @@ FROM ruby:4.0 ENV RUBY_YJIT_ENABLE=1 -ENV WEB_CONCURRENCY=auto # Use Jemalloc RUN apt-get update && \ @@ -21,4 +20,5 @@ ENV HANAMI_ENV=production ENV HANAMI_PORT=8080 ENV DATABASE_URL=postgres://benchmarkdbuser:benchmarkdbpass@tfb-database:5432/hello_world -CMD bundle exec hanami server +CMD export WEB_CONCURRENCY=$(($(nproc)*5/4)) && \ + bundle exec hanami server diff --git a/frameworks/Ruby/rails/rails-mysql.dockerfile b/frameworks/Ruby/rails/rails-mysql.dockerfile index b5f3505081a..192e4153876 100644 --- a/frameworks/Ruby/rails/rails-mysql.dockerfile +++ b/frameworks/Ruby/rails/rails-mysql.dockerfile @@ -20,10 +20,10 @@ RUN bundle install --jobs=8 COPY . /rails/ -ENV WEB_CONCURRENCY=auto ENV RAILS_MAX_THREADS=5 ENV RAILS_ENV=production_mysql ENV PORT=8080 ENV REDIS_URL=redis://localhost:6379/0 -CMD service redis-server start && \ +CMD export WEB_CONCURRENCY=$(($(nproc)*5/4)) && \ + service redis-server start && \ bin/rails server diff --git a/frameworks/Ruby/rails/rails.dockerfile b/frameworks/Ruby/rails/rails.dockerfile index 1f0951cc651..a31d255c356 100644 --- a/frameworks/Ruby/rails/rails.dockerfile +++ b/frameworks/Ruby/rails/rails.dockerfile @@ -20,10 +20,10 @@ RUN bundle install --jobs=8 COPY . /rails/ -ENV WEB_CONCURRENCY=auto ENV RAILS_MAX_THREADS=5 ENV RAILS_ENV=production_postgresql ENV PORT=8080 ENV REDIS_URL=redis://localhost:6379/0 -CMD service redis-server start && \ +CMD export WEB_CONCURRENCY=$(($(nproc)*5/4)) && \ + service redis-server start && \ bin/rails server diff --git a/frameworks/Ruby/roda-sequel/roda-sequel-postgres.dockerfile b/frameworks/Ruby/roda-sequel/roda-sequel-postgres.dockerfile index 0b48e27485a..2c7e1ab6492 100644 --- a/frameworks/Ruby/roda-sequel/roda-sequel-postgres.dockerfile +++ b/frameworks/Ruby/roda-sequel/roda-sequel-postgres.dockerfile @@ -19,8 +19,8 @@ ENV RACK_ENV=production ENV DBTYPE=postgresql ENV MAX_THREADS=5 -ENV WEB_CONCURRENCY=auto EXPOSE 8080 -CMD bundle exec puma -C config/puma.rb -b tcp://0.0.0.0:8080 +CMD export WEB_CONCURRENCY=$(($(nproc)*5/4)) && \ + bundle exec puma -C config/puma.rb -b tcp://0.0.0.0:8080 diff --git a/frameworks/Ruby/roda-sequel/roda-sequel.dockerfile b/frameworks/Ruby/roda-sequel/roda-sequel.dockerfile index 5a1c0a16161..1fedec04442 100644 --- a/frameworks/Ruby/roda-sequel/roda-sequel.dockerfile +++ b/frameworks/Ruby/roda-sequel/roda-sequel.dockerfile @@ -18,9 +18,9 @@ RUN bundle install --jobs=8 ENV RACK_ENV=production ENV DBTYPE=mysql -ENV WEB_CONCURRENCY=auto ENV MAX_THREADS=5 EXPOSE 8080 -CMD bundle exec puma -C config/puma.rb -b tcp://0.0.0.0:8080 +CMD export WEB_CONCURRENCY=$(($(nproc)*5/4)) && \ + bundle exec puma -C config/puma.rb -b tcp://0.0.0.0:8080 diff --git a/frameworks/Ruby/sinatra-sequel/sinatra-sequel-postgres.dockerfile b/frameworks/Ruby/sinatra-sequel/sinatra-sequel-postgres.dockerfile index c672cd03058..0459d8959a4 100644 --- a/frameworks/Ruby/sinatra-sequel/sinatra-sequel-postgres.dockerfile +++ b/frameworks/Ruby/sinatra-sequel/sinatra-sequel-postgres.dockerfile @@ -16,9 +16,9 @@ RUN bundle install --jobs=4 --gemfile=/sinatra-sequel/Gemfile ENV APP_ENV=production ENV DBTYPE=postgresql -ENV WEB_CONCURRENCY=auto ENV MAX_THREADS=5 EXPOSE 8080 -CMD bundle exec puma -C config/puma.rb -b tcp://0.0.0.0:8080 +CMD export WEB_CONCURRENCY=$(($(nproc)*5/4)) && \ + bundle exec puma -C config/puma.rb -b tcp://0.0.0.0:8080 diff --git a/frameworks/Ruby/sinatra-sequel/sinatra-sequel.dockerfile b/frameworks/Ruby/sinatra-sequel/sinatra-sequel.dockerfile index 73176d9bb86..acef81396e4 100644 --- a/frameworks/Ruby/sinatra-sequel/sinatra-sequel.dockerfile +++ b/frameworks/Ruby/sinatra-sequel/sinatra-sequel.dockerfile @@ -16,9 +16,9 @@ RUN bundle install --jobs=4 --gemfile=/sinatra-sequel/Gemfile ENV APP_ENV=production ENV DBTYPE=mysql -ENV WEB_CONCURRENCY=auto ENV MAX_THREADS=5 EXPOSE 8080 -CMD bundle exec puma -C config/puma.rb -b tcp://0.0.0.0:8080 +CMD export WEB_CONCURRENCY=$(($(nproc)*5/4)) && \ + bundle exec puma -C config/puma.rb -b tcp://0.0.0.0:8080 diff --git a/frameworks/Ruby/sinatra/sinatra-postgres.dockerfile b/frameworks/Ruby/sinatra/sinatra-postgres.dockerfile index 682ef3b7add..3b4f10f418b 100644 --- a/frameworks/Ruby/sinatra/sinatra-postgres.dockerfile +++ b/frameworks/Ruby/sinatra/sinatra-postgres.dockerfile @@ -16,7 +16,6 @@ RUN bundle install --jobs=4 --gemfile=/sinatra/Gemfile ENV APP_ENV=production ENV DBTYPE=postgresql -ENV WEB_CONCURRENCY=auto ENV MAX_THREADS=5 EXPOSE 8080 diff --git a/frameworks/Ruby/sinatra/sinatra.dockerfile b/frameworks/Ruby/sinatra/sinatra.dockerfile index c2aae524d0b..63faa010ca9 100644 --- a/frameworks/Ruby/sinatra/sinatra.dockerfile +++ b/frameworks/Ruby/sinatra/sinatra.dockerfile @@ -16,9 +16,9 @@ RUN bundle install --jobs=4 --gemfile=/sinatra/Gemfile ENV APP_ENV=production ENV DBTYPE=mysql -ENV WEB_CONCURRENCY=auto ENV MAX_THREADS=5 EXPOSE 8080 -CMD bundle exec puma -b tcp://0.0.0.0:8080 +CMD export WEB_CONCURRENCY=$(($(nproc)*5/4)) && \ + bundle exec puma -b tcp://0.0.0.0:8080 From c694a343c24d93f4ecd4b7792618e91bcd8c6ce4 Mon Sep 17 00:00:00 2001 From: Petrik de Heus Date: Sat, 3 Jan 2026 00:03:04 +0100 Subject: [PATCH 13/28] [ruby/rage] Remove logger from Gemfile (#10490) It is now included by rage. --- frameworks/Ruby/rage-sequel/Gemfile | 1 - 1 file changed, 1 deletion(-) diff --git a/frameworks/Ruby/rage-sequel/Gemfile b/frameworks/Ruby/rage-sequel/Gemfile index 9c1f97fe777..a6a7f3d8141 100644 --- a/frameworks/Ruby/rage-sequel/Gemfile +++ b/frameworks/Ruby/rage-sequel/Gemfile @@ -5,4 +5,3 @@ gem "rage-rb", "~> 1.19" gem "pg", "~> 1.0" gem 'sequel', '~> 5.0' gem 'sequel_pg', '~> 1.6', platforms: :ruby, require: false -gem 'logger' # required for ruby 3.5 From 6816c7ccbb43abc72938b0972ef6821744923f28 Mon Sep 17 00:00:00 2001 From: Petrik de Heus Date: Sat, 3 Jan 2026 00:03:19 +0100 Subject: [PATCH 14/28] [ruby/rage] Update ActiveRecord to 8.1 (#10491) --- frameworks/Ruby/rage/Gemfile | 2 +- frameworks/Ruby/rage/Gemfile.lock | 20 ++++++++++---------- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/frameworks/Ruby/rage/Gemfile b/frameworks/Ruby/rage/Gemfile index ef34fe5e670..6c300d6323a 100644 --- a/frameworks/Ruby/rage/Gemfile +++ b/frameworks/Ruby/rage/Gemfile @@ -3,7 +3,7 @@ source "https://rubygems.org" gem "rage-rb", "~> 1.19" gem "pg", "~> 1.0" -gem "activerecord", "~> 8.0.0", require: "active_record" +gem "activerecord", "~> 8.1.0", require: "active_record" # Build JSON APIs with ease # gem "alba" diff --git a/frameworks/Ruby/rage/Gemfile.lock b/frameworks/Ruby/rage/Gemfile.lock index df28b018da8..26bee8f63e9 100644 --- a/frameworks/Ruby/rage/Gemfile.lock +++ b/frameworks/Ruby/rage/Gemfile.lock @@ -1,33 +1,33 @@ GEM remote: https://rubygems.org/ specs: - activemodel (8.0.2) - activesupport (= 8.0.2) - activerecord (8.0.2) - activemodel (= 8.0.2) - activesupport (= 8.0.2) + activemodel (8.1.1) + activesupport (= 8.1.1) + activerecord (8.1.1) + activemodel (= 8.1.1) + activesupport (= 8.1.1) timeout (>= 0.4.0) - activesupport (8.0.2) + activesupport (8.1.1) base64 - benchmark (>= 0.3) bigdecimal concurrent-ruby (~> 1.0, >= 1.3.1) connection_pool (>= 2.2.5) drb i18n (>= 1.6, < 2) + json logger (>= 1.4.2) minitest (>= 5.1) securerandom (>= 0.3) tzinfo (~> 2.0, >= 2.0.5) uri (>= 0.13.1) base64 (0.2.0) - benchmark (0.4.0) bigdecimal (3.1.9) concurrent-ruby (1.3.5) connection_pool (2.5.0) drb (2.2.1) i18n (1.14.7) concurrent-ruby (~> 1.0) + json (2.18.0) logger (1.7.0) minitest (6.0.0) prism (~> 1.5) @@ -60,9 +60,9 @@ PLATFORMS x86_64-darwin-23 DEPENDENCIES - activerecord (~> 8.0.0) + activerecord (~> 8.1.0) pg (~> 1.0) rage-rb (~> 1.19) BUNDLED WITH - 4.0.3 + 4.0.3 From 1d21472ecd8d5e3b16665aad35506743c4d62267 Mon Sep 17 00:00:00 2001 From: Andrew McCloskey Date: Fri, 2 Jan 2026 18:03:53 -0500 Subject: [PATCH 15/28] vertx-web-kotlin-dsljson updates (#10492) --- .../vertx-web-kotlin-dsljson/build.gradle.kts | 16 ++++-- .../gradle.properties | 4 +- .../com/example/starter/db/WorldRepository.kt | 9 +-- .../starter/handlers/DefaultHandler.kt | 1 + .../com/example/starter/helpers/Properties.kt | 57 +------------------ 5 files changed, 20 insertions(+), 67 deletions(-) diff --git a/frameworks/Kotlin/vertx-web-kotlin-dsljson/build.gradle.kts b/frameworks/Kotlin/vertx-web-kotlin-dsljson/build.gradle.kts index f666562a841..6fc476870ac 100644 --- a/frameworks/Kotlin/vertx-web-kotlin-dsljson/build.gradle.kts +++ b/frameworks/Kotlin/vertx-web-kotlin-dsljson/build.gradle.kts @@ -1,10 +1,9 @@ -import nu.studer.gradle.rocker.RockerConfig +import java.net.URI +import java.nio.charset.StandardCharsets import org.jetbrains.kotlin.gradle.dsl.JvmDefaultMode import org.jetbrains.kotlin.gradle.dsl.JvmTarget import org.jetbrains.kotlin.gradle.dsl.KotlinVersion import org.jetbrains.kotlin.gradle.internal.KaptWithoutKotlincTask -import java.net.URI -import java.nio.charset.StandardCharsets plugins { alias(libs.plugins.kotlin.jvm) @@ -73,8 +72,12 @@ dependencies { // Log4j implementation(libs.log4j.core) + kapt(libs.log4j.core) + implementation(libs.log4j.api) implementation(libs.log4j.api.kotlin) + + // Disruptor implementation(libs.disruptor) // Rocker @@ -85,7 +88,7 @@ dependencies { rocker { version = libs.versions.rocker.asProvider().get() configurations { - create("main") { + create("main").apply { javaVersion = "25" templateDir = project.layout.projectDirectory.dir("src/main/resources/rocker") outputDir = project.layout.buildDirectory.dir("generated/source/rocker") @@ -171,7 +174,12 @@ tasks { } shadowJar { + mainClass = application.mainClass.get() archiveClassifier = "fat" mergeServiceFiles() + entryCompression = ZipEntryCompression.STORED + + exclude("META-INF/versions/**/module-info.class") + exclude("module-info.class") } } diff --git a/frameworks/Kotlin/vertx-web-kotlin-dsljson/gradle.properties b/frameworks/Kotlin/vertx-web-kotlin-dsljson/gradle.properties index f220152f873..762ba4008f7 100644 --- a/frameworks/Kotlin/vertx-web-kotlin-dsljson/gradle.properties +++ b/frameworks/Kotlin/vertx-web-kotlin-dsljson/gradle.properties @@ -2,9 +2,7 @@ org.gradle.daemon=true org.gradle.parallel=true org.gradle.caching=true org.gradle.configureondemand=true - -org.gradle.jvmargs=-Xms512m -Xmx4g -XX:+UseParallelGC -Dfile.encoding=UTF-8 -org.gradle.workers.max=8 +org.gradle.jvmargs=-Xms2g -Xmx4g -XX:MaxMetaspaceSize=512m -XX:+UseParallelGC -Dfile.encoding=UTF-8 kotlin.incremental=true kotlin.parallel.tasks.in.project=true diff --git a/frameworks/Kotlin/vertx-web-kotlin-dsljson/src/main/kotlin/com/example/starter/db/WorldRepository.kt b/frameworks/Kotlin/vertx-web-kotlin-dsljson/src/main/kotlin/com/example/starter/db/WorldRepository.kt index e12717e7228..a3ea7e4fc2b 100644 --- a/frameworks/Kotlin/vertx-web-kotlin-dsljson/src/main/kotlin/com/example/starter/db/WorldRepository.kt +++ b/frameworks/Kotlin/vertx-web-kotlin-dsljson/src/main/kotlin/com/example/starter/db/WorldRepository.kt @@ -12,7 +12,6 @@ import io.vertx.sqlclient.Tuple import io.vertx.sqlclient.impl.SqlClientInternal import io.vertx.sqlclient.internal.ArrayTuple import java.util.concurrent.ThreadLocalRandom -import java.util.concurrent.atomic.AtomicInteger @Suppress("NOTHING_TO_INLINE", "UNCHECKED_CAST") class WorldRepository private constructor( @@ -20,6 +19,7 @@ class WorldRepository private constructor( private val selectWorldQuery: PreparedQuery>, private val updateWorldQueries: Array>>, ) : AbstractRepository(conn) { + fun selectRandomWorld(): Future = selectWorldQuery .execute(Tuple.of(randomWorld())) .map { map(it.first()) } @@ -27,7 +27,7 @@ class WorldRepository private constructor( fun selectRandomWorlds(numWorlds: Int): Future> { val promise = Promise.promise>() val arr = arrayOfNulls(numWorlds) - val count = AtomicInteger(0) + var count = 0 (this.conn as SqlClientInternal).group { c -> val query = c.preparedQuery(SELECT_WORLD_SQL) repeat(numWorlds) { _ -> @@ -36,13 +36,13 @@ class WorldRepository private constructor( when { ar.succeeded() -> { val result = ar.result() - val index = count.getAndIncrement() + val index = count++ arr[index] = map(result.iterator().next()) if (index == numWorlds - 1) { promise.complete(arr as Array) } } - else -> promise.fail(ar.cause()) + else -> promise.tryFail(ar.cause()) } } } @@ -68,6 +68,7 @@ class WorldRepository private constructor( private const val SELECT_WORLD_SQL = "SELECT id, randomnumber FROM world WHERE id = $1" private inline fun randomWorld(): Int = 1 + ThreadLocalRandom.current().nextInt(10_000) + private inline fun map(row: Row): World = World( row.getInteger(0), row.getInteger(1), diff --git a/frameworks/Kotlin/vertx-web-kotlin-dsljson/src/main/kotlin/com/example/starter/handlers/DefaultHandler.kt b/frameworks/Kotlin/vertx-web-kotlin-dsljson/src/main/kotlin/com/example/starter/handlers/DefaultHandler.kt index 7f981320192..0b527148a7a 100644 --- a/frameworks/Kotlin/vertx-web-kotlin-dsljson/src/main/kotlin/com/example/starter/handlers/DefaultHandler.kt +++ b/frameworks/Kotlin/vertx-web-kotlin-dsljson/src/main/kotlin/com/example/starter/handlers/DefaultHandler.kt @@ -6,6 +6,7 @@ import io.vertx.core.buffer.Buffer import io.vertx.core.http.HttpServerRequest class DefaultHandler : AbstractHandler() { + fun plaintext(req: HttpServerRequest): Future = req .response().apply { headers().setAll(PeriodicResolver.plaintext) diff --git a/frameworks/Kotlin/vertx-web-kotlin-dsljson/src/main/kotlin/com/example/starter/helpers/Properties.kt b/frameworks/Kotlin/vertx-web-kotlin-dsljson/src/main/kotlin/com/example/starter/helpers/Properties.kt index 7098ddf822a..6f0d07767b1 100644 --- a/frameworks/Kotlin/vertx-web-kotlin-dsljson/src/main/kotlin/com/example/starter/helpers/Properties.kt +++ b/frameworks/Kotlin/vertx-web-kotlin-dsljson/src/main/kotlin/com/example/starter/helpers/Properties.kt @@ -26,67 +26,12 @@ object Properties { */ val EVENT_LOOP_POOL_SIZE: Int = SystemPropertyUtil.getInt("tfb.eventLoopPoolSize", CpuCoreSensor.availableProcessors()) - /** - * Whether metrics are enabled. - * Default: Reverse of `vertx.disableMetrics` (defaults to true) - */ - val METRICS_ENABLED: Boolean = SystemPropertyUtil.getBoolean("vertx.disableMetrics", true).not() - /** * Port the HTTP server listens on. * Default: 8080 (tfb.http.port) */ val HTTP_PORT: Int = SystemPropertyUtil.getInt("tfb.http.port", 8080) - /** - * Size of TCP send buffer for HTTP connections, in bytes. - * Default: 32768 (tfb.http.sendBufferSize) - */ - val HTTP_SEND_BUFFER_SIZE: Int = SystemPropertyUtil.getInt("tfb.http.sendBufferSize", 256 * 1024) - - /** - * Size of TCP receive buffer for HTTP connections, in bytes. - * Default: 32768 (tfb.http.receiveBufferSize) - */ - val HTTP_RECEIVE_BUFFER_SIZE: Int = SystemPropertyUtil.getInt("tfb.http.receiveBufferSize", 256 * 1024) - - /** - * Enables TCP Fast Open on the HTTP server. - * Default: true (tfb.http.tcpFastOpen) - */ - val HTTP_TCP_FASTOPEN: Boolean = SystemPropertyUtil.getBoolean("tfb.http.tcpFastOpen", false) - - /** - * Enables TCP_NODELAY (disables Nagle) on HTTP connections. - * Default: true (tfb.http.tcpNoDelay) - */ - val HTTP_TCP_NODELAY: Boolean = SystemPropertyUtil.getBoolean("tfb.http.tcpNoDelay", false) - - /** - * Idle timeout for HTTP connections in seconds. - * 0 disables idle timeout. - * Default: 0 (tfb.http.idleTimeout) - */ - val HTTP_IDLE_TIMEOUT: Int = SystemPropertyUtil.getInt("tfb.http.idleTimeout", 0) - - /** - * Enables SO_REUSEADDR on the HTTP server socket. - * Default: true (tfb.http.reuseAddress) - */ - val HTTP_REUSE_ADDRESS: Boolean = SystemPropertyUtil.getBoolean("tfb.http.reuseAddress", true) - - /** - * Enables SO_REUSEPORT on the HTTP server socket. - * Default: true (tfb.http.reusePort) - */ - val HTTP_REUSE_PORT: Boolean = SystemPropertyUtil.getBoolean("tfb.http.reusePort", true) - - /** - * Size of the TCP accept backlog for the HTTP server. - * Default: 8192 (tfb.http.acceptBacklog) - */ - val HTTP_ACCEPT_BACKLOG: Int = SystemPropertyUtil.getInt("tfb.http.acceptBacklog", 8192) - /** * PostgreSQL username used for connections. * Default: benchmarkdbuser (tfb.pg.user) @@ -157,7 +102,7 @@ object Properties { cachePreparedStatements = PG_CACHE_PREPARED_STATEMENTS, preparedStatementCacheMaxSize = PG_PREPARED_STATEMENT_CACHE_MAX_SIZE, tracingPolicy = TracingPolicy.IGNORE, - pipeliningLimit = PG_PIPELINING_LIMIT + pipeliningLimit = PG_PIPELINING_LIMIT, ) } } From ba197629ec0473b5eec04120fcf0f598e69e681c Mon Sep 17 00:00:00 2001 From: Francesco Iapicca Date: Sat, 3 Jan 2026 01:04:28 +0200 Subject: [PATCH 16/28] Dart3 update (#10493) * add logic for variable --define=MAX_ISOLATES * add run.sh and optimize scaling logic in Dockerfile * bump dart and dependencies version everywhere --- frameworks/Dart/dart3/README.md | 8 ++++---- frameworks/Dart/dart3/bin/server.dart | 10 +++++++++- frameworks/Dart/dart3/dart3.dockerfile | 26 +++++++++++++++++++------- frameworks/Dart/dart3/pubspec.yaml | 4 ++-- frameworks/Dart/dart3/run.sh | 18 ++++++++++++++++++ 5 files changed, 52 insertions(+), 14 deletions(-) create mode 100644 frameworks/Dart/dart3/run.sh diff --git a/frameworks/Dart/dart3/README.md b/frameworks/Dart/dart3/README.md index 7152e705637..ec6fba3cdaa 100644 --- a/frameworks/Dart/dart3/README.md +++ b/frameworks/Dart/dart3/README.md @@ -1,6 +1,6 @@ # Dart 3 Benchmarking Test -### Test Type Implementation Source Code +## Test Type Implementation Source Code - [JSON](server.dart) - [PLAINTEXT](server.dart) @@ -9,14 +9,14 @@ The tests were run with: -- [Dart v3.4.4](https://dart.dev/) +- [Dart v3.10.7](https://dart.dev/) ## Test URLs ### JSON -http://localhost:8080/json +`http://localhost:8080/json` ### PLAINTEXT -http://localhost:8080/plaintext +`http://localhost:8080/plaintext` diff --git a/frameworks/Dart/dart3/bin/server.dart b/frameworks/Dart/dart3/bin/server.dart index 5859cc51f82..7a512169dd4 100755 --- a/frameworks/Dart/dart3/bin/server.dart +++ b/frameworks/Dart/dart3/bin/server.dart @@ -3,9 +3,17 @@ import 'dart:io'; import 'dart:isolate'; void main(List args) async { + /// Isolate count per process, set at build-time via: + /// dart compile exe --define=MAX_ISOLATES=X + /// Defaults to machine core count for dynamic scaling. + final maxIsolates = int.fromEnvironment( + 'MAX_ISOLATES', + defaultValue: Platform.numberOfProcessors, + ); + /// Create an [Isolate] containing an [HttpServer] /// for each processor after the first - for (var i = 1; i < Platform.numberOfProcessors; i++) { + for (var i = 1; i < maxIsolates; i++) { await Isolate.spawn(_startServer, args); } diff --git a/frameworks/Dart/dart3/dart3.dockerfile b/frameworks/Dart/dart3/dart3.dockerfile index 812b7e959ee..ed5f060df90 100644 --- a/frameworks/Dart/dart3/dart3.dockerfile +++ b/frameworks/Dart/dart3/dart3.dockerfile @@ -1,14 +1,26 @@ -FROM dart:3.8 AS builder - -COPY . /app +FROM dart:3.10.7 AS builder WORKDIR /app + +# Define the build-time argument (Default to 8) +ARG MAX_ISOLATES=8 +COPY . . RUN mkdir build -RUN dart compile exe ./bin/server.dart -o build/server +RUN dart compile exe bin/server.dart \ + --define=MAX_ISOLATES=${MAX_ISOLATES} \ + -o build/server + +FROM busybox:glibc + +# Re-declare ARG in the second stage to use it in ENV +# Define the build-time argument (Default to 8) +ARG MAX_ISOLATES=8 +ENV MAX_ISOLATES_PER_PROCESS=${MAX_ISOLATES} -FROM scratch COPY --from=builder /runtime/ / -COPY --from=builder /app/build /bin +COPY --from=builder /app/build/server /bin/server +COPY run.sh /bin/run.sh +RUN chmod +x /bin/run.sh EXPOSE 8080 -CMD ["server"] +CMD ["/bin/run.sh"] \ No newline at end of file diff --git a/frameworks/Dart/dart3/pubspec.yaml b/frameworks/Dart/dart3/pubspec.yaml index 5a99e258055..45a6b44ddc6 100644 --- a/frameworks/Dart/dart3/pubspec.yaml +++ b/frameworks/Dart/dart3/pubspec.yaml @@ -1,7 +1,7 @@ name: dartbenchmark description: A benchmark of dart environment: - sdk: ^3.8.0 + sdk: ^3.10.7 dev_dependencies: - lints: ^4.0.0 + lints: ^6.0.0 diff --git a/frameworks/Dart/dart3/run.sh b/frameworks/Dart/dart3/run.sh new file mode 100644 index 00000000000..767d14c5451 --- /dev/null +++ b/frameworks/Dart/dart3/run.sh @@ -0,0 +1,18 @@ +#!/bin/sh +# Detect CPU threads from the system +TOTAL_CORES=$(grep -c ^processor /proc/cpuinfo) + +# This comes from the ENV in the Dockerfile +MAX_ISO=${MAX_ISOLATES_PER_PROCESS} + +# Calculate OS processes needed +NUM_WORKERS=$((TOTAL_CORES / MAX_ISO)) +if [ "$NUM_WORKERS" -le 0 ]; then NUM_WORKERS=1; fi + +echo "Scaling: $TOTAL_CORES cores / $MAX_ISO isolates = $NUM_WORKERS processes" + +for i in $(seq 1 $NUM_WORKERS); do + /bin/server & +done + +wait \ No newline at end of file From ed0ecd70fa566be08ae4366db36dd3524f2c6ad4 Mon Sep 17 00:00:00 2001 From: Petrik de Heus Date: Sat, 3 Jan 2026 00:04:47 +0100 Subject: [PATCH 17/28] [ruby/rails] Remove references to Agoo (#10489) Rails is no longer tested with Agoo. --- frameworks/Ruby/rails/app/controllers/concerns/date_header.rb | 2 +- frameworks/Ruby/rails/config/routes.rb | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/frameworks/Ruby/rails/app/controllers/concerns/date_header.rb b/frameworks/Ruby/rails/app/controllers/concerns/date_header.rb index d314038144c..7beeb3a9fc7 100644 --- a/frameworks/Ruby/rails/app/controllers/concerns/date_header.rb +++ b/frameworks/Ruby/rails/app/controllers/concerns/date_header.rb @@ -2,7 +2,7 @@ module DateHeader extend ActiveSupport::Concern included do - if defined?(Agoo) || defined?(Falcon) || defined?(Puma) + if defined?(Falcon) || defined?(Puma) before_action :add_header end end diff --git a/frameworks/Ruby/rails/config/routes.rb b/frameworks/Ruby/rails/config/routes.rb index 22c47dc8704..1987aabc219 100644 --- a/frameworks/Ruby/rails/config/routes.rb +++ b/frameworks/Ruby/rails/config/routes.rb @@ -1,7 +1,7 @@ Rails.application.routes.draw do # For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html - JsonApp = if defined?(Falcon) || defined?(Puma) || defined?(Agoo) + JsonApp = if defined?(Falcon) || defined?(Puma) ->(env) do [200, { @@ -22,7 +22,7 @@ end end - PlaintextApp = if defined?(Falcon) || defined?(Puma) || defined?(Agoo) + PlaintextApp = if defined?(Falcon) || defined?(Puma) ->(env) do [200, { From 8598b58d8a15827e4f028e2958d6a43df26d23e2 Mon Sep 17 00:00:00 2001 From: iapicca Date: Sat, 3 Jan 2026 18:58:16 +0200 Subject: [PATCH 18/28] mv .dockarfile under dart3 and update dart3 benchmark_config --- frameworks/Dart/dart3/benchmark_config.json | 20 ++++++++++++++ .../{dart3_aot => dart3}/dart3_aot.dockerfile | 0 frameworks/Dart/dart3_aot/.dockerignore | 9 ------- frameworks/Dart/dart3_aot/.gitignore | 5 ---- .../Dart/dart3_aot/analysis_options.yaml | 1 - .../Dart/dart3_aot/benchmark_config.json | 26 ------------------- frameworks/Dart/dart3_aot/pubspec.yaml | 7 ----- 7 files changed, 20 insertions(+), 48 deletions(-) rename frameworks/Dart/{dart3_aot => dart3}/dart3_aot.dockerfile (100%) delete mode 100644 frameworks/Dart/dart3_aot/.dockerignore delete mode 100644 frameworks/Dart/dart3_aot/.gitignore delete mode 100644 frameworks/Dart/dart3_aot/analysis_options.yaml delete mode 100644 frameworks/Dart/dart3_aot/benchmark_config.json delete mode 100644 frameworks/Dart/dart3_aot/pubspec.yaml diff --git a/frameworks/Dart/dart3/benchmark_config.json b/frameworks/Dart/dart3/benchmark_config.json index 059fb368d0e..76114bc99aa 100644 --- a/frameworks/Dart/dart3/benchmark_config.json +++ b/frameworks/Dart/dart3/benchmark_config.json @@ -21,6 +21,26 @@ "notes": "", "versus": "None" } + },{ + "aot": { + "json_url": "/json", + "plaintext_url": "/plaintext", + "port": 8080, + "approach": "Stripped", + "classification": "Platform", + "database": "None", + "framework": "None", + "language": "Dart", + "flavor": "None", + "orm": "None", + "platform": "None", + "webserver": "None", + "os": "Linux", + "database_os": "Linux", + "display_name": "dart3_aot", + "notes": "", + "versus": "None" + } } ] } diff --git a/frameworks/Dart/dart3_aot/dart3_aot.dockerfile b/frameworks/Dart/dart3/dart3_aot.dockerfile similarity index 100% rename from frameworks/Dart/dart3_aot/dart3_aot.dockerfile rename to frameworks/Dart/dart3/dart3_aot.dockerfile diff --git a/frameworks/Dart/dart3_aot/.dockerignore b/frameworks/Dart/dart3_aot/.dockerignore deleted file mode 100644 index 6a6cc8727a7..00000000000 --- a/frameworks/Dart/dart3_aot/.dockerignore +++ /dev/null @@ -1,9 +0,0 @@ -# From https://hub.docker.com/_/dart -.dockerignore -Dockerfile -build/ -.dart_tool/ -.git/ -.github/ -.gitignore -.packages diff --git a/frameworks/Dart/dart3_aot/.gitignore b/frameworks/Dart/dart3_aot/.gitignore deleted file mode 100644 index 27fe9f77a4b..00000000000 --- a/frameworks/Dart/dart3_aot/.gitignore +++ /dev/null @@ -1,5 +0,0 @@ -# https://dart.dev/guides/libraries/private-files -# Created by `dart pub` -.dart_tool/ -*.lock -!bin diff --git a/frameworks/Dart/dart3_aot/analysis_options.yaml b/frameworks/Dart/dart3_aot/analysis_options.yaml deleted file mode 100644 index 572dd239d09..00000000000 --- a/frameworks/Dart/dart3_aot/analysis_options.yaml +++ /dev/null @@ -1 +0,0 @@ -include: package:lints/recommended.yaml diff --git a/frameworks/Dart/dart3_aot/benchmark_config.json b/frameworks/Dart/dart3_aot/benchmark_config.json deleted file mode 100644 index b2b7412ef28..00000000000 --- a/frameworks/Dart/dart3_aot/benchmark_config.json +++ /dev/null @@ -1,26 +0,0 @@ -{ - "framework": "dart3_aot", - "tests": [ - { - "default": { - "json_url": "/json", - "plaintext_url": "/plaintext", - "port": 8080, - "approach": "Stripped", - "classification": "Platform", - "database": "None", - "framework": "None", - "language": "Dart", - "flavor": "None", - "orm": "None", - "platform": "None", - "webserver": "None", - "os": "Linux", - "database_os": "Linux", - "display_name": "dart3_aot", - "notes": "", - "versus": "None" - } - } - ] -} diff --git a/frameworks/Dart/dart3_aot/pubspec.yaml b/frameworks/Dart/dart3_aot/pubspec.yaml deleted file mode 100644 index 3c6591c0c7f..00000000000 --- a/frameworks/Dart/dart3_aot/pubspec.yaml +++ /dev/null @@ -1,7 +0,0 @@ -name: dart3_aot_benchmark -description: A benchmark of dart -environment: - sdk: ^3.10.3 - -dev_dependencies: - lints: ^6.0.0 \ No newline at end of file From 373d733b71b17c8512c51e1c882ca19f7481ecaf Mon Sep 17 00:00:00 2001 From: iapicca Date: Sat, 3 Jan 2026 20:07:33 +0200 Subject: [PATCH 19/28] include AOT horizontal scaling logic --- frameworks/Dart/dart3/bin/server.dart | 61 ++++++++++++++++++++++++--- 1 file changed, 54 insertions(+), 7 deletions(-) diff --git a/frameworks/Dart/dart3/bin/server.dart b/frameworks/Dart/dart3/bin/server.dart index 7a512169dd4..0e6ef8259ce 100755 --- a/frameworks/Dart/dart3/bin/server.dart +++ b/frameworks/Dart/dart3/bin/server.dart @@ -1,15 +1,62 @@ import 'dart:convert'; import 'dart:io'; import 'dart:isolate'; +import 'dart:math' show min; + +/// Environment declarations are evaluated at compile-time. Use 'const' to +/// ensure values are baked into AOT/Native binaries for the benchmark. +/// +/// From https://api.dart.dev/dart-core/int/int.fromEnvironment.html: +/// "This constructor is only guaranteed to work when invoked as const. +/// It may work as a non-constant invocation on some platforms +/// which have access to compiler options at run-time, +/// but most ahead-of-time compiled platforms will not have this information." +const _maxIsolatesfromEnvironment = int.fromEnvironment('MAX_ISOLATES'); void main(List args) async { - /// Isolate count per process, set at build-time via: - /// dart compile exe --define=MAX_ISOLATES=X - /// Defaults to machine core count for dynamic scaling. - final maxIsolates = int.fromEnvironment( - 'MAX_ISOLATES', - defaultValue: Platform.numberOfProcessors, - ); + /// Defines local isolate quota, using MAX_ISOLATES if provided. + /// Falls back to total available cores while respecting hardware limits. + var maxIsolates = _maxIsolatesfromEnvironment > 0 + ? min(_maxIsolatesfromEnvironment, Platform.numberOfProcessors) + : Platform.numberOfProcessors; + + ///Triggers process-level horizontal scaling when running in AOT. + if (Platform.script.toFilePath().endsWith('.aot')) { + /// Internal token used to notify newly spawned processes that they + /// belong to a secondary "worker group". + const workerGroupTag = '--workerGroup'; + + /// Determine if this process instance was initialized as a worker group. + final isWorkerGroup = args.contains(workerGroupTag); + if (isWorkerGroup) { + /// Sanitize the argument list to ensure the internal token does not + /// interfere with application-level argument parsing. + args.removeAt(args.indexOf(workerGroupTag)); + } + + ///Prevents recursive spawning + ///by ensuring only the primary process can spawn worker groups + if (!isWorkerGroup) { + /// Calculate the number of secondary worker groups required + /// to fully utilize the available hardware capacity. + /// + /// Each group serves as a container for multiple isolates, + /// helping to bypass internal VM scaling bottlenecks. + final workerGroups = Platform.numberOfProcessors ~/ maxIsolates - 1; + + ///Bootstraps independent worker processes via AOT snapshots. + ///Each process initializes its own Isolate Group. + for (var i = 0; i < workerGroups; i++) { + /// [Platform.script] identifies the AOT snapshot or executable. + /// [Isolate.spawnUri] spawns a new process group via [main()]. + Isolate.spawnUri(Platform.script, [workerGroupTag, ...args], null); + } + + /// Updates local isolate limits, assigning the primary group + /// the remaining cores after worker group allocation. + maxIsolates = Platform.numberOfProcessors - workerGroups * maxIsolates; + } + } /// Create an [Isolate] containing an [HttpServer] /// for each processor after the first From 6a66ad285a7e7ae72ba93b5b3888be0046c86725 Mon Sep 17 00:00:00 2001 From: iapicca Date: Sat, 3 Jan 2026 20:18:55 +0200 Subject: [PATCH 20/28] update dart3_aot.dockerfile to include MAX_ISOLATES arg --- frameworks/Dart/dart3/dart3_aot.dockerfile | 22 +++++++++------------- 1 file changed, 9 insertions(+), 13 deletions(-) diff --git a/frameworks/Dart/dart3/dart3_aot.dockerfile b/frameworks/Dart/dart3/dart3_aot.dockerfile index 3f15d1c657d..709d4c2af9c 100644 --- a/frameworks/Dart/dart3/dart3_aot.dockerfile +++ b/frameworks/Dart/dart3/dart3_aot.dockerfile @@ -1,27 +1,23 @@ -# ---------- Build stage ---------- -FROM dart:stable AS build - +FROM dart:3.10.7 AS build WORKDIR /app -COPY pubspec.yaml . -RUN dart pub get +# Define the build-time argument (Default to 8) +ARG MAX_ISOLATES=8 +COPY pubspec.yaml . COPY bin bin -RUN dart compile aot-snapshot bin/server.dart -o server.aot - +RUN dart pub get +RUN dart compile aot-snapshot bin/server.dart \ + --define=MAX_ISOLATES=${MAX_ISOLATES} \ + -o server.aot -# ---------- Runtime stage ---------- FROM gcr.io/distroless/base-debian12 +WORKDIR /app -# Copy Dart AOT runtime COPY --from=build /usr/lib/dart/bin/dartaotruntime /usr/lib/dart/bin/dartaotruntime - -# Copy snapshot COPY --from=build /app/server.aot /app/server.aot -WORKDIR /app - EXPOSE 8080 # Distroless requires absolute paths From 52806e24d0954c8ac4f74163fabea7a894927c75 Mon Sep 17 00:00:00 2001 From: iapicca Date: Sat, 3 Jan 2026 20:27:22 +0200 Subject: [PATCH 21/28] align dart3. dart3_aot. dockerfile(s), and update run.sh --- frameworks/Dart/dart3/dart3.dockerfile | 19 ++-- frameworks/Dart/dart3/dart3_aot.dockerfile | 2 +- frameworks/Dart/dart3/run.sh | 6 +- frameworks/Dart/dart3_aot/bin/server.dart | 119 --------------------- 4 files changed, 15 insertions(+), 131 deletions(-) delete mode 100755 frameworks/Dart/dart3_aot/bin/server.dart diff --git a/frameworks/Dart/dart3/dart3.dockerfile b/frameworks/Dart/dart3/dart3.dockerfile index ed5f060df90..278eedcc0a3 100644 --- a/frameworks/Dart/dart3/dart3.dockerfile +++ b/frameworks/Dart/dart3/dart3.dockerfile @@ -1,25 +1,28 @@ -FROM dart:3.10.7 AS builder +FROM dart:3.10.7 AS build WORKDIR /app # Define the build-time argument (Default to 8) ARG MAX_ISOLATES=8 -COPY . . -RUN mkdir build + +COPY pubspec.yaml . +COPY bin bin + RUN dart compile exe bin/server.dart \ --define=MAX_ISOLATES=${MAX_ISOLATES} \ - -o build/server + -o server FROM busybox:glibc +WORKDIR /app -# Re-declare ARG in the second stage to use it in ENV -# Define the build-time argument (Default to 8) +# Re-declare ARG 'MAX_ISOLATES' in the second stage to use it in ENV ARG MAX_ISOLATES=8 ENV MAX_ISOLATES_PER_PROCESS=${MAX_ISOLATES} -COPY --from=builder /runtime/ / -COPY --from=builder /app/build/server /bin/server +COPY --from=build /runtime/ / +COPY --from=build /app/server /app/server COPY run.sh /bin/run.sh + RUN chmod +x /bin/run.sh EXPOSE 8080 diff --git a/frameworks/Dart/dart3/dart3_aot.dockerfile b/frameworks/Dart/dart3/dart3_aot.dockerfile index 709d4c2af9c..bfe70a492de 100644 --- a/frameworks/Dart/dart3/dart3_aot.dockerfile +++ b/frameworks/Dart/dart3/dart3_aot.dockerfile @@ -1,3 +1,4 @@ + FROM dart:3.10.7 AS build WORKDIR /app @@ -7,7 +8,6 @@ ARG MAX_ISOLATES=8 COPY pubspec.yaml . COPY bin bin -RUN dart pub get RUN dart compile aot-snapshot bin/server.dart \ --define=MAX_ISOLATES=${MAX_ISOLATES} \ -o server.aot diff --git a/frameworks/Dart/dart3/run.sh b/frameworks/Dart/dart3/run.sh index 767d14c5451..e04fa806800 100644 --- a/frameworks/Dart/dart3/run.sh +++ b/frameworks/Dart/dart3/run.sh @@ -9,10 +9,10 @@ MAX_ISO=${MAX_ISOLATES_PER_PROCESS} NUM_WORKERS=$((TOTAL_CORES / MAX_ISO)) if [ "$NUM_WORKERS" -le 0 ]; then NUM_WORKERS=1; fi -echo "Scaling: $TOTAL_CORES cores / $MAX_ISO isolates = $NUM_WORKERS processes" - +# Bootstrap the calculated number of independent Dart processes. for i in $(seq 1 $NUM_WORKERS); do - /bin/server & + /app/server & done +# Keep the shell alive to manage the backgrounded process group. wait \ No newline at end of file diff --git a/frameworks/Dart/dart3_aot/bin/server.dart b/frameworks/Dart/dart3_aot/bin/server.dart deleted file mode 100755 index b492b829c5a..00000000000 --- a/frameworks/Dart/dart3_aot/bin/server.dart +++ /dev/null @@ -1,119 +0,0 @@ -import 'dart:convert'; -import 'dart:io'; -import 'dart:isolate'; - -/// The maximum number of isolates managed by a single OS process group. -const _isolatesPerGroup = 8; - -/// Internal token used to notify newly spawned processes that they -/// belong to a secondary "worker group". -const _workerGroupTag = '--workerGroup'; - -void main(List args) async { - /// Determine if this process instance was initialized as a worker group. - final isWorkerGroup = args.contains(_workerGroupTag); - if (isWorkerGroup) { - /// Sanitize the argument list to ensure the internal token does not - /// interfere with application-level argument parsing. - args.removeAt(args.indexOf(_workerGroupTag)); - } - - /// Calculate the number of secondary worker groups required - /// to fully utilize the available hardware capacity. - /// - /// Each group serves as a container for multiple isolates, - /// helping to bypass internal VM scaling bottlenecks. - final workerGroups = Platform.numberOfProcessors ~/ _isolatesPerGroup - 1; - if (!isWorkerGroup) { - for (var i = 0; i < workerGroups; i++) { - /// [Platform.script] identifies the AOT snapshot or executable. - /// [Isolate.spawnUri] bootstraps an entirely new group by re-executing [main()]. - Isolate.spawnUri(Platform.script, [_workerGroupTag], null); - } - } - - /// Determine the isolate quota for the current group. - /// Secondary worker groups run a full set defined by [_isolatesPerGroup]; - /// the primary group manages the remaining available cores. - final currentGroupIsolates = isWorkerGroup - ? _isolatesPerGroup - : Platform.numberOfProcessors - workerGroups * _isolatesPerGroup; - - /// Create an [Isolate] for the "Local Group" containing an [HttpServer] - /// for each processor available in this group after the first - for (var i = 1; i < currentGroupIsolates; i++) { - await Isolate.spawn(_startServer, args); - } - - /// Initialize the server instance for the group's lead isolate. - await _startServer(args); -} - -/// Creates and setup a [HttpServer] -Future _startServer(List args) async { - /// Binds the [HttpServer] on `0.0.0.0:8080`. - final server = await HttpServer.bind( - InternetAddress.anyIPv4, - 8080, - shared: true, - ); - - /// Sets [HttpServer]'s [serverHeader]. - server - ..defaultResponseHeaders.clear() - ..serverHeader = 'dart'; - - /// Handles [HttpRequest]'s from [HttpServer]. - await for (final request in server) { - switch (request.uri.path) { - case '/json': - _jsonTest(request); - break; - case '/plaintext': - _plaintextTest(request); - break; - default: - _sendResponse(request, HttpStatus.notFound); - } - } -} - -/// Completes the given [request] by writing the [bytes] with the given -/// [statusCode] and [type]. -void _sendResponse( - HttpRequest request, - int statusCode, { - ContentType? type, - List bytes = const [], -}) => request.response - ..statusCode = statusCode - ..headers.contentType = type - ..headers.date = DateTime.now() - ..contentLength = bytes.length - ..add(bytes) - ..close(); - -/// Completes the given [request] by writing the [response] as JSON. -void _sendJson(HttpRequest request, Object response) => _sendResponse( - request, - HttpStatus.ok, - type: ContentType.json, - bytes: _jsonEncoder.convert(response), -); - -/// Completes the given [request] by writing the [response] as plain text. -void _sendText(HttpRequest request, String response) => _sendResponse( - request, - HttpStatus.ok, - type: ContentType.text, - bytes: utf8.encode(response), -); - -/// Responds with the JSON test to the [request]. -void _jsonTest(HttpRequest request) => - _sendJson(request, const {'message': 'Hello, World!'}); - -/// Responds with the plaintext test to the [request]. -void _plaintextTest(HttpRequest request) => _sendText(request, 'Hello, World!'); - -final _jsonEncoder = JsonUtf8Encoder(); From 5c0b657bb9c19bbb78422f7de13c3c0c223f95b8 Mon Sep 17 00:00:00 2001 From: iapicca Date: Sat, 3 Jan 2026 20:29:48 +0200 Subject: [PATCH 22/28] clean up comments formatting in server.dart --- frameworks/Dart/dart3/bin/server.dart | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/frameworks/Dart/dart3/bin/server.dart b/frameworks/Dart/dart3/bin/server.dart index 0e6ef8259ce..5a31c189e7c 100755 --- a/frameworks/Dart/dart3/bin/server.dart +++ b/frameworks/Dart/dart3/bin/server.dart @@ -20,7 +20,7 @@ void main(List args) async { ? min(_maxIsolatesfromEnvironment, Platform.numberOfProcessors) : Platform.numberOfProcessors; - ///Triggers process-level horizontal scaling when running in AOT. + /// Triggers process-level horizontal scaling when running in AOT. if (Platform.script.toFilePath().endsWith('.aot')) { /// Internal token used to notify newly spawned processes that they /// belong to a secondary "worker group". @@ -34,8 +34,8 @@ void main(List args) async { args.removeAt(args.indexOf(workerGroupTag)); } - ///Prevents recursive spawning - ///by ensuring only the primary process can spawn worker groups + /// Prevents recursive spawning + /// by ensuring only the primary process can spawn worker groups if (!isWorkerGroup) { /// Calculate the number of secondary worker groups required /// to fully utilize the available hardware capacity. @@ -44,8 +44,8 @@ void main(List args) async { /// helping to bypass internal VM scaling bottlenecks. final workerGroups = Platform.numberOfProcessors ~/ maxIsolates - 1; - ///Bootstraps independent worker processes via AOT snapshots. - ///Each process initializes its own Isolate Group. + /// Bootstraps independent worker processes via AOT snapshots. + /// Each process initializes its own Isolate Group. for (var i = 0; i < workerGroups; i++) { /// [Platform.script] identifies the AOT snapshot or executable. /// [Isolate.spawnUri] spawns a new process group via [main()]. From 3ee3850548dc6a58c6376a6329290292026537e3 Mon Sep 17 00:00:00 2001 From: iapicca Date: Sat, 3 Jan 2026 20:30:43 +0200 Subject: [PATCH 23/28] delete dart3_aot folder --- frameworks/Dart/dart3_aot/README.md | 26 -------------------------- 1 file changed, 26 deletions(-) delete mode 100644 frameworks/Dart/dart3_aot/README.md diff --git a/frameworks/Dart/dart3_aot/README.md b/frameworks/Dart/dart3_aot/README.md deleted file mode 100644 index 3f82485c9a4..00000000000 --- a/frameworks/Dart/dart3_aot/README.md +++ /dev/null @@ -1,26 +0,0 @@ -# Dart 3 AOT Benchmarking Test - -## Test Type Implementation Source Code - -- [JSON](server.dart) -- [PLAINTEXT](server.dart) - -## Important Libraries - -The tests were run with: - -- [Dart v3.10.3](https://dart.dev/) - -## Test URLs - -### JSON - -`http://localhost:8080/json` - -### PLAINTEXT - -`http://localhost:8080/plaintext` - -## Why testing AOT? - -In the current version Dart, when compiled to a self-contained executable, cannot fully take advantage of all the available threads available in TechEmpower Web Framework Benchmarks' [environment](https://www.techempower.com/benchmarks/#section=environment), see this [issue](https://github.com/dart-lang/sdk/issues/60815) for more details. From 9b726cd4421194e896a1ad76212db0e6b22bf42a Mon Sep 17 00:00:00 2001 From: iapicca Date: Sat, 3 Jan 2026 20:48:41 +0200 Subject: [PATCH 24/28] renaming .dockerfile dart3_aot to dart3-aot to make the CI happy --- .../Dart/dart3/{dart3_aot.dockerfile => dart3-aot.dockerfile} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename frameworks/Dart/dart3/{dart3_aot.dockerfile => dart3-aot.dockerfile} (100%) diff --git a/frameworks/Dart/dart3/dart3_aot.dockerfile b/frameworks/Dart/dart3/dart3-aot.dockerfile similarity index 100% rename from frameworks/Dart/dart3/dart3_aot.dockerfile rename to frameworks/Dart/dart3/dart3-aot.dockerfile From f6f8885b25ce118384631c36e82b0ff836265e9b Mon Sep 17 00:00:00 2001 From: iapicca Date: Sat, 3 Jan 2026 20:57:15 +0200 Subject: [PATCH 25/28] update benchmark_config 'default' test and 'display_name's --- frameworks/Dart/dart3/benchmark_config.json | 29 ++++++--------------- 1 file changed, 8 insertions(+), 21 deletions(-) diff --git a/frameworks/Dart/dart3/benchmark_config.json b/frameworks/Dart/dart3/benchmark_config.json index 76114bc99aa..34504911a96 100644 --- a/frameworks/Dart/dart3/benchmark_config.json +++ b/frameworks/Dart/dart3/benchmark_config.json @@ -2,45 +2,32 @@ "framework": "dart3", "tests": [ { - "default": { + "dart3": { + "display_name": "dart3_native", "json_url": "/json", "plaintext_url": "/plaintext", "port": 8080, "approach": "Stripped", "classification": "Platform", "database": "None", - "framework": "None", "language": "Dart", - "flavor": "None", - "orm": "None", - "platform": "None", - "webserver": "None", "os": "Linux", - "database_os": "Linux", - "display_name": "dart3", - "notes": "", - "versus": "None" + "database_os": "Linux" } - },{ + }, + { "aot": { + "display_name": "dart3_aot", "json_url": "/json", "plaintext_url": "/plaintext", "port": 8080, "approach": "Stripped", "classification": "Platform", "database": "None", - "framework": "None", "language": "Dart", - "flavor": "None", - "orm": "None", - "platform": "None", - "webserver": "None", "os": "Linux", - "database_os": "Linux", - "display_name": "dart3_aot", - "notes": "", - "versus": "None" + "database_os": "Linux" } } ] -} +} \ No newline at end of file From 709848952c6adb8b26ab0c273c8b8813705dd0c9 Mon Sep 17 00:00:00 2001 From: iapicca Date: Sat, 3 Jan 2026 21:14:15 +0200 Subject: [PATCH 26/28] fix benchmark_config naming error --- frameworks/Dart/dart3/benchmark_config.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frameworks/Dart/dart3/benchmark_config.json b/frameworks/Dart/dart3/benchmark_config.json index 34504911a96..a06395953f8 100644 --- a/frameworks/Dart/dart3/benchmark_config.json +++ b/frameworks/Dart/dart3/benchmark_config.json @@ -2,7 +2,7 @@ "framework": "dart3", "tests": [ { - "dart3": { + "default": { "display_name": "dart3_native", "json_url": "/json", "plaintext_url": "/plaintext", From ab8e3964ffcf84d426ba146250353684a20dd483 Mon Sep 17 00:00:00 2001 From: iapicca Date: Sat, 3 Jan 2026 22:14:19 +0200 Subject: [PATCH 27/28] add error handling and internalServerError Response --- frameworks/Dart/dart3/bin/server.dart | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/frameworks/Dart/dart3/bin/server.dart b/frameworks/Dart/dart3/bin/server.dart index 5a31c189e7c..2ca70448974 100755 --- a/frameworks/Dart/dart3/bin/server.dart +++ b/frameworks/Dart/dart3/bin/server.dart @@ -84,6 +84,19 @@ Future _startServer(List _) async { /// Handles [HttpRequest]'s from [HttpServer]. await for (final request in server) { + /// Asynchronously processes each request with an 8-second safety deadline + /// to prevent stalled connections from blocking the isolate event loop. + _handleRequest(request).timeout( + const Duration(seconds: 8), + onTimeout: () => _sendResponse(request, HttpStatus.internalServerError), + ); + } +} + +/// Dispatches requests to specific test handlers. Wrapped in a try-catch +/// to ensure stable execution and guaranteed response delivery. +Future _handleRequest(HttpRequest request) async { + try { switch (request.uri.path) { case '/json': _jsonTest(request); @@ -94,6 +107,8 @@ Future _startServer(List _) async { default: _sendResponse(request, HttpStatus.notFound); } + } catch (e) { + _sendResponse(request, HttpStatus.internalServerError); } } From 65d7d9cd13de5b99299b96e538cd55a7b1902b7b Mon Sep 17 00:00:00 2001 From: iapicca Date: Sat, 3 Jan 2026 22:27:50 +0200 Subject: [PATCH 28/28] remove duplicate 'if' statement --- frameworks/Dart/dart3/bin/server.dart | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/frameworks/Dart/dart3/bin/server.dart b/frameworks/Dart/dart3/bin/server.dart index 2ca70448974..2a5b337da5b 100755 --- a/frameworks/Dart/dart3/bin/server.dart +++ b/frameworks/Dart/dart3/bin/server.dart @@ -28,15 +28,15 @@ void main(List args) async { /// Determine if this process instance was initialized as a worker group. final isWorkerGroup = args.contains(workerGroupTag); + if (isWorkerGroup) { /// Sanitize the argument list to ensure the internal token does not /// interfere with application-level argument parsing. args.removeAt(args.indexOf(workerGroupTag)); } - /// Prevents recursive spawning /// by ensuring only the primary process can spawn worker groups - if (!isWorkerGroup) { + else { /// Calculate the number of secondary worker groups required /// to fully utilize the available hardware capacity. ///