From 0eaddeb63356e0a7f315df0eaf7e047668ef0e8a Mon Sep 17 00:00:00 2001 From: kartikey321 Date: Mon, 30 Mar 2026 00:54:50 +0530 Subject: [PATCH 1/7] Add fletch framework implementation --- frameworks/fletch/.dockerignore | 2 + frameworks/fletch/Dockerfile | 23 ++ frameworks/fletch/bin/server.dart | 351 ++++++++++++++++++++++++++++++ frameworks/fletch/meta.json | 21 ++ frameworks/fletch/pubspec.lock | 285 ++++++++++++++++++++++++ frameworks/fletch/pubspec.yaml | 14 ++ 6 files changed, 696 insertions(+) create mode 100644 frameworks/fletch/.dockerignore create mode 100644 frameworks/fletch/Dockerfile create mode 100644 frameworks/fletch/bin/server.dart create mode 100644 frameworks/fletch/meta.json create mode 100644 frameworks/fletch/pubspec.lock create mode 100644 frameworks/fletch/pubspec.yaml diff --git a/frameworks/fletch/.dockerignore b/frameworks/fletch/.dockerignore new file mode 100644 index 00000000..05d02950 --- /dev/null +++ b/frameworks/fletch/.dockerignore @@ -0,0 +1,2 @@ +.dart_tool/ +pubspec.lock diff --git a/frameworks/fletch/Dockerfile b/frameworks/fletch/Dockerfile new file mode 100644 index 00000000..51ff1c42 --- /dev/null +++ b/frameworks/fletch/Dockerfile @@ -0,0 +1,23 @@ +# Stage 1 — AOT compile the Dart server +FROM dart:stable AS build + +WORKDIR /app +COPY pubspec.yaml ./ +RUN dart pub get + +COPY . . +RUN dart compile exe bin/server.dart -o bin/server + +# Stage 2 — Minimal runtime image +FROM debian:bookworm-slim + +# The Dart sqlite3 FFI loader looks for libsqlite3.so (unversioned), so we +# install the -dev package to ensure that soname symlink exists. +RUN apt-get update \ + && apt-get install -y --no-install-recommends libsqlite3-dev \ + && rm -rf /var/lib/apt/lists/* + +COPY --from=build /app/bin/server /server + +EXPOSE 8080 +CMD ["/server"] diff --git a/frameworks/fletch/bin/server.dart b/frameworks/fletch/bin/server.dart new file mode 100644 index 00000000..d25b9a58 --- /dev/null +++ b/frameworks/fletch/bin/server.dart @@ -0,0 +1,351 @@ +import 'dart:async'; +import 'dart:convert'; +import 'dart:io'; +import 'dart:isolate'; +import 'dart:typed_data'; + +import 'package:fletch/fletch.dart'; +import 'package:logger/logger.dart'; +import 'package:postgres/postgres.dart'; +import 'package:sqlite3/sqlite3.dart'; + +const _mimeTypes = { + '.css': 'text/css', + '.js': 'application/javascript', + '.html': 'text/html', + '.woff2': 'font/woff2', + '.svg': 'image/svg+xml', + '.webp': 'image/webp', + '.json': 'application/json', +}; + +// Pre-computed once; reused on every request that needs an empty result. +final _emptyJson = Uint8List.fromList(utf8.encode('{"items":[],"count":0}')); + +class _StaticFile { + final Uint8List data; + final String contentType; + const _StaticFile(this.data, this.contentType); +} + +Future main() async { + final n = Platform.numberOfProcessors; + for (var i = 1; i < n; i++) { + await Isolate.spawn(_run, null); + } + await _run(null); +} + +Future _run(dynamic _) async { + final jsonResponseBytes = _buildJsonResponseBytes(); + final gzipResponseBytes = _buildGzipResponseBytes(); + final staticFiles = _loadStaticFiles(); + final sqliteDb = _openSqlite(); + + // Prepared statement — avoids re-parsing SQL on every /db request. + final sqliteStmt = sqliteDb?.prepare( + 'SELECT id, name, category, price, quantity, active, tags,' + ' rating_score, rating_count' + ' FROM items WHERE price BETWEEN ? AND ? LIMIT 50', + ); + + // Postgres pool — populated after listen() so startup is never blocked. + Pool? pgPool; + Future? pgPoolConnectInFlight; + DateTime? pgLastConnectAttempt; + const pgRetryInterval = Duration(milliseconds: 500); + + Future ensurePgPool() async { + final current = pgPool; + if (current != null) return current; + + final inFlight = pgPoolConnectInFlight; + if (inFlight != null) return inFlight; + + final now = DateTime.now(); + final lastAttempt = pgLastConnectAttempt; + if (lastAttempt != null && now.difference(lastAttempt) < pgRetryInterval) { + return null; + } + pgLastConnectAttempt = now; + + final connectFuture = _openPostgresPool().then((pool) { + if (pool != null) pgPool = pool; + return pool; + }).whenComplete(() { + pgPoolConnectInFlight = null; + }); + pgPoolConnectInFlight = connectFuture; + return connectFuture; + } + + Future resetPgPool() async { + final oldPool = pgPool; + pgPool = null; + if (oldPool != null) { + try { + await oldPool.close(); + } catch (_) {} + } + } + + final app = Fletch( + requestTimeout: null, + secureCookies: false, + sessionSecret: 'httparena-bench-secret-key-fletch32!', + maxBodySize: 100 * 1024 * 1024, + maxFileSize: 100 * 1024 * 1024, + // Cookie parsing is unused in the benchmark; skip that middleware hop. + useCookieParser: false, + logger: Logger(level: Level.off), + ); + + app.get('/pipeline', (req, res) { + res.text('ok'); + }); + + app.get('/baseline11', (req, res) { + var sum = 0; + for (final v in req.query.values) { + final n = int.tryParse(v); + if (n != null) sum += n; + } + res.text('$sum'); + }); + + app.post('/baseline11', (req, res) async { + var sum = 0; + for (final v in req.query.values) { + final n = int.tryParse(v); + if (n != null) sum += n; + } + final body = await req.body; + if (body != null) { + final s = body is String + ? body.trim() + : utf8.decode(body as List).trim(); + final n = int.tryParse(s); + if (n != null) sum += n; + } + res.text('$sum'); + }); + + app.get('/json', (req, res) { + res.bytes(jsonResponseBytes, contentType: 'application/json'); + }); + + // Use Content-Length header when available — avoids buffering the entire + // upload body just to count bytes, which matters for large payloads. + app.post('/upload', (req, res) async { + final cl = req.httpRequest.contentLength; + if (cl >= 0) { + res.text('$cl'); + return; + } + // Fallback for chunked transfers: buffer and count. + final body = await req.body; + int size = 0; + if (body is Uint8List) { + size = body.length; + } else if (body is String) { + size = utf8.encode(body).length; + } else if (body is List) { + size = body.length; + } + res.text('$size'); + }); + + app.get('/compression', (req, res) { + res.bytes(gzipResponseBytes, contentType: 'application/json'); + res.setHeader('Content-Encoding', 'gzip'); + }); + + app.get('/static/:filename', (req, res) { + final sf = staticFiles[req.params['filename']!]; + if (sf == null) { + res.setStatus(404); + } else { + res.bytes(sf.data, contentType: sf.contentType); + } + }); + + app.get('/db', (req, res) { + if (sqliteStmt == null) { + stderr.writeln('[db] sqliteStmt is null — sqlite3 may not have loaded'); + res.bytes(_emptyJson, contentType: 'application/json'); + return; + } + final minVal = double.tryParse(req.query['min'] ?? '') ?? 10.0; + final maxVal = double.tryParse(req.query['max'] ?? '') ?? 50.0; + try { + final rows = sqliteStmt.select([minVal, maxVal]); + final items = rows + .map((row) => { + 'id': row['id'], + 'name': row['name'], + 'category': row['category'], + 'price': row['price'], + 'quantity': row['quantity'], + 'active': row['active'] == 1, + 'tags': jsonDecode(row['tags'] as String), + 'rating': { + 'score': row['rating_score'], + 'count': row['rating_count'], + }, + }) + .toList(); + res.bytes( + utf8.encode(jsonEncode({'items': items, 'count': items.length})), + contentType: 'application/json', + ); + } catch (e, st) { + stderr.writeln('[db] error: $e\n$st'); + res.bytes(_emptyJson, contentType: 'application/json'); + } + }); + + app.get('/async-db', (req, res) async { + final pool = await ensurePgPool(); + if (pool == null) { + res.bytes(_emptyJson, contentType: 'application/json'); + return; + } + final minVal = double.tryParse(req.query['min'] ?? '') ?? 10.0; + final maxVal = double.tryParse(req.query['max'] ?? '') ?? 50.0; + try { + final result = await pool.execute( + r'SELECT id, name, category, price, quantity, active, tags,' + r' rating_score, rating_count' + r' FROM items WHERE price BETWEEN $1 AND $2 LIMIT 50', + parameters: [minVal, maxVal], + ); + final items = result.map((row) { + final cols = row.toColumnMap(); + final tagsRaw = cols['tags']; + final tags = + tagsRaw is List ? tagsRaw : jsonDecode(tagsRaw as String); + return { + 'id': cols['id'], + 'name': cols['name'], + 'category': cols['category'], + 'price': cols['price'], + 'quantity': cols['quantity'], + 'active': cols['active'], + 'tags': tags, + 'rating': { + 'score': cols['rating_score'], + 'count': cols['rating_count'], + }, + }; + }).toList(); + res.bytes( + utf8.encode(jsonEncode({'items': items, 'count': items.length})), + contentType: 'application/json', + ); + } catch (_) { + await resetPgPool(); + res.bytes(_emptyJson, contentType: 'application/json'); + } + }); + + // Bind first — server is reachable immediately. + await app.listen(8080, shared: true); + + // Kick off async-db pool warmup, but keep lazy retries in request path. + unawaited(ensurePgPool()); +} + +// --------------------------------------------------------------------------- +// Data helpers +// --------------------------------------------------------------------------- + +Uint8List _buildJsonResponseBytes() { + try { + final raw = + jsonDecode(File('/data/dataset.json').readAsStringSync()) as List; + final items = raw.map(_mapItem).toList(); + return utf8.encode(jsonEncode({'items': items, 'count': items.length})); + } catch (_) { + return _emptyJson; + } +} + +Uint8List _buildGzipResponseBytes() { + try { + final raw = + jsonDecode(File('/data/dataset-large.json').readAsStringSync()) as List; + final items = raw.map(_mapItem).toList(); + final jsonBytes = + utf8.encode(jsonEncode({'items': items, 'count': items.length})); + return Uint8List.fromList(GZipCodec(level: 1).encode(jsonBytes)); + } catch (_) { + return Uint8List.fromList(GZipCodec(level: 1).encode(_emptyJson)); + } +} + +Map _mapItem(dynamic d) => { + 'id': d['id'], + 'name': d['name'], + 'category': d['category'], + 'price': d['price'], + 'quantity': d['quantity'], + 'active': d['active'], + 'tags': d['tags'], + 'rating': d['rating'], + 'total': + ((d['price'] as num) * (d['quantity'] as num) * 100).round() / 100, + }; + +Map _loadStaticFiles() { + final result = {}; + try { + for (final entity in Directory('/data/static').listSync()) { + if (entity is! File) continue; + final name = entity.uri.pathSegments.last; + final ext = name.contains('.') ? '.${name.split('.').last}' : ''; + result[name] = _StaticFile( + entity.readAsBytesSync(), + _mimeTypes[ext] ?? 'application/octet-stream', + ); + } + } catch (_) {} + return result; +} + +Database? _openSqlite() { + try { + return sqlite3.open('/data/benchmark.db', mode: OpenMode.readOnly); + } catch (e) { + stderr.writeln('[sqlite] failed to open: $e'); + return null; + } +} + +Future _openPostgresPool() async { + final dbUrl = Platform.environment['DATABASE_URL']; + if (dbUrl == null) return null; + try { + final uri = Uri.parse(dbUrl); + final userInfo = uri.userInfo.split(':'); + final endpoint = Endpoint( + host: uri.host, + port: uri.port > 0 ? uri.port : 5432, + database: uri.path.substring(1), + username: userInfo[0], + password: userInfo.length > 1 ? userInfo[1] : '', + ); + // 4 connections per isolate; with N isolates total = 4N concurrent queries. + final pool = Pool.withEndpoints( + [endpoint], + settings: const PoolSettings( + sslMode: SslMode.disable, + maxConnectionCount: 4, + ), + ); + // Warm up one connection to catch auth/config errors early. + await pool.execute('SELECT 1'); + return pool; + } catch (_) { + return null; + } +} diff --git a/frameworks/fletch/meta.json b/frameworks/fletch/meta.json new file mode 100644 index 00000000..f9f94dbd --- /dev/null +++ b/frameworks/fletch/meta.json @@ -0,0 +1,21 @@ +{ + "display_name": "Fletch", + "language": "Dart", + "engine": "dart:io", + "type": "framework", + "description": "Express-inspired HTTP framework for Dart with radix-tree routing, middleware chains, signed sessions, and built-in DI.", + "repo": "https://github.com/kartikey321/fletch", + "enabled": true, + "tests": [ + "baseline", + "pipelined", + "limited-conn", + "json", + "upload", + "compression", + "noisy", + "mixed", + "static", + "async-db" + ] +} diff --git a/frameworks/fletch/pubspec.lock b/frameworks/fletch/pubspec.lock new file mode 100644 index 00000000..32c31f1c --- /dev/null +++ b/frameworks/fletch/pubspec.lock @@ -0,0 +1,285 @@ +# Generated by pub +# See https://dart.dev/tools/pub/glossary#lockfile +packages: + args: + dependency: transitive + description: + name: args + sha256: d0481093c50b1da8910eb0bb301626d4d8eb7284aa739614d2b394ee09e3ea04 + url: "https://pub.dev" + source: hosted + version: "2.7.0" + async: + dependency: transitive + description: + name: async + sha256: e2eb0491ba5ddb6177742d2da23904574082139b07c1e33b8503b9f46f3e1a37 + url: "https://pub.dev" + source: hosted + version: "2.13.1" + boolean_selector: + dependency: transitive + description: + name: boolean_selector + sha256: "8aab1771e1243a5063b8b0ff68042d67334e3feab9e95b9490f9a6ebf73b42ea" + url: "https://pub.dev" + source: hosted + version: "2.1.2" + buffer: + dependency: transitive + description: + name: buffer + sha256: "389da2ec2c16283c8787e0adaede82b1842102f8c8aae2f49003a766c5c6b3d1" + url: "https://pub.dev" + source: hosted + version: "1.2.3" + charcode: + dependency: transitive + description: + name: charcode + sha256: fb0f1107cac15a5ea6ef0a6ef71a807b9e4267c713bb93e00e92d737cc8dbd8a + url: "https://pub.dev" + source: hosted + version: "1.4.0" + clock: + dependency: transitive + description: + name: clock + sha256: fddb70d9b5277016c77a80201021d40a2247104d9f4aa7bab7157b7e3f05b84b + url: "https://pub.dev" + source: hosted + version: "1.1.2" + collection: + dependency: transitive + description: + name: collection + sha256: "2f5709ae4d3d59dd8f7cd309b4e023046b57d8a6c82130785d2b0e5868084e76" + url: "https://pub.dev" + source: hosted + version: "1.19.1" + crypto: + dependency: transitive + description: + name: crypto + sha256: c8ea0233063ba03258fbcf2ca4d6dadfefe14f02fab57702265467a19f27fadf + url: "https://pub.dev" + source: hosted + version: "3.0.7" + ffi: + dependency: transitive + description: + name: ffi + sha256: "6d7fd89431262d8f3125e81b50d3847a091d846eafcd4fdb88dd06f36d705a45" + url: "https://pub.dev" + source: hosted + version: "2.2.0" + fixnum: + dependency: transitive + description: + name: fixnum + sha256: b6dc7065e46c974bc7c5f143080a6764ec7a4be6da1285ececdc37be96de53be + url: "https://pub.dev" + source: hosted + version: "1.1.1" + fletch: + dependency: "direct main" + description: + name: fletch + sha256: "373f6be6c32e253eee43bfde712e2b22a484acb97d989b6eb0e6ee0e9916c796" + url: "https://pub.dev" + source: hosted + version: "2.2.0" + get_it: + dependency: transitive + description: + name: get_it + sha256: "568d62f0e68666fb5d95519743b3c24a34c7f19d834b0658c46e26d778461f66" + url: "https://pub.dev" + source: hosted + version: "9.2.1" + http: + dependency: transitive + description: + name: http + sha256: "87721a4a50b19c7f1d49001e51409bddc46303966ce89a65af4f4e6004896412" + url: "https://pub.dev" + source: hosted + version: "1.6.0" + http_parser: + dependency: transitive + description: + name: http_parser + sha256: "178d74305e7866013777bab2c3d8726205dc5a4dd935297175b19a23a2e66571" + url: "https://pub.dev" + source: hosted + version: "4.1.2" + logger: + dependency: "direct main" + description: + name: logger + sha256: "25aee487596a6257655a1e091ec2ae66bc30e7af663592cc3a27e6591e05035c" + url: "https://pub.dev" + source: hosted + version: "2.7.0" + matcher: + dependency: transitive + description: + name: matcher + sha256: dc0b7dc7651697ea4ff3e69ef44b0407ea32c487a39fff6a4004fa585e901861 + url: "https://pub.dev" + source: hosted + version: "0.12.19" + meta: + dependency: transitive + description: + name: meta + sha256: df0c643f44ad098eb37988027a8e2b2b5a031fd3977f06bbfd3a76637e8df739 + url: "https://pub.dev" + source: hosted + version: "1.18.2" + mime: + dependency: "direct main" + description: + name: mime + sha256: "41a20518f0cb1256669420fdba0cd90d21561e560ac240f26ef8322e45bb7ed6" + url: "https://pub.dev" + source: hosted + version: "2.0.0" + path: + dependency: transitive + description: + name: path + sha256: "75cca69d1490965be98c73ceaea117e8a04dd21217b37b292c9ddbec0d955bc5" + url: "https://pub.dev" + source: hosted + version: "1.9.1" + petitparser: + dependency: transitive + description: + name: petitparser + sha256: "91bd59303e9f769f108f8df05e371341b15d59e995e6806aefab827b58336675" + url: "https://pub.dev" + source: hosted + version: "7.0.2" + pool: + dependency: transitive + description: + name: pool + sha256: "978783255c543aa3586a1b3c21f6e9d720eb315376a915872c61ef8b5c20177d" + url: "https://pub.dev" + source: hosted + version: "1.5.2" + postgres: + dependency: "direct main" + description: + name: postgres + sha256: fefbbfe749c6130e5096588b9c4459173684c695952cd7636ab19be76f255469 + url: "https://pub.dev" + source: hosted + version: "3.5.9" + quiver: + dependency: transitive + description: + name: quiver + sha256: ea0b925899e64ecdfbf9c7becb60d5b50e706ade44a85b2363be2a22d88117d2 + url: "https://pub.dev" + source: hosted + version: "3.2.2" + source_span: + dependency: transitive + description: + name: source_span + sha256: "56a02f1f4cd1a2d96303c0144c93bd6d909eea6bee6bf5a0e0b685edbd4c47ab" + url: "https://pub.dev" + source: hosted + version: "1.10.2" + sqlite3: + dependency: "direct main" + description: + name: sqlite3 + sha256: "3145bd74dcdb4fd6f5c6dda4d4e4490a8087d7f286a14dee5d37087290f0f8a2" + url: "https://pub.dev" + source: hosted + version: "2.9.4" + stack_trace: + dependency: transitive + description: + name: stack_trace + sha256: "8b27215b45d22309b5cddda1aa2b19bdfec9df0e765f2de506401c071d38d1b1" + url: "https://pub.dev" + source: hosted + version: "1.12.1" + stream_channel: + dependency: transitive + description: + name: stream_channel + sha256: "969e04c80b8bcdf826f8f16579c7b14d780458bd97f56d107d3950fdbeef059d" + url: "https://pub.dev" + source: hosted + version: "2.1.4" + string_scanner: + dependency: transitive + description: + name: string_scanner + sha256: "921cd31725b72fe181906c6a94d987c78e3b98c2e205b397ea399d4054872b43" + url: "https://pub.dev" + source: hosted + version: "1.4.1" + term_glyph: + dependency: transitive + description: + name: term_glyph + sha256: "7f554798625ea768a7518313e58f83891c7f5024f88e46e7182a4558850a4b8e" + url: "https://pub.dev" + source: hosted + version: "1.2.2" + test_api: + dependency: transitive + description: + name: test_api + sha256: "949a932224383300f01be9221c39180316445ecb8e7547f70a41a35bf421fb9e" + url: "https://pub.dev" + source: hosted + version: "0.7.11" + typed_data: + dependency: transitive + description: + name: typed_data + sha256: f9049c039ebfeb4cf7a7104a675823cd72dba8297f264b6637062516699fa006 + url: "https://pub.dev" + source: hosted + version: "1.4.0" + uri: + dependency: transitive + description: + name: uri + sha256: "889eea21e953187c6099802b7b4cf5219ba8f3518f604a1033064d45b1b8268a" + url: "https://pub.dev" + source: hosted + version: "1.0.0" + uuid: + dependency: transitive + description: + name: uuid + sha256: "1fef9e8e11e2991bb773070d4656b7bd5d850967a2456cfc83cf47925ba79489" + url: "https://pub.dev" + source: hosted + version: "4.5.3" + web: + dependency: transitive + description: + name: web + sha256: "868d88a33d8a87b18ffc05f9f030ba328ffefba92d6c127917a2ba740f9cfe4a" + url: "https://pub.dev" + source: hosted + version: "1.1.1" + xml: + dependency: transitive + description: + name: xml + sha256: "971043b3a0d3da28727e40ed3e0b5d18b742fa5a68665cca88e74b7876d5e025" + url: "https://pub.dev" + source: hosted + version: "6.6.1" +sdks: + dart: ">=3.9.0 <4.0.0" diff --git a/frameworks/fletch/pubspec.yaml b/frameworks/fletch/pubspec.yaml new file mode 100644 index 00000000..e0683f23 --- /dev/null +++ b/frameworks/fletch/pubspec.yaml @@ -0,0 +1,14 @@ +name: httparena_fletch +description: Fletch HTTP framework — HttpArena benchmark server +version: 1.0.0 +publish_to: none + +environment: + sdk: '>=3.6.0 <4.0.0' + +dependencies: + fletch: ^2.2.0 + postgres: ^3.0.0 + sqlite3: ^2.4.0 + logger: ^2.5.0 + From c80967d07cd71b68b59074405597ffa50a9716ca Mon Sep 17 00:00:00 2001 From: kartikey321 Date: Mon, 30 Mar 2026 01:05:03 +0530 Subject: [PATCH 2/7] Bump dependencies and update Docker build for sqlite3 3.x --- frameworks/fletch/Dockerfile | 6 +-- frameworks/fletch/pubspec.lock | 72 ++++++++++++++++++++++++++++++++-- frameworks/fletch/pubspec.yaml | 5 +-- 3 files changed, 73 insertions(+), 10 deletions(-) diff --git a/frameworks/fletch/Dockerfile b/frameworks/fletch/Dockerfile index 51ff1c42..f7b6cb28 100644 --- a/frameworks/fletch/Dockerfile +++ b/frameworks/fletch/Dockerfile @@ -6,7 +6,7 @@ COPY pubspec.yaml ./ RUN dart pub get COPY . . -RUN dart compile exe bin/server.dart -o bin/server +RUN dart build cli --target bin/server.dart --output /app/build # Stage 2 — Minimal runtime image FROM debian:bookworm-slim @@ -17,7 +17,7 @@ RUN apt-get update \ && apt-get install -y --no-install-recommends libsqlite3-dev \ && rm -rf /var/lib/apt/lists/* -COPY --from=build /app/bin/server /server +COPY --from=build /app/build/bundle /server EXPOSE 8080 -CMD ["/server"] +CMD ["/server/bin/server"] diff --git a/frameworks/fletch/pubspec.lock b/frameworks/fletch/pubspec.lock index 32c31f1c..37258a7c 100644 --- a/frameworks/fletch/pubspec.lock +++ b/frameworks/fletch/pubspec.lock @@ -49,6 +49,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.1.2" + code_assets: + dependency: transitive + description: + name: code_assets + sha256: "83ccdaa064c980b5596c35dd64a8d3ecc68620174ab9b90b6343b753aa721687" + url: "https://pub.dev" + source: hosted + version: "1.0.0" collection: dependency: transitive description: @@ -73,6 +81,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.2.0" + file: + dependency: transitive + description: + name: file + sha256: a3b4f84adafef897088c160faf7dfffb7696046cb13ae90b508c2cbc95d3b8d4 + url: "https://pub.dev" + source: hosted + version: "7.0.1" fixnum: dependency: transitive description: @@ -97,6 +113,22 @@ packages: url: "https://pub.dev" source: hosted version: "9.2.1" + glob: + dependency: transitive + description: + name: glob + sha256: c3f1ee72c96f8f78935e18aa8cecced9ab132419e8625dc187e1c2408efc20de + url: "https://pub.dev" + source: hosted + version: "2.1.3" + hooks: + dependency: transitive + description: + name: hooks + sha256: e79ed1e8e1929bc6ecb6ec85f0cb519c887aa5b423705ded0d0f2d9226def388 + url: "https://pub.dev" + source: hosted + version: "1.0.2" http: dependency: transitive description: @@ -121,6 +153,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.7.0" + logging: + dependency: transitive + description: + name: logging + sha256: c8245ada5f1717ed44271ed1c26b8ce85ca3228fd2ffdb75468ab01979309d61 + url: "https://pub.dev" + source: hosted + version: "1.3.0" matcher: dependency: transitive description: @@ -138,13 +178,21 @@ packages: source: hosted version: "1.18.2" mime: - dependency: "direct main" + dependency: transitive description: name: mime sha256: "41a20518f0cb1256669420fdba0cd90d21561e560ac240f26ef8322e45bb7ed6" url: "https://pub.dev" source: hosted version: "2.0.0" + native_toolchain_c: + dependency: transitive + description: + name: native_toolchain_c + sha256: "6ba77bb18063eebe9de401f5e6437e95e1438af0a87a3a39084fbd37c90df572" + url: "https://pub.dev" + source: hosted + version: "0.17.6" path: dependency: transitive description: @@ -177,6 +225,14 @@ packages: url: "https://pub.dev" source: hosted version: "3.5.9" + pub_semver: + dependency: transitive + description: + name: pub_semver + sha256: "5bfcf68ca79ef689f8990d1160781b4bad40a3bd5e5218ad4076ddb7f4081585" + url: "https://pub.dev" + source: hosted + version: "2.2.0" quiver: dependency: transitive description: @@ -197,10 +253,10 @@ packages: dependency: "direct main" description: name: sqlite3 - sha256: "3145bd74dcdb4fd6f5c6dda4d4e4490a8087d7f286a14dee5d37087290f0f8a2" + sha256: caa693ad15a587a2b4fde093b728131a1827903872171089dedb16f7665d3a91 url: "https://pub.dev" source: hosted - version: "2.9.4" + version: "3.2.0" stack_trace: dependency: transitive description: @@ -281,5 +337,13 @@ packages: url: "https://pub.dev" source: hosted version: "6.6.1" + yaml: + dependency: transitive + description: + name: yaml + sha256: b9da305ac7c39faa3f030eccd175340f968459dae4af175130b3fc47e40d76ce + url: "https://pub.dev" + source: hosted + version: "3.1.3" sdks: - dart: ">=3.9.0 <4.0.0" + dart: ">=3.10.0 <4.0.0" diff --git a/frameworks/fletch/pubspec.yaml b/frameworks/fletch/pubspec.yaml index e0683f23..03d10bf3 100644 --- a/frameworks/fletch/pubspec.yaml +++ b/frameworks/fletch/pubspec.yaml @@ -4,11 +4,10 @@ version: 1.0.0 publish_to: none environment: - sdk: '>=3.6.0 <4.0.0' + sdk: '>=3.10.0 <4.0.0' dependencies: fletch: ^2.2.0 postgres: ^3.0.0 - sqlite3: ^2.4.0 + sqlite3: ^3.2.0 logger: ^2.5.0 - From 601cce1e7d40a5717f21a10a199b309e81fb3940 Mon Sep 17 00:00:00 2001 From: kartikey321 Date: Mon, 30 Mar 2026 01:21:05 +0530 Subject: [PATCH 3/7] Compute json and gzip responses per request --- frameworks/fletch/bin/server.dart | 47 ++++++++++++++++--------------- 1 file changed, 24 insertions(+), 23 deletions(-) diff --git a/frameworks/fletch/bin/server.dart b/frameworks/fletch/bin/server.dart index d25b9a58..bbf5c006 100644 --- a/frameworks/fletch/bin/server.dart +++ b/frameworks/fletch/bin/server.dart @@ -37,8 +37,8 @@ Future main() async { } Future _run(dynamic _) async { - final jsonResponseBytes = _buildJsonResponseBytes(); - final gzipResponseBytes = _buildGzipResponseBytes(); + final jsonDataset = _loadDataset('/data/dataset.json'); + final compressionDataset = _loadDataset('/data/dataset-large.json'); final staticFiles = _loadStaticFiles(); final sqliteDb = _openSqlite(); @@ -131,7 +131,15 @@ Future _run(dynamic _) async { }); app.get('/json', (req, res) { - res.bytes(jsonResponseBytes, contentType: 'application/json'); + if (jsonDataset == null) { + res.bytes(_emptyJson, contentType: 'application/json'); + return; + } + final items = jsonDataset.map(_mapItem).toList(); + res.bytes( + utf8.encode(jsonEncode({'items': items, 'count': items.length})), + contentType: 'application/json', + ); }); // Use Content-Length header when available — avoids buffering the entire @@ -156,7 +164,16 @@ Future _run(dynamic _) async { }); app.get('/compression', (req, res) { - res.bytes(gzipResponseBytes, contentType: 'application/json'); + if (compressionDataset == null) { + res.bytes(Uint8List.fromList(GZipCodec(level: 1).encode(_emptyJson)), + contentType: 'application/json'); + res.setHeader('Content-Encoding', 'gzip'); + return; + } + final items = compressionDataset.map(_mapItem).toList(); + final jsonBytes = utf8.encode(jsonEncode({'items': items, 'count': items.length})); + final gzipBytes = Uint8List.fromList(GZipCodec(level: 1).encode(jsonBytes)); + res.bytes(gzipBytes, contentType: 'application/json'); res.setHeader('Content-Encoding', 'gzip'); }); @@ -259,27 +276,11 @@ Future _run(dynamic _) async { // Data helpers // --------------------------------------------------------------------------- -Uint8List _buildJsonResponseBytes() { +List? _loadDataset(String path) { try { - final raw = - jsonDecode(File('/data/dataset.json').readAsStringSync()) as List; - final items = raw.map(_mapItem).toList(); - return utf8.encode(jsonEncode({'items': items, 'count': items.length})); + return jsonDecode(File(path).readAsStringSync()) as List; } catch (_) { - return _emptyJson; - } -} - -Uint8List _buildGzipResponseBytes() { - try { - final raw = - jsonDecode(File('/data/dataset-large.json').readAsStringSync()) as List; - final items = raw.map(_mapItem).toList(); - final jsonBytes = - utf8.encode(jsonEncode({'items': items, 'count': items.length})); - return Uint8List.fromList(GZipCodec(level: 1).encode(jsonBytes)); - } catch (_) { - return Uint8List.fromList(GZipCodec(level: 1).encode(_emptyJson)); + return null; } } From d3f75bf47011737b1b9bd96c8c8c4f66d1533680 Mon Sep 17 00:00:00 2001 From: kartikey321 Date: Mon, 30 Mar 2026 02:06:49 +0530 Subject: [PATCH 4/7] Add WORKERS override and optimize baseline query parsing --- frameworks/fletch/bin/server.dart | 33 ++++++++++++++++++++----------- 1 file changed, 22 insertions(+), 11 deletions(-) diff --git a/frameworks/fletch/bin/server.dart b/frameworks/fletch/bin/server.dart index bbf5c006..19f9c8e6 100644 --- a/frameworks/fletch/bin/server.dart +++ b/frameworks/fletch/bin/server.dart @@ -29,7 +29,11 @@ class _StaticFile { } Future main() async { - final n = Platform.numberOfProcessors; + final envWorkers = int.tryParse(Platform.environment['WORKERS'] ?? ''); + final n = (envWorkers != null && envWorkers > 0) + ? envWorkers + : Platform.numberOfProcessors; + stderr.writeln('[boot] workers=$n'); for (var i = 1; i < n; i++) { await Isolate.spawn(_run, null); } @@ -105,20 +109,12 @@ Future _run(dynamic _) async { }); app.get('/baseline11', (req, res) { - var sum = 0; - for (final v in req.query.values) { - final n = int.tryParse(v); - if (n != null) sum += n; - } + final sum = _sumQueryInts(req.query); res.text('$sum'); }); app.post('/baseline11', (req, res) async { - var sum = 0; - for (final v in req.query.values) { - final n = int.tryParse(v); - if (n != null) sum += n; - } + var sum = _sumQueryInts(req.query); final body = await req.body; if (body != null) { final s = body is String @@ -297,6 +293,21 @@ Map _mapItem(dynamic d) => { ((d['price'] as num) * (d['quantity'] as num) * 100).round() / 100, }; +int _sumQueryInts(Map query) { + final a = query['a']; + final b = query['b']; + if (a != null && b != null && query.length == 2) { + return (int.tryParse(a) ?? 0) + (int.tryParse(b) ?? 0); + } + + var sum = 0; + for (final v in query.values) { + final n = int.tryParse(v); + if (n != null) sum += n; + } + return sum; +} + Map _loadStaticFiles() { final result = {}; try { From a9554cb92ddb72be90780265dda3121d34ed98c0 Mon Sep 17 00:00:00 2001 From: kartikey321 Date: Mon, 30 Mar 2026 02:07:41 +0530 Subject: [PATCH 5/7] Revert "Add WORKERS override and optimize baseline query parsing" This reverts commit d3f75bf47011737b1b9bd96c8c8c4f66d1533680. --- frameworks/fletch/bin/server.dart | 33 +++++++++++-------------------- 1 file changed, 11 insertions(+), 22 deletions(-) diff --git a/frameworks/fletch/bin/server.dart b/frameworks/fletch/bin/server.dart index 19f9c8e6..bbf5c006 100644 --- a/frameworks/fletch/bin/server.dart +++ b/frameworks/fletch/bin/server.dart @@ -29,11 +29,7 @@ class _StaticFile { } Future main() async { - final envWorkers = int.tryParse(Platform.environment['WORKERS'] ?? ''); - final n = (envWorkers != null && envWorkers > 0) - ? envWorkers - : Platform.numberOfProcessors; - stderr.writeln('[boot] workers=$n'); + final n = Platform.numberOfProcessors; for (var i = 1; i < n; i++) { await Isolate.spawn(_run, null); } @@ -109,12 +105,20 @@ Future _run(dynamic _) async { }); app.get('/baseline11', (req, res) { - final sum = _sumQueryInts(req.query); + var sum = 0; + for (final v in req.query.values) { + final n = int.tryParse(v); + if (n != null) sum += n; + } res.text('$sum'); }); app.post('/baseline11', (req, res) async { - var sum = _sumQueryInts(req.query); + var sum = 0; + for (final v in req.query.values) { + final n = int.tryParse(v); + if (n != null) sum += n; + } final body = await req.body; if (body != null) { final s = body is String @@ -293,21 +297,6 @@ Map _mapItem(dynamic d) => { ((d['price'] as num) * (d['quantity'] as num) * 100).round() / 100, }; -int _sumQueryInts(Map query) { - final a = query['a']; - final b = query['b']; - if (a != null && b != null && query.length == 2) { - return (int.tryParse(a) ?? 0) + (int.tryParse(b) ?? 0); - } - - var sum = 0; - for (final v in query.values) { - final n = int.tryParse(v); - if (n != null) sum += n; - } - return sum; -} - Map _loadStaticFiles() { final result = {}; try { From 82e5d9645837cdeb13f9133646f4230e62ecff1c Mon Sep 17 00:00:00 2001 From: kartikey321 Date: Mon, 30 Mar 2026 12:25:13 +0530 Subject: [PATCH 6/7] fix: use nproc to match isolate count to cgroup CPU quota Platform.numberOfProcessors reads the host's total CPU count and ignores the --cpus=N Docker limit Same pattern used by node/express/fastify/bun/elysia/workerman. --- .../fletch/.dart_tool/package_config.json | 274 +++++++++++++ .../fletch/.dart_tool/package_graph.json | 370 ++++++++++++++++++ frameworks/fletch/Dockerfile | 4 +- frameworks/fletch/bin/server.dart | 9 +- frameworks/fletch/entrypoint.sh | 5 + 5 files changed, 659 insertions(+), 3 deletions(-) create mode 100644 frameworks/fletch/.dart_tool/package_config.json create mode 100644 frameworks/fletch/.dart_tool/package_graph.json create mode 100644 frameworks/fletch/entrypoint.sh diff --git a/frameworks/fletch/.dart_tool/package_config.json b/frameworks/fletch/.dart_tool/package_config.json new file mode 100644 index 00000000..b54b4942 --- /dev/null +++ b/frameworks/fletch/.dart_tool/package_config.json @@ -0,0 +1,274 @@ +{ + "configVersion": 2, + "packages": [ + { + "name": "args", + "rootUri": "file:///Users/kartik/.pub-cache/hosted/pub.dev/args-2.7.0", + "packageUri": "lib/", + "languageVersion": "3.3" + }, + { + "name": "async", + "rootUri": "file:///Users/kartik/.pub-cache/hosted/pub.dev/async-2.13.1", + "packageUri": "lib/", + "languageVersion": "3.4" + }, + { + "name": "boolean_selector", + "rootUri": "file:///Users/kartik/.pub-cache/hosted/pub.dev/boolean_selector-2.1.2", + "packageUri": "lib/", + "languageVersion": "3.1" + }, + { + "name": "buffer", + "rootUri": "file:///Users/kartik/.pub-cache/hosted/pub.dev/buffer-1.2.3", + "packageUri": "lib/", + "languageVersion": "2.12" + }, + { + "name": "charcode", + "rootUri": "file:///Users/kartik/.pub-cache/hosted/pub.dev/charcode-1.4.0", + "packageUri": "lib/", + "languageVersion": "3.0" + }, + { + "name": "clock", + "rootUri": "file:///Users/kartik/.pub-cache/hosted/pub.dev/clock-1.1.2", + "packageUri": "lib/", + "languageVersion": "3.4" + }, + { + "name": "code_assets", + "rootUri": "file:///Users/kartik/.pub-cache/hosted/pub.dev/code_assets-1.0.0", + "packageUri": "lib/", + "languageVersion": "3.9" + }, + { + "name": "collection", + "rootUri": "file:///Users/kartik/.pub-cache/hosted/pub.dev/collection-1.19.1", + "packageUri": "lib/", + "languageVersion": "3.4" + }, + { + "name": "crypto", + "rootUri": "file:///Users/kartik/.pub-cache/hosted/pub.dev/crypto-3.0.7", + "packageUri": "lib/", + "languageVersion": "3.4" + }, + { + "name": "ffi", + "rootUri": "file:///Users/kartik/.pub-cache/hosted/pub.dev/ffi-2.2.0", + "packageUri": "lib/", + "languageVersion": "3.7" + }, + { + "name": "file", + "rootUri": "file:///Users/kartik/.pub-cache/hosted/pub.dev/file-7.0.1", + "packageUri": "lib/", + "languageVersion": "3.0" + }, + { + "name": "fixnum", + "rootUri": "file:///Users/kartik/.pub-cache/hosted/pub.dev/fixnum-1.1.1", + "packageUri": "lib/", + "languageVersion": "3.1" + }, + { + "name": "fletch", + "rootUri": "file:///Users/kartik/.pub-cache/hosted/pub.dev/fletch-2.2.0", + "packageUri": "lib/", + "languageVersion": "3.6" + }, + { + "name": "get_it", + "rootUri": "file:///Users/kartik/.pub-cache/hosted/pub.dev/get_it-9.2.1", + "packageUri": "lib/", + "languageVersion": "3.0" + }, + { + "name": "glob", + "rootUri": "file:///Users/kartik/.pub-cache/hosted/pub.dev/glob-2.1.3", + "packageUri": "lib/", + "languageVersion": "3.3" + }, + { + "name": "hooks", + "rootUri": "file:///Users/kartik/.pub-cache/hosted/pub.dev/hooks-1.0.2", + "packageUri": "lib/", + "languageVersion": "3.10" + }, + { + "name": "http", + "rootUri": "file:///Users/kartik/.pub-cache/hosted/pub.dev/http-1.6.0", + "packageUri": "lib/", + "languageVersion": "3.4" + }, + { + "name": "http_parser", + "rootUri": "file:///Users/kartik/.pub-cache/hosted/pub.dev/http_parser-4.1.2", + "packageUri": "lib/", + "languageVersion": "3.4" + }, + { + "name": "logger", + "rootUri": "file:///Users/kartik/.pub-cache/hosted/pub.dev/logger-2.7.0", + "packageUri": "lib/", + "languageVersion": "2.17" + }, + { + "name": "logging", + "rootUri": "file:///Users/kartik/.pub-cache/hosted/pub.dev/logging-1.3.0", + "packageUri": "lib/", + "languageVersion": "3.4" + }, + { + "name": "matcher", + "rootUri": "file:///Users/kartik/.pub-cache/hosted/pub.dev/matcher-0.12.19", + "packageUri": "lib/", + "languageVersion": "3.7" + }, + { + "name": "meta", + "rootUri": "file:///Users/kartik/.pub-cache/hosted/pub.dev/meta-1.18.2", + "packageUri": "lib/", + "languageVersion": "3.5" + }, + { + "name": "mime", + "rootUri": "file:///Users/kartik/.pub-cache/hosted/pub.dev/mime-2.0.0", + "packageUri": "lib/", + "languageVersion": "3.2" + }, + { + "name": "native_toolchain_c", + "rootUri": "file:///Users/kartik/.pub-cache/hosted/pub.dev/native_toolchain_c-0.17.6", + "packageUri": "lib/", + "languageVersion": "3.10" + }, + { + "name": "path", + "rootUri": "file:///Users/kartik/.pub-cache/hosted/pub.dev/path-1.9.1", + "packageUri": "lib/", + "languageVersion": "3.4" + }, + { + "name": "petitparser", + "rootUri": "file:///Users/kartik/.pub-cache/hosted/pub.dev/petitparser-7.0.2", + "packageUri": "lib/", + "languageVersion": "3.8" + }, + { + "name": "pool", + "rootUri": "file:///Users/kartik/.pub-cache/hosted/pub.dev/pool-1.5.2", + "packageUri": "lib/", + "languageVersion": "3.4" + }, + { + "name": "postgres", + "rootUri": "file:///Users/kartik/.pub-cache/hosted/pub.dev/postgres-3.5.9", + "packageUri": "lib/", + "languageVersion": "3.9" + }, + { + "name": "pub_semver", + "rootUri": "file:///Users/kartik/.pub-cache/hosted/pub.dev/pub_semver-2.2.0", + "packageUri": "lib/", + "languageVersion": "3.4" + }, + { + "name": "quiver", + "rootUri": "file:///Users/kartik/.pub-cache/hosted/pub.dev/quiver-3.2.2", + "packageUri": "lib/", + "languageVersion": "2.17" + }, + { + "name": "source_span", + "rootUri": "file:///Users/kartik/.pub-cache/hosted/pub.dev/source_span-1.10.2", + "packageUri": "lib/", + "languageVersion": "3.1" + }, + { + "name": "sqlite3", + "rootUri": "file:///Users/kartik/.pub-cache/hosted/pub.dev/sqlite3-3.2.0", + "packageUri": "lib/", + "languageVersion": "3.9" + }, + { + "name": "stack_trace", + "rootUri": "file:///Users/kartik/.pub-cache/hosted/pub.dev/stack_trace-1.12.1", + "packageUri": "lib/", + "languageVersion": "3.4" + }, + { + "name": "stream_channel", + "rootUri": "file:///Users/kartik/.pub-cache/hosted/pub.dev/stream_channel-2.1.4", + "packageUri": "lib/", + "languageVersion": "3.3" + }, + { + "name": "string_scanner", + "rootUri": "file:///Users/kartik/.pub-cache/hosted/pub.dev/string_scanner-1.4.1", + "packageUri": "lib/", + "languageVersion": "3.1" + }, + { + "name": "term_glyph", + "rootUri": "file:///Users/kartik/.pub-cache/hosted/pub.dev/term_glyph-1.2.2", + "packageUri": "lib/", + "languageVersion": "3.1" + }, + { + "name": "test_api", + "rootUri": "file:///Users/kartik/.pub-cache/hosted/pub.dev/test_api-0.7.11", + "packageUri": "lib/", + "languageVersion": "3.7" + }, + { + "name": "typed_data", + "rootUri": "file:///Users/kartik/.pub-cache/hosted/pub.dev/typed_data-1.4.0", + "packageUri": "lib/", + "languageVersion": "3.5" + }, + { + "name": "uri", + "rootUri": "file:///Users/kartik/.pub-cache/hosted/pub.dev/uri-1.0.0", + "packageUri": "lib/", + "languageVersion": "2.12" + }, + { + "name": "uuid", + "rootUri": "file:///Users/kartik/.pub-cache/hosted/pub.dev/uuid-4.5.3", + "packageUri": "lib/", + "languageVersion": "3.0" + }, + { + "name": "web", + "rootUri": "file:///Users/kartik/.pub-cache/hosted/pub.dev/web-1.1.1", + "packageUri": "lib/", + "languageVersion": "3.4" + }, + { + "name": "xml", + "rootUri": "file:///Users/kartik/.pub-cache/hosted/pub.dev/xml-6.6.1", + "packageUri": "lib/", + "languageVersion": "3.8" + }, + { + "name": "yaml", + "rootUri": "file:///Users/kartik/.pub-cache/hosted/pub.dev/yaml-3.1.3", + "packageUri": "lib/", + "languageVersion": "3.4" + }, + { + "name": "httparena_fletch", + "rootUri": "../", + "packageUri": "lib/", + "languageVersion": "3.6" + } + ], + "generator": "pub", + "generatorVersion": "3.11.4", + "flutterRoot": "file:///Users/kartik/Downloads/flutter", + "flutterVersion": "3.41.6", + "pubCache": "file:///Users/kartik/.pub-cache" +} diff --git a/frameworks/fletch/.dart_tool/package_graph.json b/frameworks/fletch/.dart_tool/package_graph.json new file mode 100644 index 00000000..92538e38 --- /dev/null +++ b/frameworks/fletch/.dart_tool/package_graph.json @@ -0,0 +1,370 @@ +{ + "roots": [ + "httparena_fletch" + ], + "packages": [ + { + "name": "httparena_fletch", + "version": "1.0.0", + "dependencies": [ + "fletch", + "logger", + "postgres", + "sqlite3" + ], + "devDependencies": [] + }, + { + "name": "sqlite3", + "version": "3.2.0", + "dependencies": [ + "code_assets", + "collection", + "crypto", + "ffi", + "hooks", + "meta", + "native_toolchain_c", + "path", + "typed_data", + "web" + ] + }, + { + "name": "fletch", + "version": "2.2.0", + "dependencies": [ + "args", + "async", + "crypto", + "get_it", + "http", + "logger", + "meta", + "mime", + "uri", + "uuid", + "xml" + ] + }, + { + "name": "code_assets", + "version": "1.0.0", + "dependencies": [ + "collection", + "hooks" + ] + }, + { + "name": "collection", + "version": "1.19.1", + "dependencies": [] + }, + { + "name": "uri", + "version": "1.0.0", + "dependencies": [ + "matcher", + "quiver" + ] + }, + { + "name": "mime", + "version": "2.0.0", + "dependencies": [] + }, + { + "name": "typed_data", + "version": "1.4.0", + "dependencies": [ + "collection" + ] + }, + { + "name": "native_toolchain_c", + "version": "0.17.6", + "dependencies": [ + "code_assets", + "glob", + "hooks", + "logging", + "meta", + "pub_semver" + ] + }, + { + "name": "pub_semver", + "version": "2.2.0", + "dependencies": [ + "collection" + ] + }, + { + "name": "logging", + "version": "1.3.0", + "dependencies": [] + }, + { + "name": "crypto", + "version": "3.0.7", + "dependencies": [ + "typed_data" + ] + }, + { + "name": "get_it", + "version": "9.2.1", + "dependencies": [ + "async", + "collection", + "meta" + ] + }, + { + "name": "web", + "version": "1.1.1", + "dependencies": [] + }, + { + "name": "hooks", + "version": "1.0.2", + "dependencies": [ + "collection", + "crypto", + "logging", + "meta", + "pub_semver", + "yaml" + ] + }, + { + "name": "yaml", + "version": "3.1.3", + "dependencies": [ + "collection", + "source_span", + "string_scanner" + ] + }, + { + "name": "xml", + "version": "6.6.1", + "dependencies": [ + "collection", + "meta", + "petitparser" + ] + }, + { + "name": "uuid", + "version": "4.5.3", + "dependencies": [ + "crypto", + "fixnum" + ] + }, + { + "name": "fixnum", + "version": "1.1.1", + "dependencies": [] + }, + { + "name": "glob", + "version": "2.1.3", + "dependencies": [ + "async", + "collection", + "file", + "path", + "string_scanner" + ] + }, + { + "name": "petitparser", + "version": "7.0.2", + "dependencies": [ + "collection", + "meta" + ] + }, + { + "name": "async", + "version": "2.13.1", + "dependencies": [ + "collection", + "meta" + ] + }, + { + "name": "args", + "version": "2.7.0", + "dependencies": [] + }, + { + "name": "string_scanner", + "version": "1.4.1", + "dependencies": [ + "source_span" + ] + }, + { + "name": "file", + "version": "7.0.1", + "dependencies": [ + "meta", + "path" + ] + }, + { + "name": "path", + "version": "1.9.1", + "dependencies": [] + }, + { + "name": "logger", + "version": "2.7.0", + "dependencies": [ + "clock", + "meta" + ] + }, + { + "name": "clock", + "version": "1.1.2", + "dependencies": [] + }, + { + "name": "meta", + "version": "1.18.2", + "dependencies": [] + }, + { + "name": "quiver", + "version": "3.2.2", + "dependencies": [ + "matcher" + ] + }, + { + "name": "ffi", + "version": "2.2.0", + "dependencies": [] + }, + { + "name": "http", + "version": "1.6.0", + "dependencies": [ + "async", + "http_parser", + "meta", + "web" + ] + }, + { + "name": "http_parser", + "version": "4.1.2", + "dependencies": [ + "collection", + "source_span", + "string_scanner", + "typed_data" + ] + }, + { + "name": "source_span", + "version": "1.10.2", + "dependencies": [ + "collection", + "path", + "term_glyph" + ] + }, + { + "name": "term_glyph", + "version": "1.2.2", + "dependencies": [] + }, + { + "name": "matcher", + "version": "0.12.19", + "dependencies": [ + "async", + "meta", + "stack_trace", + "term_glyph", + "test_api" + ] + }, + { + "name": "stack_trace", + "version": "1.12.1", + "dependencies": [ + "path" + ] + }, + { + "name": "test_api", + "version": "0.7.11", + "dependencies": [ + "async", + "boolean_selector", + "collection", + "meta", + "source_span", + "stack_trace", + "stream_channel", + "string_scanner", + "term_glyph" + ] + }, + { + "name": "boolean_selector", + "version": "2.1.2", + "dependencies": [ + "source_span", + "string_scanner" + ] + }, + { + "name": "stream_channel", + "version": "2.1.4", + "dependencies": [ + "async" + ] + }, + { + "name": "postgres", + "version": "3.5.9", + "dependencies": [ + "async", + "buffer", + "charcode", + "collection", + "crypto", + "meta", + "pool", + "stack_trace", + "stream_channel" + ] + }, + { + "name": "charcode", + "version": "1.4.0", + "dependencies": [] + }, + { + "name": "buffer", + "version": "1.2.3", + "dependencies": [] + }, + { + "name": "pool", + "version": "1.5.2", + "dependencies": [ + "async", + "stack_trace" + ] + } + ], + "configVersion": 1 +} \ No newline at end of file diff --git a/frameworks/fletch/Dockerfile b/frameworks/fletch/Dockerfile index f7b6cb28..aab47a4a 100644 --- a/frameworks/fletch/Dockerfile +++ b/frameworks/fletch/Dockerfile @@ -18,6 +18,8 @@ RUN apt-get update \ && rm -rf /var/lib/apt/lists/* COPY --from=build /app/build/bundle /server +COPY entrypoint.sh /entrypoint.sh +RUN chmod +x /entrypoint.sh EXPOSE 8080 -CMD ["/server/bin/server"] +CMD ["/entrypoint.sh"] diff --git a/frameworks/fletch/bin/server.dart b/frameworks/fletch/bin/server.dart index bbf5c006..db41e196 100644 --- a/frameworks/fletch/bin/server.dart +++ b/frameworks/fletch/bin/server.dart @@ -28,8 +28,13 @@ class _StaticFile { const _StaticFile(this.data, this.contentType); } -Future main() async { - final n = Platform.numberOfProcessors; +Future main(List args) async { + // Prefer the worker count passed via entrypoint.sh (derived from `nproc`, + // which respects the cgroup CPU quota set by --cpus=N). Fall back to + // Platform.numberOfProcessors when running outside Docker. + final n = args.isNotEmpty + ? (int.tryParse(args[0]) ?? Platform.numberOfProcessors) + : Platform.numberOfProcessors; for (var i = 1; i < n; i++) { await Isolate.spawn(_run, null); } diff --git a/frameworks/fletch/entrypoint.sh b/frameworks/fletch/entrypoint.sh new file mode 100644 index 00000000..05d77632 --- /dev/null +++ b/frameworks/fletch/entrypoint.sh @@ -0,0 +1,5 @@ +#!/bin/sh +# nproc on Linux reads the cgroup CPU quota, so it returns the value set by +# --cpus=N rather than the host's total CPU count. This ensures the Dart +# server spawns exactly as many isolates as the container is allowed to use. +exec /server/bin/server "$(nproc)" From 94fed24d54ae8b99f21dda3240123dfdc5920716 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Mon, 30 Mar 2026 07:46:29 +0000 Subject: [PATCH 7/7] Benchmark results: fletch --- site/data/async-db-1024.json | 20 ++++++++++++++ site/data/async-db-512.json | 20 ++++++++++++++ site/data/baseline-16384.json | 20 ++++++++++++++ site/data/baseline-4096.json | 20 ++++++++++++++ site/data/baseline-512.json | 20 ++++++++++++++ site/data/compression-16384.json | 20 ++++++++++++++ site/data/compression-4096.json | 20 ++++++++++++++ site/data/current.json | 4 +-- site/data/frameworks.json | 1 + site/data/json-16384.json | 20 ++++++++++++++ site/data/json-4096.json | 20 ++++++++++++++ site/data/limited-conn-4096.json | 20 ++++++++++++++ site/data/limited-conn-512.json | 20 ++++++++++++++ site/data/mixed-16384.json | 27 +++++++++++++++++++ site/data/mixed-4096.json | 27 +++++++++++++++++++ site/data/noisy-16384.json | 20 ++++++++++++++ site/data/noisy-4096.json | 20 ++++++++++++++ site/data/noisy-512.json | 20 ++++++++++++++ site/data/pipelined-16384.json | 20 ++++++++++++++ site/data/pipelined-4096.json | 20 ++++++++++++++ site/data/pipelined-512.json | 20 ++++++++++++++ site/data/static-16384.json | 20 ++++++++++++++ site/data/static-4096.json | 20 ++++++++++++++ site/data/upload-256.json | 20 ++++++++++++++ site/data/upload-512.json | 20 ++++++++++++++ site/data/upload-64.json | 20 ++++++++++++++ site/static/logs/async-db/1024/fletch.log | 0 site/static/logs/async-db/512/fletch.log | 0 site/static/logs/baseline/16384/fletch.log | 0 site/static/logs/baseline/4096/fletch.log | 0 site/static/logs/baseline/512/fletch.log | 0 site/static/logs/compression/16384/fletch.log | 0 site/static/logs/compression/4096/fletch.log | 0 site/static/logs/json/16384/fletch.log | 0 site/static/logs/json/4096/fletch.log | 0 site/static/logs/limited-conn/4096/fletch.log | 0 site/static/logs/limited-conn/512/fletch.log | 0 site/static/logs/mixed/16384/fletch.log | 7 +++++ site/static/logs/mixed/4096/fletch.log | 0 site/static/logs/noisy/16384/fletch.log | 0 site/static/logs/noisy/4096/fletch.log | 0 site/static/logs/noisy/512/fletch.log | 0 site/static/logs/pipelined/16384/fletch.log | 0 site/static/logs/pipelined/4096/fletch.log | 0 site/static/logs/pipelined/512/fletch.log | 0 site/static/logs/static/16384/fletch.log | 0 site/static/logs/static/4096/fletch.log | 0 site/static/logs/upload/256/fletch.log | 0 site/static/logs/upload/512/fletch.log | 0 site/static/logs/upload/64/fletch.log | 0 50 files changed, 504 insertions(+), 2 deletions(-) create mode 100644 site/static/logs/async-db/1024/fletch.log create mode 100644 site/static/logs/async-db/512/fletch.log create mode 100644 site/static/logs/baseline/16384/fletch.log create mode 100644 site/static/logs/baseline/4096/fletch.log create mode 100644 site/static/logs/baseline/512/fletch.log create mode 100644 site/static/logs/compression/16384/fletch.log create mode 100644 site/static/logs/compression/4096/fletch.log create mode 100644 site/static/logs/json/16384/fletch.log create mode 100644 site/static/logs/json/4096/fletch.log create mode 100644 site/static/logs/limited-conn/4096/fletch.log create mode 100644 site/static/logs/limited-conn/512/fletch.log create mode 100644 site/static/logs/mixed/16384/fletch.log create mode 100644 site/static/logs/mixed/4096/fletch.log create mode 100644 site/static/logs/noisy/16384/fletch.log create mode 100644 site/static/logs/noisy/4096/fletch.log create mode 100644 site/static/logs/noisy/512/fletch.log create mode 100644 site/static/logs/pipelined/16384/fletch.log create mode 100644 site/static/logs/pipelined/4096/fletch.log create mode 100644 site/static/logs/pipelined/512/fletch.log create mode 100644 site/static/logs/static/16384/fletch.log create mode 100644 site/static/logs/static/4096/fletch.log create mode 100644 site/static/logs/upload/256/fletch.log create mode 100644 site/static/logs/upload/512/fletch.log create mode 100644 site/static/logs/upload/64/fletch.log diff --git a/site/data/async-db-1024.json b/site/data/async-db-1024.json index 2d9166d9..4d72a7bb 100644 --- a/site/data/async-db-1024.json +++ b/site/data/async-db-1024.json @@ -758,5 +758,25 @@ "status_3xx": 0, "status_4xx": 0, "status_5xx": 0 + }, + { + "framework": "Fletch", + "language": "Dart", + "rps": 3817, + "avg_latency": "211.29ms", + "p99_latency": "905.60ms", + "cpu": "867.0%", + "memory": "2.5GiB", + "connections": 1024, + "threads": 64, + "duration": "5s", + "pipeline": 1, + "bandwidth": "30.29MB/s", + "input_bw": "", + "reconnects": 0, + "status_2xx": 19086, + "status_3xx": 0, + "status_4xx": 0, + "status_5xx": 0 } ] \ No newline at end of file diff --git a/site/data/async-db-512.json b/site/data/async-db-512.json index e04fd4f9..94995207 100644 --- a/site/data/async-db-512.json +++ b/site/data/async-db-512.json @@ -758,5 +758,25 @@ "status_3xx": 0, "status_4xx": 0, "status_5xx": 0 + }, + { + "framework": "Fletch", + "language": "Dart", + "rps": 4873, + "avg_latency": "99.72ms", + "p99_latency": "444.50ms", + "cpu": "1105.6%", + "memory": "1.9GiB", + "connections": 512, + "threads": 64, + "duration": "5s", + "pipeline": 1, + "bandwidth": "38.68MB/s", + "input_bw": "", + "reconnects": 0, + "status_2xx": 24369, + "status_3xx": 0, + "status_4xx": 0, + "status_5xx": 0 } ] \ No newline at end of file diff --git a/site/data/baseline-16384.json b/site/data/baseline-16384.json index 30d926f7..5355f129 100644 --- a/site/data/baseline-16384.json +++ b/site/data/baseline-16384.json @@ -1058,5 +1058,25 @@ "status_3xx": 0, "status_4xx": 0, "status_5xx": 0 + }, + { + "framework": "Fletch", + "language": "Dart", + "rps": 158019, + "avg_latency": "27.42ms", + "p99_latency": "138.20ms", + "cpu": "1227.9%", + "memory": "1.4GiB", + "connections": 16384, + "threads": 64, + "duration": "5s", + "pipeline": 1, + "bandwidth": "29.38MB/s", + "input_bw": "12.21MB/s", + "reconnects": 0, + "status_2xx": 790095, + "status_3xx": 0, + "status_4xx": 0, + "status_5xx": 0 } ] \ No newline at end of file diff --git a/site/data/baseline-4096.json b/site/data/baseline-4096.json index f400b8e6..7de234aa 100644 --- a/site/data/baseline-4096.json +++ b/site/data/baseline-4096.json @@ -1058,5 +1058,25 @@ "status_3xx": 0, "status_4xx": 0, "status_5xx": 0 + }, + { + "framework": "Fletch", + "language": "Dart", + "rps": 177116, + "avg_latency": "8.35ms", + "p99_latency": "12.60ms", + "cpu": "1353.5%", + "memory": "1.4GiB", + "connections": 4096, + "threads": 64, + "duration": "5s", + "pipeline": 1, + "bandwidth": "32.93MB/s", + "input_bw": "13.68MB/s", + "reconnects": 0, + "status_2xx": 885583, + "status_3xx": 0, + "status_4xx": 0, + "status_5xx": 0 } ] \ No newline at end of file diff --git a/site/data/baseline-512.json b/site/data/baseline-512.json index b3a09aee..768d075b 100644 --- a/site/data/baseline-512.json +++ b/site/data/baseline-512.json @@ -1058,5 +1058,25 @@ "status_3xx": 0, "status_4xx": 0, "status_5xx": 0 + }, + { + "framework": "Fletch", + "language": "Dart", + "rps": 180487, + "avg_latency": "2.31ms", + "p99_latency": "3.85ms", + "cpu": "1374.3%", + "memory": "1.3GiB", + "connections": 512, + "threads": 64, + "duration": "5s", + "pipeline": 1, + "bandwidth": "33.55MB/s", + "input_bw": "13.94MB/s", + "reconnects": 0, + "status_2xx": 902437, + "status_3xx": 0, + "status_4xx": 0, + "status_5xx": 0 } ] \ No newline at end of file diff --git a/site/data/compression-16384.json b/site/data/compression-16384.json index 95af5f82..aac9eae8 100644 --- a/site/data/compression-16384.json +++ b/site/data/compression-16384.json @@ -846,5 +846,25 @@ "status_3xx": 0, "status_4xx": 0, "status_5xx": 0 + }, + { + "framework": "Fletch", + "language": "Dart", + "rps": 126, + "avg_latency": "1.31s", + "p99_latency": "4.25s", + "cpu": "708.3%", + "memory": "1023.0MiB", + "connections": 16384, + "threads": 64, + "duration": "5s", + "pipeline": 1, + "bandwidth": "26.56MB/s", + "input_bw": "9.11KB/s", + "reconnects": 0, + "status_2xx": 632, + "status_3xx": 0, + "status_4xx": 0, + "status_5xx": 0 } ] \ No newline at end of file diff --git a/site/data/compression-4096.json b/site/data/compression-4096.json index 75471de4..549b8aa2 100644 --- a/site/data/compression-4096.json +++ b/site/data/compression-4096.json @@ -846,5 +846,25 @@ "status_3xx": 0, "status_4xx": 0, "status_5xx": 0 + }, + { + "framework": "Fletch", + "language": "Dart", + "rps": 140, + "avg_latency": "1.30s", + "p99_latency": "3.89s", + "cpu": "783.4%", + "memory": "3.9GiB", + "connections": 4096, + "threads": 64, + "duration": "5s", + "pipeline": 1, + "bandwidth": "29.46MB/s", + "input_bw": "10.12KB/s", + "reconnects": 0, + "status_2xx": 701, + "status_3xx": 0, + "status_4xx": 0, + "status_5xx": 0 } ] \ No newline at end of file diff --git a/site/data/current.json b/site/data/current.json index 12438d18..1cf676bc 100644 --- a/site/data/current.json +++ b/site/data/current.json @@ -1,5 +1,5 @@ { - "date": "2026-03-29", + "date": "2026-03-30", "cpu": "AMD Ryzen Threadripper PRO 3995WX 64-Cores", "cores": "64", "threads": "128", @@ -7,7 +7,7 @@ "os": "Ubuntu 24.04.4 LTS", "kernel": "6.17.0-19-generic", "docker": "29.3.0", - "commit": "40a4b16", + "commit": "82e5d96", "governor": "performance", "docker_runtime": "runc", "threads_per_core": "2", diff --git a/site/data/frameworks.json b/site/data/frameworks.json index 1b6724ce..20eeb22c 100644 --- a/site/data/frameworks.json +++ b/site/data/frameworks.json @@ -22,6 +22,7 @@ "FastPySGI-ASGI": {"description": "An ultra fast WSGI/ASGI server for Python", "repo": "https://github.com/remittor/fastpysgi", "type": "engine", "engine": "libuv"}, "fiber": {"description": "Fiber is an Express-inspired Go web framework built on fasthttp, featuring zero-allocation routing and extreme performance.", "repo": "https://github.com/gofiber/fiber", "type": "framework", "engine": "fiber"}, "flask": {"description": "Flask web framework on Gunicorn with sync workers, one worker per CPU core.", "repo": "https://github.com/pallets/flask", "type": "framework", "engine": "gunicorn"}, + "Fletch": {"description": "Express-inspired HTTP framework for Dart with radix-tree routing, middleware chains, signed sessions, and built-in DI.", "repo": "https://github.com/kartikey321/fletch", "type": "framework", "engine": "dart:io"}, "GenHTTP": {"description": "Lightweight, embeddable and modular C# web server.", "repo": "https://github.com/Kaliumhexacyanoferrat/GenHTTP", "type": "framework", "engine": "GenHTTP"}, "GenHTTP-WS": {"description": "GenHTTP WebSocket echo server using the functional API with zero-allocation frame handling.", "repo": "https://github.com/Kaliumhexacyanoferrat/GenHTTP", "type": "framework", "engine": "GenHTTP"}, "gin": {"description": "Gin is a Go web framework with a martini-like API, featuring the fastest HTTP router (httprouter) and zero-allocation routing.", "repo": "https://github.com/gin-gonic/gin", "type": "framework", "engine": "gin"}, diff --git a/site/data/json-16384.json b/site/data/json-16384.json index a65ca454..ae47abac 100644 --- a/site/data/json-16384.json +++ b/site/data/json-16384.json @@ -874,5 +874,25 @@ "status_3xx": 0, "status_4xx": 0, "status_5xx": 0 + }, + { + "framework": "Fletch", + "language": "Dart", + "rps": 30174, + "avg_latency": "98.01ms", + "p99_latency": "961.10ms", + "cpu": "1196.1%", + "memory": "1.4GiB", + "connections": 16384, + "threads": 64, + "duration": "5s", + "pipeline": 1, + "bandwidth": "245.98MB/s", + "input_bw": "", + "reconnects": 0, + "status_2xx": 150874, + "status_3xx": 0, + "status_4xx": 0, + "status_5xx": 0 } ] \ No newline at end of file diff --git a/site/data/json-4096.json b/site/data/json-4096.json index 46bdf613..7845bc2c 100644 --- a/site/data/json-4096.json +++ b/site/data/json-4096.json @@ -874,5 +874,25 @@ "status_3xx": 0, "status_4xx": 0, "status_5xx": 0 + }, + { + "framework": "Fletch", + "language": "Dart", + "rps": 37808, + "avg_latency": "33.00ms", + "p99_latency": "323.20ms", + "cpu": "1346.5%", + "memory": "1.3GiB", + "connections": 4096, + "threads": 64, + "duration": "5s", + "pipeline": 1, + "bandwidth": "308.22MB/s", + "input_bw": "", + "reconnects": 0, + "status_2xx": 189044, + "status_3xx": 0, + "status_4xx": 0, + "status_5xx": 0 } ] \ No newline at end of file diff --git a/site/data/limited-conn-4096.json b/site/data/limited-conn-4096.json index 5a021cf9..319f6659 100644 --- a/site/data/limited-conn-4096.json +++ b/site/data/limited-conn-4096.json @@ -1043,5 +1043,25 @@ "status_3xx": 0, "status_4xx": 0, "status_5xx": 0 + }, + { + "framework": "Fletch", + "language": "Dart", + "rps": 127671, + "avg_latency": "6.86ms", + "p99_latency": "12.90ms", + "cpu": "1176.2%", + "memory": "1.2GiB", + "connections": 4096, + "threads": 64, + "duration": "5s", + "pipeline": 1, + "bandwidth": "25.93MB/s", + "input_bw": "9.86MB/s", + "reconnects": 69417, + "status_2xx": 638356, + "status_3xx": 0, + "status_4xx": 0, + "status_5xx": 0 } ] \ No newline at end of file diff --git a/site/data/limited-conn-512.json b/site/data/limited-conn-512.json index 8ab9db21..c4790d58 100644 --- a/site/data/limited-conn-512.json +++ b/site/data/limited-conn-512.json @@ -1043,5 +1043,25 @@ "status_3xx": 0, "status_4xx": 0, "status_5xx": 0 + }, + { + "framework": "Fletch", + "language": "Dart", + "rps": 144092, + "avg_latency": "2.74ms", + "p99_latency": "3.64ms", + "cpu": "1401.7%", + "memory": "1.1GiB", + "connections": 512, + "threads": 64, + "duration": "5s", + "pipeline": 1, + "bandwidth": "29.41MB/s", + "input_bw": "11.13MB/s", + "reconnects": 79450, + "status_2xx": 720462, + "status_3xx": 0, + "status_4xx": 0, + "status_5xx": 0 } ] \ No newline at end of file diff --git a/site/data/mixed-16384.json b/site/data/mixed-16384.json index 3ec55584..8ff1bdbc 100644 --- a/site/data/mixed-16384.json +++ b/site/data/mixed-16384.json @@ -1051,5 +1051,32 @@ "tpl_compression": 85553, "tpl_static": 95221, "tpl_async_db": 2 + }, + { + "framework": "Fletch", + "language": "Dart", + "rps": 611, + "avg_latency": "1.15s", + "p99_latency": "5.00s", + "cpu": "854.6%", + "memory": "9.9GiB", + "connections": 16384, + "threads": 64, + "duration": "5s", + "pipeline": 1, + "bandwidth": "31.95MB/s", + "input_bw": "43.68MB/s", + "reconnects": 2060, + "status_2xx": 9168, + "status_3xx": 0, + "status_4xx": 0, + "status_5xx": 0, + "tpl_baseline": 2983, + "tpl_json": 576, + "tpl_db": 573, + "tpl_upload": 546, + "tpl_compression": 2154, + "tpl_static": 1133, + "tpl_async_db": 1203 } ] \ No newline at end of file diff --git a/site/data/mixed-4096.json b/site/data/mixed-4096.json index 09c99949..e7066cab 100644 --- a/site/data/mixed-4096.json +++ b/site/data/mixed-4096.json @@ -1051,5 +1051,32 @@ "tpl_compression": 94430, "tpl_static": 106061, "tpl_async_db": 0 + }, + { + "framework": "Fletch", + "language": "Dart", + "rps": 724, + "avg_latency": "974.94ms", + "p99_latency": "5.00s", + "cpu": "863.3%", + "memory": "11.2GiB", + "connections": 4096, + "threads": 64, + "duration": "5s", + "pipeline": 1, + "bandwidth": "31.05MB/s", + "input_bw": "51.76MB/s", + "reconnects": 2253, + "status_2xx": 10872, + "status_3xx": 0, + "status_4xx": 0, + "status_5xx": 0, + "tpl_baseline": 3833, + "tpl_json": 731, + "tpl_db": 750, + "tpl_upload": 733, + "tpl_compression": 2055, + "tpl_static": 1417, + "tpl_async_db": 1353 } ] \ No newline at end of file diff --git a/site/data/noisy-16384.json b/site/data/noisy-16384.json index 476d238b..357cf090 100644 --- a/site/data/noisy-16384.json +++ b/site/data/noisy-16384.json @@ -825,5 +825,25 @@ "status_3xx": 0, "status_4xx": 3863291, "status_5xx": 0 + }, + { + "framework": "Fletch", + "language": "Dart", + "rps": 106777, + "avg_latency": "18.54ms", + "p99_latency": "39.10ms", + "cpu": "1105.5%", + "memory": "2.0GiB", + "connections": 16384, + "threads": 64, + "duration": "5s", + "pipeline": 1, + "bandwidth": "29.19MB/s", + "input_bw": "10.79MB/s", + "reconnects": 1905, + "status_2xx": 533885, + "status_3xx": 0, + "status_4xx": 179468, + "status_5xx": 0 } ] \ No newline at end of file diff --git a/site/data/noisy-4096.json b/site/data/noisy-4096.json index ef7edcbb..baefec99 100644 --- a/site/data/noisy-4096.json +++ b/site/data/noisy-4096.json @@ -825,5 +825,25 @@ "status_3xx": 0, "status_4xx": 2271170, "status_5xx": 0 + }, + { + "framework": "Fletch", + "language": "Dart", + "rps": 131098, + "avg_latency": "2.93ms", + "p99_latency": "6.16ms", + "cpu": "1349.1%", + "memory": "1.4GiB", + "connections": 4096, + "threads": 64, + "duration": "5s", + "pipeline": 1, + "bandwidth": "35.71MB/s", + "input_bw": "13.25MB/s", + "reconnects": 237, + "status_2xx": 655490, + "status_3xx": 0, + "status_4xx": 217806, + "status_5xx": 0 } ] \ No newline at end of file diff --git a/site/data/noisy-512.json b/site/data/noisy-512.json index 02eabf49..0d288f43 100644 --- a/site/data/noisy-512.json +++ b/site/data/noisy-512.json @@ -825,5 +825,25 @@ "status_3xx": 0, "status_4xx": 2213021, "status_5xx": 0 + }, + { + "framework": "Fletch", + "language": "Dart", + "rps": 108469, + "avg_latency": "2.52ms", + "p99_latency": "3.61ms", + "cpu": "1233.7%", + "memory": "1.6GiB", + "connections": 512, + "threads": 64, + "duration": "5s", + "pipeline": 1, + "bandwidth": "30.43MB/s", + "input_bw": "10.97MB/s", + "reconnects": 34, + "status_2xx": 542349, + "status_3xx": 0, + "status_4xx": 197138, + "status_5xx": 0 } ] \ No newline at end of file diff --git a/site/data/pipelined-16384.json b/site/data/pipelined-16384.json index 7c365b72..61e83ca2 100644 --- a/site/data/pipelined-16384.json +++ b/site/data/pipelined-16384.json @@ -1045,5 +1045,25 @@ "status_3xx": 0, "status_4xx": 0, "status_5xx": 0 + }, + { + "framework": "Fletch", + "language": "Dart", + "rps": 267269, + "avg_latency": "81.11ms", + "p99_latency": "2.20s", + "cpu": "1310.2%", + "memory": "1.2GiB", + "connections": 16384, + "threads": 64, + "duration": "5s", + "pipeline": 16, + "bandwidth": "49.70MB/s", + "input_bw": "", + "reconnects": 0, + "status_2xx": 1336346, + "status_3xx": 0, + "status_4xx": 0, + "status_5xx": 0 } ] \ No newline at end of file diff --git a/site/data/pipelined-4096.json b/site/data/pipelined-4096.json index 15475573..d90712d8 100644 --- a/site/data/pipelined-4096.json +++ b/site/data/pipelined-4096.json @@ -1045,5 +1045,25 @@ "status_3xx": 0, "status_4xx": 0, "status_5xx": 0 + }, + { + "framework": "Fletch", + "language": "Dart", + "rps": 276937, + "avg_latency": "31.58ms", + "p99_latency": "523.40ms", + "cpu": "1368.9%", + "memory": "1.1GiB", + "connections": 4096, + "threads": 64, + "duration": "5s", + "pipeline": 16, + "bandwidth": "51.51MB/s", + "input_bw": "", + "reconnects": 0, + "status_2xx": 1384688, + "status_3xx": 0, + "status_4xx": 0, + "status_5xx": 0 } ] \ No newline at end of file diff --git a/site/data/pipelined-512.json b/site/data/pipelined-512.json index f252c0cc..04e45d11 100644 --- a/site/data/pipelined-512.json +++ b/site/data/pipelined-512.json @@ -1045,5 +1045,25 @@ "status_3xx": 0, "status_4xx": 0, "status_5xx": 0 + }, + { + "framework": "Fletch", + "language": "Dart", + "rps": 274481, + "avg_latency": "22.02ms", + "p99_latency": "371.10ms", + "cpu": "1373.3%", + "memory": "1.1GiB", + "connections": 512, + "threads": 64, + "duration": "5s", + "pipeline": 16, + "bandwidth": "51.04MB/s", + "input_bw": "", + "reconnects": 0, + "status_2xx": 1372407, + "status_3xx": 0, + "status_4xx": 0, + "status_5xx": 0 } ] \ No newline at end of file diff --git a/site/data/static-16384.json b/site/data/static-16384.json index 625992d7..18cff4c6 100644 --- a/site/data/static-16384.json +++ b/site/data/static-16384.json @@ -798,5 +798,25 @@ "status_3xx": 0, "status_4xx": 0, "status_5xx": 0 + }, + { + "framework": "Fletch", + "language": "Dart", + "rps": 147628, + "avg_latency": "20.51ms", + "p99_latency": "135.50ms", + "cpu": "1327.7%", + "memory": "1.2GiB", + "connections": 16384, + "threads": 64, + "duration": "5s", + "pipeline": 1, + "bandwidth": "2.29GB/s", + "input_bw": "8.02MB/s", + "reconnects": 0, + "status_2xx": 738141, + "status_3xx": 0, + "status_4xx": 0, + "status_5xx": 0 } ] \ No newline at end of file diff --git a/site/data/static-4096.json b/site/data/static-4096.json index 1ef28f4b..fd018aff 100644 --- a/site/data/static-4096.json +++ b/site/data/static-4096.json @@ -798,5 +798,25 @@ "status_3xx": 0, "status_4xx": 0, "status_5xx": 0 + }, + { + "framework": "Fletch", + "language": "Dart", + "rps": 172174, + "avg_latency": "7.39ms", + "p99_latency": "14.10ms", + "cpu": "1337.5%", + "memory": "1.4GiB", + "connections": 4096, + "threads": 64, + "duration": "5s", + "pipeline": 1, + "bandwidth": "2.72GB/s", + "input_bw": "9.36MB/s", + "reconnects": 0, + "status_2xx": 860871, + "status_3xx": 0, + "status_4xx": 0, + "status_5xx": 0 } ] \ No newline at end of file diff --git a/site/data/upload-256.json b/site/data/upload-256.json index bcd2bcaa..79105623 100644 --- a/site/data/upload-256.json +++ b/site/data/upload-256.json @@ -858,5 +858,25 @@ "status_3xx": 0, "status_4xx": 0, "status_5xx": 0 + }, + { + "framework": "Fletch", + "language": "Dart", + "rps": 100, + "avg_latency": "1.34s", + "p99_latency": "4.88s", + "cpu": "467.8%", + "memory": "7.9GiB", + "connections": 256, + "threads": 64, + "duration": "5s", + "pipeline": 1, + "bandwidth": "19.62KB/s", + "input_bw": "1.95GB/s", + "reconnects": 0, + "status_2xx": 500, + "status_3xx": 0, + "status_4xx": 0, + "status_5xx": 0 } ] \ No newline at end of file diff --git a/site/data/upload-512.json b/site/data/upload-512.json index ef8a6dca..89c53842 100644 --- a/site/data/upload-512.json +++ b/site/data/upload-512.json @@ -858,5 +858,25 @@ "status_3xx": 0, "status_4xx": 0, "status_5xx": 0 + }, + { + "framework": "Fletch", + "language": "Dart", + "rps": 97, + "avg_latency": "1.62s", + "p99_latency": "5.00s", + "cpu": "442.9%", + "memory": "8.0GiB", + "connections": 512, + "threads": 64, + "duration": "5s", + "pipeline": 1, + "bandwidth": "19.11KB/s", + "input_bw": "1.89GB/s", + "reconnects": 0, + "status_2xx": 487, + "status_3xx": 0, + "status_4xx": 0, + "status_5xx": 0 } ] \ No newline at end of file diff --git a/site/data/upload-64.json b/site/data/upload-64.json index c24b923d..0360c427 100644 --- a/site/data/upload-64.json +++ b/site/data/upload-64.json @@ -858,5 +858,25 @@ "status_3xx": 0, "status_4xx": 0, "status_5xx": 0 + }, + { + "framework": "Fletch", + "language": "Dart", + "rps": 145, + "avg_latency": "427.12ms", + "p99_latency": "1.62s", + "cpu": "595.7%", + "memory": "6.3GiB", + "connections": 64, + "threads": 64, + "duration": "5s", + "pipeline": 1, + "bandwidth": "28.53KB/s", + "input_bw": "2.83GB/s", + "reconnects": 0, + "status_2xx": 727, + "status_3xx": 0, + "status_4xx": 0, + "status_5xx": 0 } ] \ No newline at end of file diff --git a/site/static/logs/async-db/1024/fletch.log b/site/static/logs/async-db/1024/fletch.log new file mode 100644 index 00000000..e69de29b diff --git a/site/static/logs/async-db/512/fletch.log b/site/static/logs/async-db/512/fletch.log new file mode 100644 index 00000000..e69de29b diff --git a/site/static/logs/baseline/16384/fletch.log b/site/static/logs/baseline/16384/fletch.log new file mode 100644 index 00000000..e69de29b diff --git a/site/static/logs/baseline/4096/fletch.log b/site/static/logs/baseline/4096/fletch.log new file mode 100644 index 00000000..e69de29b diff --git a/site/static/logs/baseline/512/fletch.log b/site/static/logs/baseline/512/fletch.log new file mode 100644 index 00000000..e69de29b diff --git a/site/static/logs/compression/16384/fletch.log b/site/static/logs/compression/16384/fletch.log new file mode 100644 index 00000000..e69de29b diff --git a/site/static/logs/compression/4096/fletch.log b/site/static/logs/compression/4096/fletch.log new file mode 100644 index 00000000..e69de29b diff --git a/site/static/logs/json/16384/fletch.log b/site/static/logs/json/16384/fletch.log new file mode 100644 index 00000000..e69de29b diff --git a/site/static/logs/json/4096/fletch.log b/site/static/logs/json/4096/fletch.log new file mode 100644 index 00000000..e69de29b diff --git a/site/static/logs/limited-conn/4096/fletch.log b/site/static/logs/limited-conn/4096/fletch.log new file mode 100644 index 00000000..e69de29b diff --git a/site/static/logs/limited-conn/512/fletch.log b/site/static/logs/limited-conn/512/fletch.log new file mode 100644 index 00000000..e69de29b diff --git a/site/static/logs/mixed/16384/fletch.log b/site/static/logs/mixed/16384/fletch.log new file mode 100644 index 00000000..3f056aa0 --- /dev/null +++ b/site/static/logs/mixed/16384/fletch.log @@ -0,0 +1,7 @@ +evacuation failed +evacuation failed +evacuation failed +evacuation failed +evacuation failed +evacuation failed +evacuation failed diff --git a/site/static/logs/mixed/4096/fletch.log b/site/static/logs/mixed/4096/fletch.log new file mode 100644 index 00000000..e69de29b diff --git a/site/static/logs/noisy/16384/fletch.log b/site/static/logs/noisy/16384/fletch.log new file mode 100644 index 00000000..e69de29b diff --git a/site/static/logs/noisy/4096/fletch.log b/site/static/logs/noisy/4096/fletch.log new file mode 100644 index 00000000..e69de29b diff --git a/site/static/logs/noisy/512/fletch.log b/site/static/logs/noisy/512/fletch.log new file mode 100644 index 00000000..e69de29b diff --git a/site/static/logs/pipelined/16384/fletch.log b/site/static/logs/pipelined/16384/fletch.log new file mode 100644 index 00000000..e69de29b diff --git a/site/static/logs/pipelined/4096/fletch.log b/site/static/logs/pipelined/4096/fletch.log new file mode 100644 index 00000000..e69de29b diff --git a/site/static/logs/pipelined/512/fletch.log b/site/static/logs/pipelined/512/fletch.log new file mode 100644 index 00000000..e69de29b diff --git a/site/static/logs/static/16384/fletch.log b/site/static/logs/static/16384/fletch.log new file mode 100644 index 00000000..e69de29b diff --git a/site/static/logs/static/4096/fletch.log b/site/static/logs/static/4096/fletch.log new file mode 100644 index 00000000..e69de29b diff --git a/site/static/logs/upload/256/fletch.log b/site/static/logs/upload/256/fletch.log new file mode 100644 index 00000000..e69de29b diff --git a/site/static/logs/upload/512/fletch.log b/site/static/logs/upload/512/fletch.log new file mode 100644 index 00000000..e69de29b diff --git a/site/static/logs/upload/64/fletch.log b/site/static/logs/upload/64/fletch.log new file mode 100644 index 00000000..e69de29b