From c82b9925d30a2a70bdaf61a0fef8dbfec3f32db2 Mon Sep 17 00:00:00 2001 From: Nevindra Date: Fri, 9 Oct 2026 16:38:43 +0700 Subject: [PATCH 1/5] nilo: re-pin to Zig 0.17 nilo, add HTTP/2, h2c and unary gRPC profiles Pin nilo at c4e2d08 (Zig 0.17.0) and build it with http2, tls and libdeflate. Serve h2c on 8080 and 8082 and HTTP/2 over TLS on 8443, with /baseline2, /static and benchmark.BenchmarkService/GetSum. Set zio to work stealing, as a measurement of the async-db gap, and subscribe to the six new profiles. --- frameworks/nilo/Dockerfile | 14 +-- frameworks/nilo/build.zig | 34 +++++++- frameworks/nilo/build.zig.zon | 10 ++- frameworks/nilo/meta.json | 10 ++- frameworks/nilo/src/main.zig | 156 +++++++++++++++++++++++++++------- site/data/tls/nilo.json | 5 ++ 6 files changed, 183 insertions(+), 46 deletions(-) create mode 100644 site/data/tls/nilo.json diff --git a/frameworks/nilo/Dockerfile b/frameworks/nilo/Dockerfile index 96dbbf520..fa15255b4 100644 --- a/frameworks/nilo/Dockerfile +++ b/frameworks/nilo/Dockerfile @@ -1,9 +1,9 @@ -# nilo — a toolkit for Zig 0.16 whose largest module is an HTTP server on +# nilo, a toolkit for Zig 0.17 whose largest module is an HTTP server on # zio fibers. One static binary, built from the commit `build.zig.zon` pins. FROM alpine:3.20 AS build ARG TARGETARCH -ARG ZIG_VERSION=0.16.0 +ARG ZIG_VERSION=0.17.0 RUN apk add --no-cache ca-certificates curl git tar xz # The official toolchain, for the arch Buildx is building. @@ -22,9 +22,11 @@ WORKDIR /server COPY build.zig build.zig.zon ./ COPY src ./src -# nilo and its one dependency (zio) come from the pin in build.zig.zon; the -# Postgres driver behind nilo_sql is fetched because build.zig asks for it. -# Static against musl, so the runtime image needs nothing. +# nilo and zio come from the pins in build.zig.zon. build.zig asks nilo for +# four flags, and each fetches what it needs: the Postgres and SQLite drivers +# behind nilo_sql, tls.zig for the TLS listeners, libdeflate for gzip. HTTP/2 +# and gRPC (`http2`) fetch nothing. Static against musl, so the runtime image +# needs nothing. RUN set -eu; \ case "${TARGETARCH:-amd64}" in \ # `+aes+pclmul` is not decoration. Zig's `x86_64_v3` level carries @@ -44,5 +46,5 @@ RUN set -eu; \ FROM alpine:3.20 COPY --from=build /server/zig-out/bin/nilo-arena /nilo-arena -EXPOSE 8080 8081 +EXPOSE 8080 8081 8082 8443 ENTRYPOINT ["/nilo-arena"] diff --git a/frameworks/nilo/build.zig b/frameworks/nilo/build.zig index 0f521e454..3ccd38c26 100644 --- a/frameworks/nilo/build.zig +++ b/frameworks/nilo/build.zig @@ -9,11 +9,36 @@ pub fn build(b: *std.Build) void { const target = b.standardTargetOptions(.{}); const optimize = b.standardOptimizeOption(.{}); - // `.tls = true` is what makes the TLS listener on 8081 exist at all: the + // Four flags, each of which keeps its dependency out of a build that does + // not ask: + // + // `.tls = true` makes the TLS listeners on 8081 and 8443 exist at all: the // library behind it is fetched and linked only for a dependent that asks - // (ADR 0288), and a build without it refuses `.tls` at `listen()` rather + // (ADR 212), and a build without it refuses `.tls` at `listen()` rather // than serving cleartext on a port the entry believed was encrypted. - const nilo = b.dependency("nilo", .{ .target = target, .optimize = optimize, .sql = true, .tls = true }); + // + // `.http2 = true` builds HTTP/2 and gRPC into the one server (ADR 259, + // ADR 220): a plain listener tells h2c from HTTP/1.1 by the first bytes, + // and a TLS one offers `h2` and `http/1.1` by ALPN. It brings no + // dependency, only code. + // + // `.libdeflate = true` makes `app.compress` gzip with libdeflate instead of + // `std.flate` (ADR 248), which is what `json-comp` spends its time on. + const nilo = b.dependency("nilo", .{ + .target = target, + .optimize = optimize, + .sql = true, + .tls = true, + .http2 = true, + .libdeflate = true, + }); + + // zio itself, at the commit nilo pins, because `zio_options` is typed + // `zio.Options` and nilo does not re-export zio. The arguments are the + // ones nilo's own build passes, so this is the same zio nilo links and not + // a second copy; the scheduling the program runs is the root file's + // `zio_options`, which overrides this build option. + const zio = b.dependency("zio", .{ .target = target, .optimize = optimize, .scheduling = .pinned }); const exe = b.addExecutable(.{ .name = "nilo-arena", @@ -24,10 +49,11 @@ pub fn build(b: *std.Build) void { // A release build strips, the way nilo's own measured binaries // do: a panic still names the request (`nilo.panic`), and the // board never opens a debugger. - .strip = optimize != .Debug, + .strip = optimize != .debug, .imports = &.{ .{ .name = "nilo_http", .module = nilo.module("nilo_http") }, .{ .name = "nilo_sql", .module = nilo.module("nilo_sql") }, + .{ .name = "zio", .module = zio.module("zio") }, }, }), }); diff --git a/frameworks/nilo/build.zig.zon b/frameworks/nilo/build.zig.zon index f9b1bf484..6f1483cc6 100644 --- a/frameworks/nilo/build.zig.zon +++ b/frameworks/nilo/build.zig.zon @@ -1,15 +1,19 @@ .{ .name = .nilo_arena, .version = "0.0.0", - .minimum_zig_version = "0.16.0", + .minimum_zig_version = "0.17.0", .fingerprint = 0x31b5705688860733, .dependencies = .{ // Pinned to a commit, not a branch, so the build the board ran is // the build the row describes. Move both lines together: // zig fetch --save=nilo git+https://github.com/nevindra/nilo# .nilo = .{ - .url = "git+https://github.com/nevindra/nilo#224a507209b9d4d66f8d6e90406d00a394d14656", - .hash = "nilo-0.5.0-5HEqwlFaWQCQKkgQTyL_cehVbhjE2VRsdMlX2g2i2H38", + .url = "git+https://github.com/nevindra/nilo#c4e2d0852bfab4ef0e737414b0c2ea9a63b2c8ca", + .hash = "nilo-0.7.0-5HEqwmx4lwAs2v0-m7oxBCSGkSdtpMVvYovB-PyGex8J", + }, + .zio = .{ + .url = "git+https://github.com/lalinsky/zio?ref=main#3bbd74d68a889e5d4da7274afdc7c7617ec614d6", + .hash = "zio-0.19.0-xHbVVMFBLACx1T0028HttNTseV6bDeL0AI4id51AHx57", }, }, .paths = .{ "build.zig", "build.zig.zon", "src" }, diff --git a/frameworks/nilo/meta.json b/frameworks/nilo/meta.json index a02ebf049..2b1fa9f2a 100644 --- a/frameworks/nilo/meta.json +++ b/frameworks/nilo/meta.json @@ -10,7 +10,7 @@ "request": true, "response": true }, - "description": "A toolkit for Zig 0.16 whose largest module is an HTTP/1.1 server on zio fibers (io_uring, epoll, kqueue). A plain function is a route: its argument list is the routing, the typed input, the 400 for anything that does not fit, and the OpenAPI document. One allocation per request, 4,669 bytes per idle connection, and a wait parks the fiber rather than the thread. Serves cleartext on 8080 and TLS 1.3 on 8081 from one process. Refuses HTTP/2, HTTP/3, gRPC and templates on the record, which is why it sits out those profiles.", + "description": "A toolkit for Zig 0.17 whose largest module is an HTTP server on zio fibers (io_uring, epoll, kqueue). A plain function is a route: its argument list is the routing, the typed input, the 400 for anything that does not fit, and the OpenAPI document. One allocation per request, 4,669 bytes per idle connection, and a wait parks the fiber rather than the thread. Serves HTTP/1.1 and h2c on 8080, TLS 1.3 on 8081, h2c on 8082 and HTTP/2 over TLS with ALPN on 8443 from one process. HTTP/2 and unary gRPC are behind the -Dhttp2 build flag, which this entry builds with; gRPC is unary only, so the streaming profiles are not subscribed. Refuses HTTP/3 and templates on the record, which is why it sits out those profiles.", "repo": "https://github.com/nevindra/nilo", "enabled": true, "tests": [ @@ -27,7 +27,13 @@ "8gbit", "echo-ws", "echo-ws-pipeline", - "echo-ws-limited" + "echo-ws-limited", + "baseline-h2", + "static-h2", + "baseline-h2c", + "json-h2c", + "unary-grpc", + "unary-grpc-tls" ], "maintainers": [ "nevindra" diff --git a/frameworks/nilo/src/main.zig b/frameworks/nilo/src/main.zig index 478ccb846..acb330503 100644 --- a/frameworks/nilo/src/main.zig +++ b/frameworks/nilo/src/main.zig @@ -17,28 +17,51 @@ //! 10,000 closes the rest at accept (ADR 0265). The deploying guide is where //! that knob is documented, which is what standard mode asks for. //! -//! **Two listeners, and the second is why this file needs a recent nilo.** -//! 8080 carries cleartext and 8081 carries TLS, from one process, because -//! the board restarts the container per profile and tells the binary -//! nothing about which profile is coming (ADR 0289). The certificate is the -//! board's, mounted at `/certs`, and its paths are overridable the way the -//! `json-tls` guidelines say frameworks usually do it. +//! **Four listeners, from one process**, because the board restarts the +//! container per profile and tells the binary nothing about which profile is +//! coming (ADR 213). 8080 is cleartext HTTP/1.1, and also h2c for the gRPC +//! profiles: a build with `.http2 = true` tells an HTTP/2 connection from an +//! HTTP/1.1 one by its first bytes (ADR 259, ADR 220). 8081 is HTTP/1.1 over +//! TLS. 8082 is h2c with prior knowledge. 8443 is HTTP/2 over TLS, chosen by +//! ALPN. They share one route table, so `/baseline2`, `/json/{count}` and +//! `/static/*` answer on every port. The certificate is the board's, mounted +//! at `/certs`, and its paths are overridable the way the `json-tls` +//! guidelines say frameworks usually do it. //! //! **`-Dcpu` is load-bearing here and the Dockerfile says so.** Zig's //! `x86_64_v3` carries no `aes` and no `pclmul`, and `std.crypto`'s -//! AES-256-GCM without them is seventy times slower — enough that `8gbit` +//! AES-256-GCM without them is seventy times slower, enough that `8gbit` //! delivers 39% of its offered rate at a six-second p99. The measured run //! is in `bench/result/http.md`. //! +//! **Scheduling is zio's default here, not nilo's.** nilo builds zio with +//! `.pinned` (a connection stays on the thread it was dealt to), and says an +//! application's own `zio_options` can override it. This entry does, below, +//! with `.work_stealing`. See the comment on `zio_options`. +//! //! Profiles nilo does not subscribe to, and why: `fortunes` in standard -//! mode needs a template engine, refused on the record (ADR 0028), and so -//! are the HTTP/2, HTTP/3 and gRPC profiles. +//! mode needs a template engine, refused on the record (README, "What it won't do"), and so is +//! HTTP/3. The gRPC profiles are unary only; the streaming ones are not +//! served (ADR 220). const std = @import("std"); const nilo = @import("nilo_http"); const sql = @import("nilo_sql"); +const zio = @import("zio"); const fail = nilo.fail; +/// zio's scheduling, read by zio from the root module the way std reads +/// `std_options`. nilo builds its own zio `.pinned` (ADR 199), so a task never +/// leaves the thread it was spawned on. This entry asks for `.work_stealing`, +/// which is zio's own default, as a measured hypothesis and not a tuning +/// claim: on the board's `async-db` profile nilo read 57k req/s at 830% CPU +/// where dusty, also on zio and running `.work_stealing`, read 290k at 4,606%. +/// A pinned fiber that waits on Postgres cannot be picked up by an idle +/// thread; a stolen one can. Whether that is the gap is what this run on the +/// board's 64 cores is for. Every other profile is expected to move little, +/// and the board will say if one does not. +pub const zio_options: zio.Options = .{ .scheduling = .work_stealing }; + pub const std_options = nilo.std_options; pub const std_options_debug_io = nilo.debug_io; pub const panic = nilo.panic; @@ -194,14 +217,15 @@ fn noDb() Listing { return nothing; } -// ---- json-comp, json-tls ---- +// ---- json-comp, json-tls, json-h2c ---- // // `GET /json/{count}?m={multiplier}` answers the first `count` items of the // board's 50-item dataset with `total = price * quantity * m` added to each, -// wrapped in `{items, count}`. The same route serves both profiles: over +// wrapped in `{items, count}`. The same route serves all three profiles: over // 8081 with TLS and no `Accept-Encoding` it is `json-tls`, and over 8080 // with `Accept-Encoding: gzip, br` it is `json-comp`, where the answer goes -// out gzipped because `app.compress` is on. +// out gzipped because `app.compress` is on, with libdeflate because the +// build asked for it (ADR 248). Over 8082 with HTTP/2 it is `json-h2c`. // // The dataset is read once at startup and the arithmetic is done per // request, which is what both profiles' anti-cheat rules require: a @@ -288,6 +312,54 @@ fn echoBody(c: *nilo.Ctx) !void { try c.send(200, "application/octet-stream", body.view()); } +// ---- baseline-h2, baseline-h2c ---- +// +// `GET /baseline2?a=1&b=1` answers the sum as `text/plain`, the same +// workload as `/baseline11` over HTTP/2: on 8443 with TLS and ALPN, and on +// 8082 as h2c with prior knowledge. It is the same function as the HTTP/1.1 +// route, because the protocol is the listener's business and not the +// handler's. + +// ---- static-h2 ---- +// +// `GET /static/{file}` for the twenty files in `/data/static`, over 8443. +// `reload = true` is what the profile's rule asks for: the cache must follow +// the disk, "replace a file and the next response must carry the new bytes", +// and nilo's default holds the directory in memory from startup. With it on, +// every file is opened per request (ADR 009), which costs the profile the +// gzipped copy `app.static` would otherwise have made at load. Compression is +// optional there, and the pre-compressed `.br` and `.gz` files on disk are +// not selected: nilo has no API for that, and selecting them by hand is +// what standard mode does not allow. + +// ---- unary-grpc, unary-grpc-tls ---- +// +// `benchmark.BenchmarkService/GetSum`, from `requests/benchmark.proto`: +// `SumRequest{a, b}` in, `SumReply{result}` out, as a unary call over h2c on +// 8080 and over h2 with TLS on 8443. The service is a struct and a method is +// a function from a message to a message (ADR 258), so the call is an +// ordinary route: it takes the message, nilo frames the reply and sends +// `grpc-status` as a trailer. + +const SumRequest = struct { + pub const wire = .{ .a = 1, .b = 2 }; + a: i32 = 0, + b: i32 = 0, +}; + +const SumReply = struct { + pub const wire = .{ .result = 1 }; + result: i32 = 0, +}; + +const BenchmarkService = struct { + pub const nilo_service = "benchmark.BenchmarkService"; + + pub fn getSum(in: SumRequest) SumReply { + return .{ .result = in.a +% in.b }; + } +}; + // ---- echo-ws ---- // // `/ws` upgrades and echoes every message back with the opcode it arrived @@ -337,10 +409,22 @@ pub fn main(init: std.process.Init) !void { try app.get("/baseline11", baselineGet); try app.post("/baseline11", baselinePost); + try app.get("/baseline2", baselineGet); try app.get("/pipeline", pipeline); try app.get("/delay/:ms", delay); try app.get("/ws", ws); try app.post("/echo", echoBody); + try app.rpc(BenchmarkService); + + // The board mounts `/data/static` for the static profiles. A developer + // running this by hand from the repository does not have it, and the + // other profiles should not die for want of it. + const static_dir = env.getPosix("STATIC_DIR") orelse "/data/static"; + if (readable(gpa, static_dir)) { + try app.staticWith("/static", static_dir, .{ .reload = true }); + } else { + std.log.warn("no static directory at \"{s}\", so /static is a 404: static-h2 cannot be served.", .{static_dir}); + } // The 50-item dataset the board mounts. Both `/json` profiles need it, // and a container without it should say so once here rather than answer @@ -393,40 +477,46 @@ pub fn main(init: std.process.Init) !void { try app.get("/async-db", noDb); } - // No logger, for the reason `bench/main.zig` gives: a line per request - // would measure the logger. `max_connections` is the one setting off - // its default, and the header comment says why. - // 8081 with TLS beside 8080 in cleartext, which `json-tls` and `8gbit` - // both want while the other nine profiles want the plain one (ADR 0289). - // ALPN advertises `http/1.1` only, which is what those profiles ask for - // and what nilo's TLS listener does. + // 8080 carries HTTP/1.1 and h2c (gRPC); the `also` listeners are 8082 + // (h2c, nothing else on it), 8081 (TLS, which `json-tls` and `8gbit` use + // and which advertises `http/1.1` when a client offers only that) and + // 8443 (TLS, `h2` first by ALPN). In a build with `.http2 = true` a TLS + // listener offers both by ALPN and serves what the client chose, so the + // two TLS ports differ only in who connects to them. const cert = env.getPosix("TLS_CERT") orelse "/certs/server.crt"; const key = env.getPosix("TLS_KEY") orelse "/certs/server.key"; - const secure: []const nilo.Options.Listener = if (readable(gpa, cert) and readable(gpa, key)) - &.{.{ .address = "0.0.0.0", .port = 8081, .tls = .{ .cert = cert, .key = key } }} - else secure: { + var also: [3]nilo.Options.Listener = undefined; + var n_also: usize = 0; + also[n_also] = .{ .address = "0.0.0.0", .port = 8082 }; + n_also += 1; + if (readable(gpa, cert) and readable(gpa, key)) { + also[n_also] = .{ .address = "0.0.0.0", .port = 8081, .tls = .{ .cert = cert, .key = key } }; + n_also += 1; + also[n_also] = .{ .address = "0.0.0.0", .port = 8443, .tls = .{ .cert = cert, .key = key } }; + n_also += 1; + } else { // Loud, and then up anyway. The board always mounts the pair, so - // reaching this line means the mount moved — and refusing to start - // would take the nine profiles that need no certificate down with - // the two that do. + // reaching this line means the mount moved, and refusing to start + // would take the profiles that need no certificate down with the + // ones that do. std.log.warn( - "no certificate at \"{s}\" and \"{s}\", so there is no TLS listener on 8081: " ++ - "json-tls and 8gbit cannot be served. Every cleartext profile is unaffected.", + "no certificate at \"{s}\" and \"{s}\", so there is no TLS listener on 8081 or 8443: " ++ + "json-tls, 8gbit, baseline-h2, static-h2 and unary-grpc-tls cannot be served. " ++ + "Every cleartext profile is unaffected.", .{ cert, key }, ); - break :secure &.{}; - }; + } // No logger, for the reason `bench/main.zig` gives: a line per request // would measure the logger. `max_connections` is the one setting off // its default, and the header comment says why. It counts the sockets // this process holds rather than the sockets a port holds, so it is not - // doubled by the second listener. + // multiplied by the extra listeners. try app.listen(.{ .address = "0.0.0.0", .port = 8080, .max_connections = 65_536, - .also = secure, + .also = also[0..n_also], }); } @@ -437,6 +527,10 @@ test "the baseline sum is the two operands, plus the body on a POST" { try std.testing.expectEqual(@as(i64, 55), baselineGet(.{ .value = .{ .a = 13, .b = 42 } }).value); } +test "the gRPC sum is the two operands" { + try std.testing.expectEqual(@as(i32, 3), BenchmarkService.getSum(.{ .a = 1, .b = 2 }).result); +} + test "a zero delay answers zero without waiting" { try std.testing.expectEqual(@as(i64, 0), (try delay(0)).value); } diff --git a/site/data/tls/nilo.json b/site/data/tls/nilo.json new file mode 100644 index 000000000..78c129ca9 --- /dev/null +++ b/site/data/tls/nilo.json @@ -0,0 +1,5 @@ +{ + "framework": "nilo", + "tls": "pass", + "check": "none" +} From b88886000cb201013811e8d2444ce23596311d60 Mon Sep 17 00:00:00 2001 From: Nevindra Date: Fri, 9 Oct 2026 22:07:48 +0700 Subject: [PATCH 2/5] nilo: re-pin to 077b4a8, return to pinned scheduling, follow the static disk The work-stealing override from the last run is gone: it did not close the async-db gap and it scattered every HTTP/2 stream off its connection's executor. The pin brings inline HTTP/2 calls for routes that never wait, JSON written once into the arena, a compressor slot per executor, and staticWith(.follow = true), which keeps the directory in memory and in step with the disk and serves the .br/.gz siblings itself. The database profiles print pool statistics to the log when DATABASE_URL is set. --- frameworks/nilo/Dockerfile | 2 +- frameworks/nilo/build.zig | 8 - frameworks/nilo/build.zig.zon | 8 +- frameworks/nilo/src/main.zig | 372 +++++++++++++++++++++++++++++++--- 4 files changed, 343 insertions(+), 47 deletions(-) diff --git a/frameworks/nilo/Dockerfile b/frameworks/nilo/Dockerfile index fa15255b4..b9e9c2b3f 100644 --- a/frameworks/nilo/Dockerfile +++ b/frameworks/nilo/Dockerfile @@ -22,7 +22,7 @@ WORKDIR /server COPY build.zig build.zig.zon ./ COPY src ./src -# nilo and zio come from the pins in build.zig.zon. build.zig asks nilo for +# nilo comes from the pin in build.zig.zon, and zio from nilo's. build.zig asks nilo for # four flags, and each fetches what it needs: the Postgres and SQLite drivers # behind nilo_sql, tls.zig for the TLS listeners, libdeflate for gzip. HTTP/2 # and gRPC (`http2`) fetch nothing. Static against musl, so the runtime image diff --git a/frameworks/nilo/build.zig b/frameworks/nilo/build.zig index 3ccd38c26..c1f4b6df4 100644 --- a/frameworks/nilo/build.zig +++ b/frameworks/nilo/build.zig @@ -33,13 +33,6 @@ pub fn build(b: *std.Build) void { .libdeflate = true, }); - // zio itself, at the commit nilo pins, because `zio_options` is typed - // `zio.Options` and nilo does not re-export zio. The arguments are the - // ones nilo's own build passes, so this is the same zio nilo links and not - // a second copy; the scheduling the program runs is the root file's - // `zio_options`, which overrides this build option. - const zio = b.dependency("zio", .{ .target = target, .optimize = optimize, .scheduling = .pinned }); - const exe = b.addExecutable(.{ .name = "nilo-arena", .root_module = b.createModule(.{ @@ -53,7 +46,6 @@ pub fn build(b: *std.Build) void { .imports = &.{ .{ .name = "nilo_http", .module = nilo.module("nilo_http") }, .{ .name = "nilo_sql", .module = nilo.module("nilo_sql") }, - .{ .name = "zio", .module = zio.module("zio") }, }, }), }); diff --git a/frameworks/nilo/build.zig.zon b/frameworks/nilo/build.zig.zon index 6f1483cc6..70c2ebf84 100644 --- a/frameworks/nilo/build.zig.zon +++ b/frameworks/nilo/build.zig.zon @@ -8,12 +8,8 @@ // the build the row describes. Move both lines together: // zig fetch --save=nilo git+https://github.com/nevindra/nilo# .nilo = .{ - .url = "git+https://github.com/nevindra/nilo#c4e2d0852bfab4ef0e737414b0c2ea9a63b2c8ca", - .hash = "nilo-0.7.0-5HEqwmx4lwAs2v0-m7oxBCSGkSdtpMVvYovB-PyGex8J", - }, - .zio = .{ - .url = "git+https://github.com/lalinsky/zio?ref=main#3bbd74d68a889e5d4da7274afdc7c7617ec614d6", - .hash = "zio-0.19.0-xHbVVMFBLACx1T0028HttNTseV6bDeL0AI4id51AHx57", + .url = "git+https://github.com/nevindra/nilo#077b4a81cd4c146664b1b4cbdae4631420759e3f", + .hash = "nilo-0.7.0-5HEqwrJznAD77mTEmYOkNsg1eugyIHlp0NF_wyAb67ur", }, }, .paths = .{ "build.zig", "build.zig.zon", "src" }, diff --git a/frameworks/nilo/src/main.zig b/frameworks/nilo/src/main.zig index acb330503..a79f762f2 100644 --- a/frameworks/nilo/src/main.zig +++ b/frameworks/nilo/src/main.zig @@ -34,10 +34,11 @@ //! delivers 39% of its offered rate at a six-second p99. The measured run //! is in `bench/result/http.md`. //! -//! **Scheduling is zio's default here, not nilo's.** nilo builds zio with -//! `.pinned` (a connection stays on the thread it was dealt to), and says an -//! application's own `zio_options` can override it. This entry does, below, -//! with `.work_stealing`. See the comment on `zio_options`. +//! **Scheduling is nilo's, `.pinned`** (a connection stays on the thread it +//! was dealt to, ADR 199). The previous run overrode it with zio's +//! `.work_stealing` to test the `async-db` gap; it did not close that gap +//! and it put every HTTP/2 profile at the bottom (a stream's call could not +//! stay on its connection's executor), so the override is gone. //! //! Profiles nilo does not subscribe to, and why: `fortunes` in standard //! mode needs a template engine, refused on the record (README, "What it won't do"), and so is @@ -47,21 +48,8 @@ const std = @import("std"); const nilo = @import("nilo_http"); const sql = @import("nilo_sql"); -const zio = @import("zio"); const fail = nilo.fail; -/// zio's scheduling, read by zio from the root module the way std reads -/// `std_options`. nilo builds its own zio `.pinned` (ADR 199), so a task never -/// leaves the thread it was spawned on. This entry asks for `.work_stealing`, -/// which is zio's own default, as a measured hypothesis and not a tuning -/// claim: on the board's `async-db` profile nilo read 57k req/s at 830% CPU -/// where dusty, also on zio and running `.work_stealing`, read 290k at 4,606%. -/// A pinned fiber that waits on Postgres cannot be picked up by an idle -/// thread; a stolen one can. Whether that is the gap is what this run on the -/// board's 64 cores is for. Every other profile is expected to move little, -/// and the board will say if one does not. -pub const zio_options: zio.Options = .{ .scheduling = .work_stealing }; - pub const std_options = nilo.std_options; pub const std_options_debug_io = nilo.debug_io; pub const panic = nilo.panic; @@ -133,6 +121,310 @@ fn delay(ms: u32) !Number { return .{ .value = ms }; } + +// ---- async-db instrumentation: one line a second in the container's log ---- +// +// What the board publishes for a profile is its log, so a run that comes out +// slow can say why. Every counter is one relaxed atomic add on the request +// path, and the line is written by one plain OS thread that sleeps a second. + +const Stats = struct { + const sub = 8; // buckets per power of two + const buckets = 24 * sub; // 1 us .. 16 s + answered: std.atomic.Value(u64) = .init(0), + inflight: std.atomic.Value(i64) = .init(0), + max_inflight: std.atomic.Value(i64) = .init(0), + stmt_hist: [buckets]std.atomic.Value(u32) = @splat(.init(0)), + req_hist: [buckets]std.atomic.Value(u32) = @splat(.init(0)), + stmt_sum: std.atomic.Value(u64) = .init(0), + req_sum: std.atomic.Value(u64) = .init(0), + stmt_n: std.atomic.Value(u64) = .init(0), + + fn bucket(us: u64) usize { + if (us < sub) return @intCast(us); + const lg: u6 = @intCast(63 - @clz(us)); + const frac: u64 = (us >> (lg - 3)) & (sub - 1); + const b = (@as(usize, lg) - 2) * sub + @as(usize, @intCast(frac)); + return @min(b, buckets - 1); + } + + fn upper(b: usize) u64 { + if (b < sub) return b + 1; + const lg = b / sub + 2; + const frac = b % sub; + return (@as(u64, sub) + frac + 1) << @intCast(lg - 3); + } + + fn add(hist: *[buckets]std.atomic.Value(u32), us: u64) void { + _ = hist[bucket(us)].fetchAdd(1, .monotonic); + } + + /// Mean and p99 of what was added since the last call, and the histogram emptied. + fn drain(hist: *[buckets]std.atomic.Value(u32), sum: *std.atomic.Value(u64), n_out: *u64) struct { mean: u64, p99: u64 } { + var counts: [buckets]u32 = undefined; + var n: u64 = 0; + for (hist, &counts) |*h, *c| { + c.* = h.swap(0, .monotonic); + n += c.*; + } + const total = sum.swap(0, .monotonic); + n_out.* = n; + if (n == 0) return .{ .mean = 0, .p99 = 0 }; + const want = n - n / 100; + var seen: u64 = 0; + var p99: u64 = 0; + for (counts, 0..) |c, b| { + seen += c; + if (seen >= want) { + p99 = upper(b); + break; + } + } + return .{ .mean = total / n, .p99 = p99 }; + } +}; + + +/// What the operating system says about this process's threads, read from +/// /proc once a second: where the CPU went (a few hot threads or all of +/// them), how often they slept, and how many pages they faulted in. +const Deltas = struct { minflt: u64, vol: u64, invol: u64 }; + +const Proc = struct { + const max_threads = 256; + tids: [max_threads]u32 = undefined, + ticks: [max_threads]u64 = @splat(0), + n: usize = 0, + minflt: u64 = 0, + vol: u64 = 0, + invol: u64 = 0, + /// Kernel io_uring workers seen among the threads: any at all says the ring backend is in use. + iou: usize = 0, + + /// A small /proc file read in one go, or null. /proc files report a size + /// of zero, so the usual read-the-whole-file calls do not take them. + fn readSmall(path: []const u8, buf: []u8) ?[]const u8 { + var z: [96]u8 = undefined; + if (path.len >= z.len) return null; + @memcpy(z[0..path.len], path); + z[path.len] = 0; + const zp: [*:0]const u8 = @ptrCast(&z); + const rc = std.os.linux.open(zp, .{ .ACCMODE = .RDONLY }, 0); + if (std.os.linux.errno(rc) != .SUCCESS) return null; + const fd: i32 = @intCast(rc); + defer _ = std.os.linux.close(fd); + const n = std.os.linux.read(fd, buf.ptr, buf.len); + if (std.os.linux.errno(n) != .SUCCESS) return null; + return buf[0..n]; + } + + fn field(text: []const u8, name: []const u8) u64 { + const at = std.mem.indexOf(u8, text, name) orelse return 0; + var rest = text[at + name.len ..]; + rest = std.mem.trimStart(u8, rest, " \t"); + const end = std.mem.indexOfAny(u8, rest, "\n \t") orelse rest.len; + return std.fmt.parseInt(u64, rest[0..end], 10) catch 0; + } + + /// Fills `cpu` (percent of one CPU per thread, descending) and returns + /// the number of threads, with the deltas of the three counters. + fn sample(self: *Proc, io: std.Io, secs_x100: u64, cpu: []u64, d: *Deltas) usize { + var dir = std.Io.Dir.cwd().openDir(io, "/proc/self/task", .{ .iterate = true }) catch |err| { + std.log.info("asyncdb: cannot read /proc/self/task: {s}", .{@errorName(err)}); + return 0; + }; + defer dir.close(io); + var it = dir.iterate(); + var count: usize = 0; + var iou: usize = 0; + var minflt: u64 = 0; + var vol: u64 = 0; + var invol: u64 = 0; + var path_buf: [64]u8 = undefined; + while (it.next(io) catch null) |entry| { + const tid = std.fmt.parseInt(u32, entry.name, 10) catch continue; + const stat_path = std.fmt.bufPrint(&path_buf, "/proc/self/task/{d}/stat", .{tid}) catch continue; + var stat_buf: [1024]u8 = undefined; + const stat = readSmall(stat_path, &stat_buf) orelse continue; + const close = std.mem.lastIndexOfScalar(u8, stat, ')') orelse continue; + if (std.mem.indexOf(u8, stat[0..close], "(iou-") != null) iou += 1; + var f = std.mem.tokenizeScalar(u8, stat[close + 1 ..], ' '); + var i: usize = 0; + var ut: u64 = 0; + var st: u64 = 0; + var mf: u64 = 0; + while (f.next()) |tok| : (i += 1) { + if (i == 7) mf = std.fmt.parseInt(u64, tok, 10) catch 0; + if (i == 11) ut = std.fmt.parseInt(u64, tok, 10) catch 0; + if (i == 12) st = std.fmt.parseInt(u64, tok, 10) catch 0; + } + minflt += mf; + const status_path = std.fmt.bufPrint(&path_buf, "/proc/self/task/{d}/status", .{tid}) catch continue; + var status_buf: [2048]u8 = undefined; + if (readSmall(status_path, &status_buf)) |status| { + vol += field(status, "voluntary_ctxt_switches:"); + invol += field(status, "nonvoluntary_ctxt_switches:"); + } + const now = ut + st; + var prev: u64 = 0; + var slot: ?usize = null; + for (self.tids[0..self.n], 0..) |t, k| if (t == tid) { + slot = k; + break; + }; + if (slot) |k| { + prev = self.ticks[k]; + self.ticks[k] = now; + } else if (self.n < max_threads) { + self.tids[self.n] = tid; + self.ticks[self.n] = now; + self.n += 1; + prev = now; + } + if (count < cpu.len) { + cpu[count] = (now -| prev) * 10_000 / @max(secs_x100, 1); + count += 1; + } + } + self.iou = iou; + d.minflt = minflt -| self.minflt; + d.vol = vol -| self.vol; + d.invol = invol -| self.invol; + self.minflt = minflt; + self.vol = vol; + self.invol = invol; + std.mem.sort(u64, cpu[0..count], {}, std.sort.desc(u64)); + return count; + } +}; + +var stats: Stats = .{}; +var stats_db: ?*sql.Db = null; + +fn statementTold(sent: sql.Sent) void { + Stats.add(&stats.stmt_hist, sent.micros); + _ = stats.stmt_sum.fetchAdd(sent.micros, .monotonic); +} + +fn requestStarted() i64 { + const now: i64 = @intCast(nilo.monotonicNanos()); + const in = stats.inflight.fetchAdd(1, .monotonic) + 1; + if (in > stats.max_inflight.load(.monotonic)) stats.max_inflight.store(in, .monotonic); + return now; +} + +fn requestEnded(started: i64) void { + const us: u64 = @intCast(@divTrunc(@as(i64, @intCast(nilo.monotonicNanos())) - started, 1000)); + _ = stats.inflight.fetchSub(1, .monotonic); + _ = stats.answered.fetchAdd(1, .monotonic); + Stats.add(&stats.req_hist, us); + _ = stats.req_sum.fetchAdd(us, .monotonic); +} + +fn statsThread() void { + var threaded: std.Io.Threaded = .init(std.heap.smp_allocator, .{}); + const io = threaded.io(); + var proc: Proc = .{}; + var sysctl: [16]u8 = undefined; + const disabled = Proc.readSmall("/proc/sys/kernel/io_uring_disabled", &sysctl) orelse "unreadable"; + std.log.info("asyncdb: kernel.io_uring_disabled={s} (0 means the ring backend can be used; 1 or 2 means zio falls back to epoll)", .{std.mem.trim(u8, disabled, " \n")}); + var last_ns: u64 = nilo.monotonicNanos(); + var cpu: [Proc.max_threads]u64 = undefined; + var last_answered: u64 = 0; + var last_stmts: usize = 0; + var last_waited: usize = 0; + var last_dropped: usize = 0; + var in_use_sum: u64 = 0; + var avail_sum: u64 = 0; + var samples: u64 = 0; + var tick: u32 = 0; + while (true) { + io.sleep(.fromMilliseconds(100), .awake) catch return; + const pool = (stats_db orelse continue).poolStats() orelse continue; + in_use_sum += pool.in_use; + avail_sum += pool.available; + samples += 1; + tick += 1; + if (tick < 10) continue; + tick = 0; + const now_ns = nilo.monotonicNanos(); + const secs_x100: u64 = (now_ns - last_ns) / 10_000_000; + last_ns = now_ns; + var delta: Deltas = undefined; + const nthreads = proc.sample(io, secs_x100, &cpu, &delta); + var total: u64 = 0; + var hot: usize = 0; + var warm: usize = 0; + for (cpu[0..nthreads]) |c| { + total += c; + if (c >= 5000) hot += 1; + if (c >= 1000) warm += 1; + } + var sn: u64 = 0; + var rn: u64 = 0; + const st = Stats.drain(&stats.stmt_hist, &stats.stmt_sum, &sn); + const rq = Stats.drain(&stats.req_hist, &stats.req_sum, &rn); + const answered = stats.answered.load(.monotonic); + const rate = answered - last_answered; + last_answered = answered; + const stmts = pool.statements -% last_stmts; + last_stmts = pool.statements; + const waited = pool.waited -% last_waited; + last_waited = pool.waited; + const dropped = pool.dropped -% last_dropped; + last_dropped = pool.dropped; + const mean_in_use = in_use_sum * 10 / @max(samples, 1); + const mean_avail = avail_sum * 10 / @max(samples, 1); + // hold: Little's law on the pool, mean connections in use over statements a second. + const hold_us: u64 = if (stmts > 0) mean_in_use * 100_000 / stmts else 0; + std.log.info( + "asyncdb: answered={d}/s inflight={d} (max {d}) pool size={d} open={d} in_use={d}.{d} idle={d}.{d} missing={d} " ++ + "waited={d} dropped={d} | statement mean={d}us p99={d}us | request mean={d}us p99={d}us | hold~{d}us", + .{ + rate, + stats.inflight.load(.monotonic), + stats.max_inflight.swap(0, .monotonic), + pool.size, + pool.size - pool.missing, + mean_in_use / 10, + mean_in_use % 10, + mean_avail / 10, + mean_avail % 10, + pool.missing, + waited, + dropped, + st.mean, + st.p99, + rq.mean, + rq.p99, + hold_us, + }, + ); + std.log.info( + "asyncdb: threads={d} cpu={d}% hot(>=50%)={d} warm(>=10%)={d} top=[{d},{d},{d},{d},{d},{d}]% sleeps={d}/s preempted={d}/s faults={d}/s io_uring_workers={d}", + .{ + nthreads, + total / 100, + hot, + warm, + cpu[0] / 100, + cpu[1] / 100, + cpu[2] / 100, + cpu[3] / 100, + cpu[4] / 100, + cpu[5] / 100, + delta.vol, + delta.invol, + delta.minflt, + proc.iou, + }, + ); + in_use_sum = 0; + avail_sum = 0; + samples = 0; + } +} + // ---- async-db ---- // // `GET /async-db?min=10&max=50&limit=20`: a range scan over `items` with the @@ -189,7 +481,10 @@ const Range = struct { limit: i32 = 50, }; + fn asyncDb(db: *sql.Db, c: *nilo.Ctx, q: nilo.Query(Range)) !Listing { + const started = requestStarted(); + defer requestEnded(started); const limit: usize = @intCast(std.math.clamp(q.value.limit, 1, 50)); const rows = db.select(Item, c, .{ .where = .{ .price = .{ .gte = q.value.min, .lte = q.value.max } }, @@ -247,6 +542,11 @@ const DatasetItem = struct { /// The dataset, held for the life of the process. A pointer, so it reaches a /// handler as a service rather than as a global the handler names. const Dataset = struct { + /// Read once at startup and never written, so a route that takes it + /// cannot wait on it, and HTTP/2 may run that route on the connection's + /// own fiber (ADR 260). + pub const nilo_never_waits = true; + items: []const DatasetItem, }; @@ -279,9 +579,9 @@ const Multiplier = struct { /// `count` is the path param, clamped to what the dataset holds. The board /// rotates 1, 5, 10, 15, 25, 40 and 50 through it. -fn jsonItems(data: *Dataset, c: *nilo.Ctx, count: usize, q: nilo.Query(Multiplier)) !JsonListing { +fn jsonItems(data: *Dataset, arena: std.mem.Allocator, count: usize, q: nilo.Query(Multiplier)) !JsonListing { const take = @min(count, data.items.len); - const out = try c.arena().alloc(JsonItem, take); + const out = try arena.alloc(JsonItem, take); for (data.items[0..take], out) |item, *listed| listed.* = .{ .id = item.id, .name = item.name, @@ -323,14 +623,14 @@ fn echoBody(c: *nilo.Ctx) !void { // ---- static-h2 ---- // // `GET /static/{file}` for the twenty files in `/data/static`, over 8443. -// `reload = true` is what the profile's rule asks for: the cache must follow -// the disk, "replace a file and the next response must carry the new bytes", -// and nilo's default holds the directory in memory from startup. With it on, -// every file is opened per request (ADR 009), which costs the profile the -// gzipped copy `app.static` would otherwise have made at load. Compression is -// optional there, and the pre-compressed `.br` and `.gz` files on disk are -// not selected: nilo has no API for that, and selecting them by hand is -// what standard mode does not allow. +// The profile's rule is that the cache must follow the disk, "replace a file +// and the next response must carry the new bytes", and nilo's default holds +// the directory in memory from startup. `follow = true` (ADR 277) is nilo's +// documented answer: the tree stays in memory and is read again when inotify +// says a file changed, and a response already being written finishes on the +// tree it began on. The `.br` and `.gz` files beside each original are served +// as its codings by `app.static` itself (ADR 273), chosen by the client's q +// values, so the entry selects nothing by hand. // ---- unary-grpc, unary-grpc-tls ---- // @@ -421,7 +721,7 @@ pub fn main(init: std.process.Init) !void { // other profiles should not die for want of it. const static_dir = env.getPosix("STATIC_DIR") orelse "/data/static"; if (readable(gpa, static_dir)) { - try app.staticWith("/static", static_dir, .{ .reload = true }); + try app.staticWith("/static", static_dir, .{ .follow = true }); } else { std.log.warn("no static directory at \"{s}\", so /static is a 404: static-h2 cannot be served.", .{static_dir}); } @@ -471,6 +771,9 @@ pub fn main(init: std.process.Init) !void { db = sql.Db.init(gpa, url, .{ .size = size }); db.checking(.{ .tables = &.{Item} }); has_db = true; + db.watching(statementTold); + stats_db = &db; + _ = std.Thread.spawn(.{}, statsThread, .{}) catch {}; try app.provide(&db); try app.get("/async-db", asyncDb); } else { @@ -508,14 +811,19 @@ pub fn main(init: std.process.Init) !void { } // No logger, for the reason `bench/main.zig` gives: a line per request - // would measure the logger. `max_connections` is the one setting off - // its default, and the header comment says why. It counts the sockets - // this process holds rather than the sockets a port holds, so it is not - // multiplied by the extra listeners. + // would measure the logger. `max_connections` is off its default, and + // the header comment says why. It counts the sockets this process holds + // rather than the sockets a port holds, so it is not multiplied by the + // extra listeners. `max_requests_per_connection` is off too: it ends a + // keep-alive connection after about 1,000 requests so that a balancer can + // move a busy client (ADR 275), and here there is one client and no + // balancer, so all it would do is drop the requests a pipelined client + // already sent behind the last one. try app.listen(.{ .address = "0.0.0.0", .port = 8080, .max_connections = 65_536, + .max_requests_per_connection = 0, .also = also[0..n_also], }); } From 2d4b3ff2586813ff3b5f05414959cc5b4faa82ef Mon Sep 17 00:00:00 2001 From: Nevindra Date: Sat, 10 Oct 2026 08:48:37 +0700 Subject: [PATCH 3/5] nilo: re-pin to 778a602, which sends a burst of HTTP/2 answers in writes of 32 KiB --- frameworks/nilo/build.zig.zon | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/frameworks/nilo/build.zig.zon b/frameworks/nilo/build.zig.zon index 70c2ebf84..6c95ffe17 100644 --- a/frameworks/nilo/build.zig.zon +++ b/frameworks/nilo/build.zig.zon @@ -8,8 +8,8 @@ // the build the row describes. Move both lines together: // zig fetch --save=nilo git+https://github.com/nevindra/nilo# .nilo = .{ - .url = "git+https://github.com/nevindra/nilo#077b4a81cd4c146664b1b4cbdae4631420759e3f", - .hash = "nilo-0.7.0-5HEqwrJznAD77mTEmYOkNsg1eugyIHlp0NF_wyAb67ur", + .url = "git+https://github.com/nevindra/nilo#778a6020cf80d0e56632369f35195efe2534ec40", + .hash = "nilo-0.7.0-5HEqwq58ogB5SsehVQL5H_-zGUVG0alMV3V1Ki5I2T0a", }, }, .paths = .{ "build.zig", "build.zig.zon", "src" }, From 7b2c9e68596ae168f500cb6381cffa4f1e31ba40 Mon Sep 17 00:00:00 2001 From: Nevindra Date: Sat, 10 Oct 2026 09:57:46 +0700 Subject: [PATCH 4/5] nilo: re-pin to v0.8.0 --- frameworks/nilo/build.zig.zon | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/frameworks/nilo/build.zig.zon b/frameworks/nilo/build.zig.zon index 6c95ffe17..5de2efa17 100644 --- a/frameworks/nilo/build.zig.zon +++ b/frameworks/nilo/build.zig.zon @@ -8,8 +8,8 @@ // the build the row describes. Move both lines together: // zig fetch --save=nilo git+https://github.com/nevindra/nilo# .nilo = .{ - .url = "git+https://github.com/nevindra/nilo#778a6020cf80d0e56632369f35195efe2534ec40", - .hash = "nilo-0.7.0-5HEqwq58ogB5SsehVQL5H_-zGUVG0alMV3V1Ki5I2T0a", + .url = "git+https://github.com/nevindra/nilo?ref=v0.8.0#d3ab2f33bbb8fc2281605c33a12fe3619c63f42d", + .hash = "nilo-0.8.0-5HEqwq58ogBz1MCJR4WuM7uGdb0PznnQgoANOdGFRbPx", }, }, .paths = .{ "build.zig", "build.zig.zon", "src" }, From 832e74dd5e7c5b9436c2b0652e38e6593001dbc8 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Sun, 11 Oct 2026 14:32:44 +0000 Subject: [PATCH 5/5] Benchmark results: nilo [skip ci] --- site/data/frameworks.json | 2 +- site/data/results/nilo.json | 577 +++++++++++++----- site/static/logs/8gbit/512/nilo.log | 7 +- site/static/logs/async-db/1024/nilo.log | 82 ++- site/static/logs/async/32000/nilo.log | 7 +- site/static/logs/baseline-h2/1024/nilo.log | 5 + site/static/logs/baseline-h2/256/nilo.log | 5 + site/static/logs/baseline-h2c/1024/nilo.log | 5 + site/static/logs/baseline-h2c/256/nilo.log | 5 + site/static/logs/baseline-h2c/4096/nilo.log | 5 + site/static/logs/baseline/4096/nilo.log | 7 +- .../static/logs/echo-ws-limited/4096/nilo.log | 7 +- site/static/logs/echo-ws-limited/512/nilo.log | 7 +- .../logs/echo-ws-pipeline/16384/nilo.log | 7 +- .../logs/echo-ws-pipeline/4096/nilo.log | 7 +- .../static/logs/echo-ws-pipeline/512/nilo.log | 7 +- site/static/logs/echo-ws/16384/nilo.log | 7 +- site/static/logs/echo-ws/4096/nilo.log | 7 +- site/static/logs/echo-ws/512/nilo.log | 7 +- site/static/logs/json-comp/16384/nilo.log | 318 +--------- site/static/logs/json-comp/4096/nilo.log | 7 +- site/static/logs/json-h2c/1024/nilo.log | 5 + site/static/logs/json-h2c/4096/nilo.log | 5 + site/static/logs/json-tls/4096/nilo.log | 7 +- site/static/logs/latency-10k/1024/nilo.log | 7 +- site/static/logs/latency-1m/1024/nilo.log | 7 +- .../logs/latency-500k-8cpu/1024/nilo.log | 7 +- site/static/logs/limited-conn/4096/nilo.log | 7 +- site/static/logs/pipelined/4096/nilo.log | 7 +- site/static/logs/static-h2/1024/nilo.log | 5 + site/static/logs/static-h2/256/nilo.log | 5 + site/static/logs/unary-grpc-tls/1024/nilo.log | 5 + site/static/logs/unary-grpc-tls/256/nilo.log | 5 + site/static/logs/unary-grpc/1024/nilo.log | 5 + site/static/logs/unary-grpc/256/nilo.log | 5 + 35 files changed, 654 insertions(+), 516 deletions(-) create mode 100644 site/static/logs/baseline-h2/1024/nilo.log create mode 100644 site/static/logs/baseline-h2/256/nilo.log create mode 100644 site/static/logs/baseline-h2c/1024/nilo.log create mode 100644 site/static/logs/baseline-h2c/256/nilo.log create mode 100644 site/static/logs/baseline-h2c/4096/nilo.log create mode 100644 site/static/logs/json-h2c/1024/nilo.log create mode 100644 site/static/logs/json-h2c/4096/nilo.log create mode 100644 site/static/logs/static-h2/1024/nilo.log create mode 100644 site/static/logs/static-h2/256/nilo.log create mode 100644 site/static/logs/unary-grpc-tls/1024/nilo.log create mode 100644 site/static/logs/unary-grpc-tls/256/nilo.log create mode 100644 site/static/logs/unary-grpc/1024/nilo.log create mode 100644 site/static/logs/unary-grpc/256/nilo.log diff --git a/site/data/frameworks.json b/site/data/frameworks.json index 1661cf36c..3dbe3d042 100644 --- a/site/data/frameworks.json +++ b/site/data/frameworks.json @@ -1358,7 +1358,7 @@ }, "nilo": { "dir": "nilo", - "description": "A toolkit for Zig 0.16 whose largest module is an HTTP/1.1 server on zio fibers (io_uring, epoll, kqueue). A plain function is a route: its argument list is the routing, the typed input, the 400 for anything that does not fit, and the OpenAPI document. One allocation per request, 4,669 bytes per idle connection, and a wait parks the fiber rather than the thread. Serves cleartext on 8080 and TLS 1.3 on 8081 from one process. Refuses HTTP/2, HTTP/3, gRPC and templates on the record, which is why it sits out those profiles.", + "description": "A toolkit for Zig 0.17 whose largest module is an HTTP server on zio fibers (io_uring, epoll, kqueue). A plain function is a route: its argument list is the routing, the typed input, the 400 for anything that does not fit, and the OpenAPI document. One allocation per request, 4,669 bytes per idle connection, and a wait parks the fiber rather than the thread. Serves HTTP/1.1 and h2c on 8080, TLS 1.3 on 8081, h2c on 8082 and HTTP/2 over TLS with ALPN on 8443 from one process. HTTP/2 and unary gRPC are behind the -Dhttp2 build flag, which this entry builds with; gRPC is unary only, so the streaming profiles are not subscribed. Refuses HTTP/3 and templates on the record, which is why it sits out those profiles.", "repo": "https://github.com/nevindra/nilo", "type": "experimental", "engine": "nilo_http on zio", diff --git a/site/data/results/nilo.json b/site/data/results/nilo.json index 4f09a2f90..65119476b 100644 --- a/site/data/results/nilo.json +++ b/site/data/results/nilo.json @@ -4,44 +4,44 @@ "8gbit-512": { "framework": "nilo", "language": "Zig", - "rps": 49160, - "avg_latency": "108.7us", - "p99_latency": "150.0us", - "cpu": "443.7%", - "memory": "128MiB", + "rps": 49266, + "avg_latency": "102.7us", + "p99_latency": "144.0us", + "cpu": "272.5%", + "memory": "120MiB", "connections": 512, "threads": 64, "duration": "5s", "pipeline": 1, - "bandwidth": "509.25MB/s", - "input_bw": "480.08MB/s", + "bandwidth": "510.35MB/s", + "input_bw": "481.11MB/s", "reconnects": 0, - "status_2xx": 245864, + "status_2xx": 246403, "status_3xx": 0, "status_4xx": 0, "status_5xx": 0, - "cpu_usec": 19178547, - "cpu_per_req_us": 78.0047, + "cpu_usec": 16063303, + "cpu_per_req_us": 65.1912, "target_rate": 50000, - "rate_ratio": 0.9832, - "p99_9_latency": "1301.0us" + "rate_ratio": 0.9853, + "p99_9_latency": "6294.0us" }, "async-32000": { "framework": "nilo", "language": "Zig", - "rps": 1956056, - "avg_latency": "15.17ms", - "p99_latency": "29.10ms", - "cpu": "5306.0%", - "memory": "927MiB", + "rps": 1973470, + "avg_latency": "15.13ms", + "p99_latency": "28.00ms", + "cpu": "4898.7%", + "memory": "1002MiB", "connections": 32000, "threads": 64, "duration": "5s", "pipeline": 1, - "bandwidth": "192.11MB/s", - "input_bw": "89.54MB/s", + "bandwidth": "193.82MB/s", + "input_bw": "90.34MB/s", "reconnects": 0, - "status_2xx": 19560563, + "status_2xx": 19734706, "status_3xx": 0, "status_4xx": 0, "status_5xx": 0 @@ -49,19 +49,19 @@ "async-db-1024": { "framework": "nilo", "language": "Zig", - "rps": 57285, - "avg_latency": "17.65ms", - "p99_latency": "77.60ms", - "cpu": "829.5%", - "memory": "134MiB", + "rps": 68515, + "avg_latency": "14.47ms", + "p99_latency": "59.80ms", + "cpu": "769.1%", + "memory": "150MiB", "connections": 1024, "threads": 64, "duration": "5s", "pipeline": 1, - "bandwidth": "219.84MB/s", - "input_bw": "3.82MB/s", - "reconnects": 22509, - "status_2xx": 572855, + "bandwidth": "262.88MB/s", + "input_bw": "4.57MB/s", + "reconnects": 27129, + "status_2xx": 685157, "status_3xx": 0, "status_4xx": 0, "status_5xx": 0 @@ -69,19 +69,114 @@ "baseline-4096": { "framework": "nilo", "language": "Zig", - "rps": 2957435, - "avg_latency": "1.38ms", - "p99_latency": "1.58ms", - "cpu": "6635.6%", - "memory": "179MiB", + "rps": 3076550, + "avg_latency": "1.33ms", + "p99_latency": "1.52ms", + "cpu": "6693.6%", + "memory": "171MiB", "connections": 4096, "threads": 64, "duration": "5s", "pipeline": 1, - "bandwidth": "290.43MB/s", - "input_bw": "228.45MB/s", + "bandwidth": "302.13MB/s", + "input_bw": "237.66MB/s", "reconnects": 0, - "status_2xx": 14787178, + "status_2xx": 15382753, + "status_3xx": 0, + "status_4xx": 0, + "status_5xx": 0 + }, + "baseline-h2-1024": { + "framework": "nilo", + "language": "Zig", + "rps": 8912070, + "avg_latency": "14.40ms", + "p99_latency": "120.50ms", + "cpu": "6164.7%", + "memory": "227MiB", + "connections": 1024, + "threads": 64, + "duration": "5s", + "pipeline": 1, + "bandwidth": "593.49MB/s", + "reconnects": 0, + "status_2xx": 45095078, + "status_3xx": 0, + "status_4xx": 0, + "status_5xx": 0 + }, + "baseline-h2-256": { + "framework": "nilo", + "language": "Zig", + "rps": 7267874, + "avg_latency": "4.06ms", + "p99_latency": "24.26ms", + "cpu": "6442.7%", + "memory": "111MiB", + "connections": 256, + "threads": 64, + "duration": "5s", + "pipeline": 1, + "bandwidth": "481.12MB/s", + "reconnects": 0, + "status_2xx": 36557407, + "status_3xx": 0, + "status_4xx": 0, + "status_5xx": 0 + }, + "baseline-h2c-1024": { + "framework": "nilo", + "language": "Zig", + "rps": 7234451, + "avg_latency": "13.47ms", + "p99_latency": "46.11ms", + "cpu": "6369.0%", + "memory": "142MiB", + "connections": 1024, + "threads": 64, + "duration": "5s", + "pipeline": 1, + "bandwidth": "481.77MB/s", + "reconnects": 0, + "status_2xx": 36606326, + "status_3xx": 0, + "status_4xx": 0, + "status_5xx": 0 + }, + "baseline-h2c-256": { + "framework": "nilo", + "language": "Zig", + "rps": 9010310, + "avg_latency": "2.67ms", + "p99_latency": "11.03ms", + "cpu": "6446.2%", + "memory": "57MiB", + "connections": 256, + "threads": 64, + "duration": "5s", + "pipeline": 1, + "bandwidth": "596.47MB/s", + "reconnects": 0, + "status_2xx": 45321864, + "status_3xx": 0, + "status_4xx": 0, + "status_5xx": 0 + }, + "baseline-h2c-4096": { + "framework": "nilo", + "language": "Zig", + "rps": 6873413, + "avg_latency": "56.66ms", + "p99_latency": "146.15ms", + "cpu": "6440.6%", + "memory": "253MiB", + "connections": 4096, + "threads": 64, + "duration": "5s", + "pipeline": 1, + "bandwidth": "459.56MB/s", + "reconnects": 0, + "status_2xx": 34916940, "status_3xx": 0, "status_4xx": 0, "status_5xx": 0 @@ -89,18 +184,18 @@ "echo-ws-16384": { "framework": "nilo", "language": "Zig", - "rps": 3122294, - "avg_latency": "4.48ms", - "p99_latency": "5.92ms", - "cpu": "6553.8%", - "memory": "504MiB", + "rps": 3466526, + "avg_latency": "3.98ms", + "p99_latency": "5.84ms", + "cpu": "6480.0%", + "memory": "478MiB", "connections": 16384, "threads": 64, "duration": "5s", "pipeline": 1, - "bandwidth": "21.24MB/s", + "bandwidth": "23.54MB/s", "reconnects": 0, - "status_2xx": 15611471, + "status_2xx": 17332632, "status_3xx": 0, "status_4xx": 0, "status_5xx": 0 @@ -108,18 +203,18 @@ "echo-ws-4096": { "framework": "nilo", "language": "Zig", - "rps": 3694061, - "avg_latency": "1.11ms", - "p99_latency": "1.68ms", - "cpu": "6350.2%", - "memory": "156MiB", + "rps": 3995815, + "avg_latency": "1.02ms", + "p99_latency": "1.78ms", + "cpu": "6515.9%", + "memory": "145MiB", "connections": 4096, "threads": 64, "duration": "5s", "pipeline": 1, - "bandwidth": "24.66MB/s", + "bandwidth": "26.68MB/s", "reconnects": 0, - "status_2xx": 18470308, + "status_2xx": 19979079, "status_3xx": 0, "status_4xx": 0, "status_5xx": 0 @@ -127,18 +222,18 @@ "echo-ws-512": { "framework": "nilo", "language": "Zig", - "rps": 3563707, - "avg_latency": "143us", - "p99_latency": "279us", - "cpu": "6654.5%", - "memory": "55MiB", + "rps": 4111406, + "avg_latency": "123us", + "p99_latency": "161us", + "cpu": "6575.9%", + "memory": "47MiB", "connections": 512, "threads": 64, "duration": "5s", "pipeline": 1, - "bandwidth": "23.78MB/s", + "bandwidth": "27.44MB/s", "reconnects": 0, - "status_2xx": 17818535, + "status_2xx": 20557033, "status_3xx": 0, "status_4xx": 0, "status_5xx": 0 @@ -146,18 +241,18 @@ "echo-ws-limited-4096": { "framework": "nilo", "language": "Zig", - "rps": 2139364, - "avg_latency": "954us", - "p99_latency": "3.65ms", - "cpu": "5974.6%", - "memory": "248MiB", + "rps": 2139768, + "avg_latency": "637us", + "p99_latency": "2.15ms", + "cpu": "5619.1%", + "memory": "220MiB", "connections": 4096, "threads": 64, "duration": "5s", "pipeline": 1, - "bandwidth": "40.60MB/s", - "reconnects": 1069550, - "status_2xx": 10696824, + "bandwidth": "40.61MB/s", + "reconnects": 1069773, + "status_2xx": 10698841, "status_3xx": 0, "status_4xx": 0, "status_5xx": 0 @@ -165,18 +260,18 @@ "echo-ws-limited-512": { "framework": "nilo", "language": "Zig", - "rps": 1173069, - "avg_latency": "369us", - "p99_latency": "1.35ms", - "cpu": "3803.1%", - "memory": "84MiB", + "rps": 1192006, + "avg_latency": "351us", + "p99_latency": "1.29ms", + "cpu": "3619.4%", + "memory": "96MiB", "connections": 512, "threads": 64, "duration": "5s", "pipeline": 1, - "bandwidth": "22.26MB/s", - "reconnects": 586540, - "status_2xx": 5865348, + "bandwidth": "22.62MB/s", + "reconnects": 596022, + "status_2xx": 5960030, "status_3xx": 0, "status_4xx": 0, "status_5xx": 0 @@ -184,18 +279,18 @@ "echo-ws-pipeline-16384": { "framework": "nilo", "language": "Zig", - "rps": 45825642, - "avg_latency": "4.91ms", - "p99_latency": "6.31ms", - "cpu": "6277.2%", - "memory": "510MiB", + "rps": 50919069, + "avg_latency": "4.37ms", + "p99_latency": "6.12ms", + "cpu": "6211.1%", + "memory": "503MiB", "connections": 16384, "threads": 64, "duration": "5s", "pipeline": 16, - "bandwidth": "306.23MB/s", + "bandwidth": "340.21MB/s", "reconnects": 0, - "status_2xx": 229128212, + "status_2xx": 254595345, "status_3xx": 0, "status_4xx": 0, "status_5xx": 0 @@ -203,18 +298,18 @@ "echo-ws-pipeline-4096": { "framework": "nilo", "language": "Zig", - "rps": 53370713, - "avg_latency": "1.23ms", - "p99_latency": "1.60ms", - "cpu": "6618.0%", - "memory": "154MiB", + "rps": 58610864, + "avg_latency": "1.12ms", + "p99_latency": "1.73ms", + "cpu": "6284.8%", + "memory": "151MiB", "connections": 4096, "threads": 64, "duration": "5s", "pipeline": 16, - "bandwidth": "356.22MB/s", + "bandwidth": "391.15MB/s", "reconnects": 0, - "status_2xx": 266853567, + "status_2xx": 293054320, "status_3xx": 0, "status_4xx": 0, "status_5xx": 0 @@ -222,18 +317,18 @@ "echo-ws-pipeline-512": { "framework": "nilo", "language": "Zig", - "rps": 53031382, - "avg_latency": "153us", - "p99_latency": "253us", - "cpu": "6697.7%", - "memory": "55MiB", + "rps": 61071888, + "avg_latency": "133us", + "p99_latency": "190us", + "cpu": "6309.6%", + "memory": "47MiB", "connections": 512, "threads": 64, "duration": "5s", "pipeline": 16, - "bandwidth": "353.93MB/s", + "bandwidth": "407.59MB/s", "reconnects": 0, - "status_2xx": 265156912, + "status_2xx": 305359440, "status_3xx": 0, "status_4xx": 0, "status_5xx": 0 @@ -241,19 +336,19 @@ "json-comp-16384": { "framework": "nilo", "language": "Zig", - "rps": 268625, - "avg_latency": "27.65ms", - "p99_latency": "397.90ms", - "cpu": "6016.0%", - "memory": "437MiB", + "rps": 594331, + "avg_latency": "19.67ms", + "p99_latency": "179.00ms", + "cpu": "6547.5%", + "memory": "496MiB", "connections": 16384, "threads": 64, "duration": "5s", "pipeline": 1, - "bandwidth": "361.62MB/s", - "input_bw": "19.98MB/s", - "reconnects": 51885, - "status_2xx": 1343125, + "bandwidth": "784.83MB/s", + "input_bw": "44.21MB/s", + "reconnects": 114115, + "status_2xx": 2971655, "status_3xx": 0, "status_4xx": 0, "status_5xx": 0 @@ -261,19 +356,57 @@ "json-comp-4096": { "framework": "nilo", "language": "Zig", - "rps": 270152, - "avg_latency": "15.21ms", - "p99_latency": "148.60ms", - "cpu": "5949.5%", - "memory": "250MiB", + "rps": 611376, + "avg_latency": "6.69ms", + "p99_latency": "31.20ms", + "cpu": "6598.4%", + "memory": "321MiB", + "connections": 4096, + "threads": 64, + "duration": "5s", + "pipeline": 1, + "bandwidth": "807.37MB/s", + "input_bw": "45.48MB/s", + "reconnects": 121072, + "status_2xx": 3056882, + "status_3xx": 0, + "status_4xx": 0, + "status_5xx": 0 + }, + "json-h2c-1024": { + "framework": "nilo", + "language": "Zig", + "rps": 1409454, + "avg_latency": "22.23ms", + "p99_latency": "94.60ms", + "cpu": "1507.4%", + "memory": "359MiB", + "connections": 1024, + "threads": 64, + "duration": "5s", + "pipeline": 1, + "bandwidth": "4.79GB/s", + "reconnects": 0, + "status_2xx": 7131839, + "status_3xx": 0, + "status_4xx": 0, + "status_5xx": 0 + }, + "json-h2c-4096": { + "framework": "nilo", + "language": "Zig", + "rps": 1387433, + "avg_latency": "87.83ms", + "p99_latency": "327.18ms", + "cpu": "1787.2%", + "memory": "894MiB", "connections": 4096, "threads": 64, "duration": "5s", "pipeline": 1, - "bandwidth": "363.67MB/s", - "input_bw": "20.10MB/s", - "reconnects": 52596, - "status_2xx": 1350761, + "bandwidth": "4.74GB/s", + "reconnects": 0, + "status_2xx": 7062034, "status_3xx": 0, "status_4xx": 0, "status_5xx": 0 @@ -281,18 +414,18 @@ "json-tls-4096": { "framework": "nilo", "language": "Zig", - "rps": 1333036, - "avg_latency": "2.99ms", - "p99_latency": "65.00ms", - "cpu": "6458.8%", - "memory": "706MiB", + "rps": 1561927, + "avg_latency": "3.09ms", + "p99_latency": "309.41ms", + "cpu": "6303.1%", + "memory": "653MiB", "connections": 4096, "threads": 64, "duration": "5s", "pipeline": 1, - "bandwidth": "4.53GB", + "bandwidth": "5.30GB", "reconnects": 0, - "status_2xx": 6798783, + "status_2xx": 7969220, "status_3xx": 0, "status_4xx": 0, "status_5xx": 0 @@ -301,90 +434,90 @@ "framework": "nilo", "language": "Zig", "rps": 9983, - "avg_latency": "75.0us", - "p99_latency": "106.0us", - "cpu": "32.3%", - "memory": "68MiB", + "avg_latency": "72.6us", + "p99_latency": "103.0us", + "cpu": "24.9%", + "memory": "66MiB", "connections": 1024, "threads": 64, "duration": "20s", "pipeline": 1, "bandwidth": "1.02MB/s", "reconnects": 0, - "status_2xx": 199685, + "status_2xx": 199677, "status_3xx": 0, "status_4xx": 0, "status_5xx": 0, - "cpu_usec": 6731862, - "cpu_per_req_us": 33.7124, + "cpu_usec": 5223387, + "cpu_per_req_us": 26.1592, "target_rate": 10000, "rate_ratio": 0.9983, - "p99_9_latency": "141.0us" + "p99_9_latency": "3951.0us" }, "latency-1m-1024": { "framework": "nilo", "language": "Zig", - "rps": 997873, - "avg_latency": "120.8us", - "p99_latency": "201.0us", - "cpu": "3572.9%", - "memory": "70MiB", + "rps": 997605, + "avg_latency": "103.9us", + "p99_latency": "180.0us", + "cpu": "2745.5%", + "memory": "68MiB", "connections": 1024, "threads": 64, "duration": "20s", "pipeline": 1, - "bandwidth": "101.78MB/s", + "bandwidth": "101.76MB/s", "reconnects": 0, - "status_2xx": 19960822, + "status_2xx": 19955520, "status_3xx": 0, "status_4xx": 0, "status_5xx": 0, - "cpu_usec": 622556514, - "cpu_per_req_us": 31.1889, + "cpu_usec": 501047034, + "cpu_per_req_us": 25.1082, "target_rate": 1000000, - "rate_ratio": 0.9979, - "p99_9_latency": "3835.0us" + "rate_ratio": 0.9976, + "p99_9_latency": "3027.0us" }, "latency-500k-8cpu-1024": { "framework": "nilo", "language": "Zig", - "rps": 444866, - "avg_latency": "1079887.7us", - "p99_latency": "2192384.0us", - "cpu": "796.9%", - "memory": "46MiB", + "rps": 440897, + "avg_latency": "1158568.3us", + "p99_latency": "2309120.0us", + "cpu": "793.1%", + "memory": "49MiB", "connections": 1024, "threads": 64, "duration": "20s", "pipeline": 1, - "bandwidth": "45.38MB/s", + "bandwidth": "44.97MB/s", "reconnects": 0, - "status_2xx": 8900151, + "status_2xx": 8820872, "status_3xx": 0, "status_4xx": 0, "status_5xx": 0, - "cpu_usec": 159583326, - "cpu_per_req_us": 17.9304, + "cpu_usec": 159555389, + "cpu_per_req_us": 18.0884, "target_rate": 500000, - "rate_ratio": 0.8897, - "p99_9_latency": "2276352.0us" + "rate_ratio": 0.8818, + "p99_9_latency": "2388992.0us" }, "limited-conn-4096": { "framework": "nilo", "language": "Zig", - "rps": 2303617, + "rps": 2301647, "avg_latency": "1.76ms", - "p99_latency": "10.40ms", - "cpu": "6280.3%", - "memory": "233MiB", + "p99_latency": "10.60ms", + "cpu": "5868.5%", + "memory": "261MiB", "connections": 4096, "threads": 64, "duration": "5s", "pipeline": 1, - "bandwidth": "226.22MB/s", - "input_bw": "177.95MB/s", - "reconnects": 1150971, - "status_2xx": 11518086, + "bandwidth": "226.02MB/s", + "input_bw": "177.80MB/s", + "reconnects": 1150252, + "status_2xx": 11508237, "status_3xx": 0, "status_4xx": 0, "status_5xx": 0 @@ -392,18 +525,132 @@ "pipelined-4096": { "framework": "nilo", "language": "Zig", - "rps": 8103580, - "avg_latency": "8.09ms", - "p99_latency": "8.35ms", - "cpu": "6213.8%", - "memory": "149MiB", + "rps": 12006230, + "avg_latency": "5.47ms", + "p99_latency": "11.00ms", + "cpu": "6548.0%", + "memory": "140MiB", "connections": 4096, "threads": 64, "duration": "5s", "pipeline": 16, - "bandwidth": "795.79MB/s", + "bandwidth": "1.15GB/s", + "reconnects": 0, + "status_2xx": 60031152, + "status_3xx": 0, + "status_4xx": 0, + "status_5xx": 0 + }, + "static-h2-1024": { + "framework": "nilo", + "language": "Zig", + "rps": 201561, + "avg_latency": "155.29ms", + "p99_latency": "253.54ms", + "cpu": "6225.3%", + "memory": "686MiB", + "connections": 1024, + "threads": 64, + "duration": "5s", + "pipeline": 1, + "bandwidth": "3.13GB/s", + "reconnects": 0, + "status_2xx": 1021917, + "status_3xx": 0, + "status_4xx": 0, + "status_5xx": 0 + }, + "static-h2-256": { + "framework": "nilo", + "language": "Zig", + "rps": 862191, + "avg_latency": "9.29ms", + "p99_latency": "25.11ms", + "cpu": "6541.1%", + "memory": "1.4GiB", + "connections": 256, + "threads": 64, + "duration": "5s", + "pipeline": 1, + "bandwidth": "13.27GB/s", + "reconnects": 0, + "status_2xx": 4336824, + "status_3xx": 0, + "status_4xx": 0, + "status_5xx": 0 + }, + "unary-grpc-1024": { + "framework": "nilo", + "language": "Zig", + "rps": 6706912, + "avg_latency": "10.99ms", + "p99_latency": "197.47ms", + "cpu": "6382.7%", + "memory": "1006MiB", + "connections": 1024, + "threads": 64, + "duration": "5s", + "pipeline": 1, + "bandwidth": "446.66MB/s", + "reconnects": 0, + "status_2xx": 33936978, + "status_3xx": 0, + "status_4xx": 0, + "status_5xx": 0 + }, + "unary-grpc-256": { + "framework": "nilo", + "language": "Zig", + "rps": 6357462, + "avg_latency": "3.65ms", + "p99_latency": "9.96ms", + "cpu": "6459.6%", + "memory": "423MiB", + "connections": 256, + "threads": 64, + "duration": "5s", + "pipeline": 1, + "bandwidth": "421.71MB/s", + "reconnects": 0, + "status_2xx": 32041611, + "status_3xx": 0, + "status_4xx": 0, + "status_5xx": 0 + }, + "unary-grpc-tls-1024": { + "framework": "nilo", + "language": "Zig", + "rps": 3391337, + "avg_latency": "45.16ms", + "p99_latency": "561.80ms", + "cpu": "6238.6%", + "memory": "2.1GiB", + "connections": 1024, + "threads": 64, + "duration": "5s", + "pipeline": 1, + "bandwidth": "225.86MB/s", + "reconnects": 0, + "status_2xx": 17160166, + "status_3xx": 0, + "status_4xx": 0, + "status_5xx": 0 + }, + "unary-grpc-tls-256": { + "framework": "nilo", + "language": "Zig", + "rps": 2126794, + "avg_latency": "12.95ms", + "p99_latency": "113.54ms", + "cpu": "6405.4%", + "memory": "626MiB", + "connections": 256, + "threads": 64, + "duration": "5s", + "pipeline": 1, + "bandwidth": "140.52MB/s", "reconnects": 0, - "status_2xx": 40517904, + "status_2xx": 10676507, "status_3xx": 0, "status_4xx": 0, "status_5xx": 0 diff --git a/site/static/logs/8gbit/512/nilo.log b/site/static/logs/8gbit/512/nilo.log index 2ca69ee8c..d563971f8 100644 --- a/site/static/logs/8gbit/512/nilo.log +++ b/site/static/logs/8gbit/512/nilo.log @@ -1,2 +1,5 @@ -info: nilo listening on 0.0.0.0:8080 across 64 thread(s) -info: nilo also listening on https://0.0.0.0:8081 +2026-10-11T14:19:15.455Z info nilo: loaded 20 static file(s) (1758039 bytes held, 486436 of them precompressed files) from "/data/static" onto "/static" +2026-10-11T14:19:15.510Z info nilo listening on 0.0.0.0:8080 across 64 thread(s) +2026-10-11T14:19:15.510Z info nilo also listening on 0.0.0.0:8082 +2026-10-11T14:19:15.510Z info nilo also listening on https://0.0.0.0:8081 +2026-10-11T14:19:15.510Z info nilo also listening on https://0.0.0.0:8443 diff --git a/site/static/logs/async-db/1024/nilo.log b/site/static/logs/async-db/1024/nilo.log index 2ca69ee8c..963564885 100644 --- a/site/static/logs/async-db/1024/nilo.log +++ b/site/static/logs/async-db/1024/nilo.log @@ -1,2 +1,80 @@ -info: nilo listening on 0.0.0.0:8080 across 64 thread(s) -info: nilo also listening on https://0.0.0.0:8081 +2026-10-11T14:19:41.002Z info nilo: loaded 20 static file(s) (1758039 bytes held, 486436 of them precompressed files) from "/data/static" onto "/static" +2026-10-11T14:19:41.002Z info asyncdb: kernel.io_uring_disabled=0 (0 means the ring backend can be used; 1 or 2 means zio falls back to epoll) +2026-10-11T14:19:41.056Z info nilo listening on 0.0.0.0:8080 across 64 thread(s) +2026-10-11T14:19:41.056Z info nilo also listening on 0.0.0.0:8082 +2026-10-11T14:19:41.056Z info nilo also listening on https://0.0.0.0:8081 +2026-10-11T14:19:41.056Z info nilo also listening on https://0.0.0.0:8443 +2026-10-11T14:19:42.006Z info asyncdb: answered=0/s inflight=0 (max 0) pool size=256 open=256 in_use=0.0 idle=165.6 missing=0 waited=0 dropped=0 | statement mean=0us p99=0us | request mean=0us p99=0us | hold~0us +2026-10-11T14:19:42.006Z info asyncdb: threads=68 cpu=0% hot(>=50%)=0 warm(>=10%)=0 top=[0,0,0,0,0,0]% sleeps=2609/s preempted=3/s faults=2796/s io_uring_workers=2 +2026-10-11T14:19:43.009Z info asyncdb: answered=51975/s inflight=713 (max 770) pool size=256 open=256 in_use=232.2 idle=23.8 missing=0 waited=50396 dropped=0 | statement mean=11131us p99=61440us | request mean=11133us p99=61440us | hold~4480us +2026-10-11T14:19:43.009Z info asyncdb: threads=68 cpu=540% hot(>=50%)=0 warm(>=10%)=1 top=[10,9,9,9,9,9]% sleeps=50898/s preempted=10715/s faults=81035/s io_uring_workers=2 +2026-10-11T14:19:44.013Z info asyncdb: answered=67871/s inflight=717 (max 772) pool size=256 open=256 in_use=254.8 idle=1.2 missing=0 waited=67845 dropped=0 | statement mean=10626us p99=57344us | request mean=10627us p99=57344us | hold~3756us +2026-10-11T14:19:44.013Z info asyncdb: threads=68 cpu=766% hot(>=50%)=0 warm(>=10%)=64 top=[14,14,14,13,13,13]% sleeps=71483/s preempted=9593/s faults=95446/s io_uring_workers=2 +2026-10-11T14:19:45.017Z info asyncdb: answered=68634/s inflight=686 (max 771) pool size=256 open=256 in_use=254.7 idle=1.3 missing=0 waited=68590 dropped=0 | statement mean=10374us p99=57344us | request mean=10375us p99=57344us | hold~3711us +2026-10-11T14:19:45.017Z info asyncdb: threads=68 cpu=758% hot(>=50%)=0 warm(>=10%)=64 top=[15,14,13,13,13,13]% sleeps=70369/s preempted=9933/s faults=93450/s io_uring_workers=2 +2026-10-11T14:19:46.020Z info asyncdb: answered=69160/s inflight=693 (max 777) pool size=256 open=256 in_use=255.3 idle=0.7 missing=0 waited=69240 dropped=0 | statement mean=10245us p99=57344us | request mean=10246us p99=57344us | hold~3690us +2026-10-11T14:19:46.020Z info asyncdb: threads=68 cpu=758% hot(>=50%)=0 warm(>=10%)=64 top=[13,13,13,13,13,13]% sleeps=69926/s preempted=10165/s faults=94254/s io_uring_workers=2 +2026-10-11T14:19:47.024Z info asyncdb: answered=70668/s inflight=694 (max 766) pool size=256 open=256 in_use=254.8 idle=1.2 missing=0 waited=70653 dropped=0 | statement mean=9889us p99=53248us | request mean=9890us p99=53248us | hold~3603us +2026-10-11T14:19:47.024Z info asyncdb: threads=68 cpu=791% hot(>=50%)=0 warm(>=10%)=64 top=[14,14,14,14,14,13]% sleeps=73248/s preempted=9404/s faults=95358/s io_uring_workers=2 +2026-10-11T14:19:48.028Z info asyncdb: answered=67873/s inflight=703 (max 751) pool size=256 open=256 in_use=255.2 idle=0.8 missing=0 waited=67931 dropped=0 | statement mean=10190us p99=57344us | request mean=10190us p99=57344us | hold~3760us +2026-10-11T14:19:48.028Z info asyncdb: threads=68 cpu=755% hot(>=50%)=0 warm(>=10%)=63 top=[14,13,13,13,13,13]% sleeps=72862/s preempted=10184/s faults=91789/s io_uring_workers=2 +2026-10-11T14:19:49.031Z info asyncdb: answered=67907/s inflight=659 (max 743) pool size=256 open=256 in_use=255.0 idle=1.0 missing=0 waited=67710 dropped=0 | statement mean=10056us p99=57344us | request mean=10057us p99=57344us | hold~3756us +2026-10-11T14:19:49.031Z info asyncdb: threads=68 cpu=748% hot(>=50%)=0 warm(>=10%)=64 top=[14,13,13,13,13,13]% sleeps=72845/s preempted=10815/s faults=90621/s io_uring_workers=2 +2026-10-11T14:19:50.035Z info asyncdb: answered=69187/s inflight=591 (max 735) pool size=256 open=256 in_use=254.2 idle=1.8 missing=0 waited=69224 dropped=0 | statement mean=9718us p99=57344us | request mean=9719us p99=57344us | hold~3674us +2026-10-11T14:19:50.035Z info asyncdb: threads=68 cpu=764% hot(>=50%)=0 warm(>=10%)=64 top=[14,14,14,13,13,13]% sleeps=74699/s preempted=10162/s faults=92944/s io_uring_workers=2 +2026-10-11T14:19:51.039Z info asyncdb: answered=66057/s inflight=634 (max 716) pool size=256 open=256 in_use=254.3 idle=1.7 missing=0 waited=66059 dropped=0 | statement mean=9939us p99=61440us | request mean=9940us p99=61440us | hold~3847us +2026-10-11T14:19:51.039Z info asyncdb: threads=68 cpu=758% hot(>=50%)=0 warm(>=10%)=64 top=[15,14,13,13,13,13]% sleeps=76824/s preempted=10115/s faults=92524/s io_uring_workers=2 +2026-10-11T14:19:52.042Z info asyncdb: answered=70162/s inflight=661 (max 708) pool size=256 open=256 in_use=253.7 idle=2.3 missing=0 waited=70154 dropped=0 | statement mean=9280us p99=57344us | request mean=9281us p99=57344us | hold~3617us +2026-10-11T14:19:52.042Z info asyncdb: threads=68 cpu=773% hot(>=50%)=0 warm(>=10%)=64 top=[15,14,14,14,13,13]% sleeps=75925/s preempted=11570/s faults=91106/s io_uring_workers=2 +2026-10-11T14:19:53.046Z info asyncdb: answered=10759/s inflight=0 (max 695) pool size=256 open=256 in_use=25.3 idle=230.7 missing=0 waited=10350 dropped=0 | statement mean=10125us p99=57344us | request mean=10126us p99=57344us | hold~2318us +2026-10-11T14:19:53.046Z info asyncdb: threads=68 cpu=121% hot(>=50%)=0 warm(>=10%)=0 top=[3,3,3,3,3,3]% sleeps=12591/s preempted=1769/s faults=15121/s io_uring_workers=2 +2026-10-11T14:19:54.052Z info asyncdb: answered=0/s inflight=0 (max 0) pool size=256 open=256 in_use=0.0 idle=256.0 missing=0 waited=0 dropped=0 | statement mean=0us p99=0us | request mean=0us p99=0us | hold~0us +2026-10-11T14:19:54.052Z info asyncdb: threads=68 cpu=0% hot(>=50%)=0 warm(>=10%)=0 top=[0,0,0,0,0,0]% sleeps=35/s preempted=0/s faults=0/s io_uring_workers=2 +2026-10-11T14:19:55.056Z info asyncdb: answered=44724/s inflight=716 (max 760) pool size=256 open=256 in_use=157.5 idle=98.5 missing=0 waited=38244 dropped=0 | statement mean=8747us p99=49152us | request mean=8748us p99=49152us | hold~3533us +2026-10-11T14:19:55.056Z info asyncdb: threads=68 cpu=488% hot(>=50%)=0 warm(>=10%)=0 top=[9,9,9,9,9,9]% sleeps=43204/s preempted=5827/s faults=57702/s io_uring_workers=2 +2026-10-11T14:19:56.060Z info asyncdb: answered=67812/s inflight=697 (max 785) pool size=256 open=256 in_use=254.9 idle=1.1 missing=0 waited=67812 dropped=0 | statement mean=10624us p99=57344us | request mean=10624us p99=57344us | hold~3758us +2026-10-11T14:19:56.060Z info asyncdb: threads=68 cpu=759% hot(>=50%)=0 warm(>=10%)=64 top=[13,13,13,13,13,13]% sleeps=67923/s preempted=9109/s faults=95632/s io_uring_workers=2 +2026-10-11T14:19:57.064Z info asyncdb: answered=67660/s inflight=677 (max 768) pool size=256 open=256 in_use=254.9 idle=1.1 missing=0 waited=67681 dropped=0 | statement mean=10460us p99=57344us | request mean=10461us p99=57344us | hold~3766us +2026-10-11T14:19:57.064Z info asyncdb: threads=68 cpu=753% hot(>=50%)=0 warm(>=10%)=64 top=[15,14,14,13,13,13]% sleeps=68827/s preempted=9281/s faults=89565/s io_uring_workers=2 +2026-10-11T14:19:58.068Z info asyncdb: answered=68290/s inflight=680 (max 753) pool size=256 open=256 in_use=255.1 idle=0.9 missing=0 waited=68171 dropped=0 | statement mean=10234us p99=53248us | request mean=10234us p99=53248us | hold~3740us +2026-10-11T14:19:58.068Z info asyncdb: threads=68 cpu=753% hot(>=50%)=0 warm(>=10%)=64 top=[13,13,13,13,13,13]% sleeps=66955/s preempted=10724/s faults=91437/s io_uring_workers=2 +2026-10-11T14:19:59.072Z info asyncdb: answered=67325/s inflight=698 (max 752) pool size=256 open=256 in_use=255.7 idle=0.3 missing=0 waited=67400 dropped=0 | statement mean=10243us p99=53248us | request mean=10244us p99=53248us | hold~3796us +2026-10-11T14:19:59.072Z info asyncdb: threads=68 cpu=752% hot(>=50%)=0 warm(>=10%)=64 top=[14,14,13,13,13,13]% sleeps=67703/s preempted=8820/s faults=92921/s io_uring_workers=2 +2026-10-11T14:20:00.075Z info asyncdb: answered=69772/s inflight=702 (max 750) pool size=256 open=256 in_use=254.6 idle=1.4 missing=0 waited=69846 dropped=0 | statement mean=9843us p99=53248us | request mean=9844us p99=53248us | hold~3645us +2026-10-11T14:20:00.075Z info asyncdb: threads=68 cpu=772% hot(>=50%)=0 warm(>=10%)=64 top=[14,14,13,13,13,13]% sleeps=69948/s preempted=9178/s faults=93308/s io_uring_workers=2 +2026-10-11T14:20:01.079Z info asyncdb: answered=70128/s inflight=688 (max 744) pool size=256 open=256 in_use=254.9 idle=1.1 missing=0 waited=70038 dropped=0 | statement mean=9609us p99=53248us | request mean=9610us p99=53248us | hold~3635us +2026-10-11T14:20:01.079Z info asyncdb: threads=68 cpu=775% hot(>=50%)=0 warm(>=10%)=64 top=[14,14,14,14,13,13]% sleeps=70062/s preempted=8448/s faults=93199/s io_uring_workers=2 +2026-10-11T14:20:02.082Z info asyncdb: answered=69693/s inflight=638 (max 727) pool size=256 open=256 in_use=253.4 idle=2.6 missing=0 waited=69715 dropped=0 | statement mean=9544us p99=49152us | request mean=9545us p99=49152us | hold~3635us +2026-10-11T14:20:02.082Z info asyncdb: threads=68 cpu=771% hot(>=50%)=0 warm(>=10%)=64 top=[14,14,14,13,13,13]% sleeps=70033/s preempted=8725/s faults=93258/s io_uring_workers=2 +2026-10-11T14:20:03.086Z info asyncdb: answered=70212/s inflight=683 (max 723) pool size=256 open=256 in_use=253.6 idle=2.4 missing=0 waited=70167 dropped=0 | statement mean=9394us p99=53248us | request mean=9394us p99=53248us | hold~3612us +2026-10-11T14:20:03.086Z info asyncdb: threads=68 cpu=781% hot(>=50%)=0 warm(>=10%)=64 top=[15,14,14,14,14,13]% sleeps=71836/s preempted=8280/s faults=94687/s io_uring_workers=2 +2026-10-11T14:20:04.090Z info asyncdb: answered=67809/s inflight=642 (max 718) pool size=256 open=256 in_use=254.8 idle=1.2 missing=0 waited=67773 dropped=0 | statement mean=9671us p99=53248us | request mean=9671us p99=53248us | hold~3758us +2026-10-11T14:20:04.090Z info asyncdb: threads=68 cpu=748% hot(>=50%)=0 warm(>=10%)=64 top=[14,14,13,13,13,13]% sleeps=70714/s preempted=8800/s faults=92401/s io_uring_workers=2 +2026-10-11T14:20:05.094Z info asyncdb: answered=31384/s inflight=0 (max 705) pool size=256 open=256 in_use=100.9 idle=155.1 missing=0 waited=30968 dropped=0 | statement mean=9159us p99=49152us | request mean=9159us p99=49152us | hold~3196us +2026-10-11T14:20:05.094Z info asyncdb: threads=68 cpu=348% hot(>=50%)=0 warm(>=10%)=0 top=[7,7,6,6,6,6]% sleeps=32155/s preempted=3949/s faults=41266/s io_uring_workers=2 +2026-10-11T14:20:06.102Z info asyncdb: answered=0/s inflight=0 (max 0) pool size=256 open=256 in_use=0.0 idle=256.0 missing=0 waited=0 dropped=0 | statement mean=0us p99=0us | request mean=0us p99=0us | hold~0us +2026-10-11T14:20:06.102Z info asyncdb: threads=68 cpu=1% hot(>=50%)=0 warm(>=10%)=0 top=[1,0,0,0,0,0]% sleeps=35/s preempted=1/s faults=2/s io_uring_workers=2 +2026-10-11T14:20:07.107Z info asyncdb: answered=26250/s inflight=726 (max 757) pool size=256 open=256 in_use=90.9 idle=165.1 missing=0 waited=19589 dropped=0 | statement mean=7516us p99=45056us | request mean=7518us p99=45056us | hold~3478us +2026-10-11T14:20:07.107Z info asyncdb: threads=68 cpu=288% hot(>=50%)=0 warm(>=10%)=0 top=[6,6,6,6,5,5]% sleeps=24054/s preempted=4063/s faults=30483/s io_uring_workers=2 +2026-10-11T14:20:08.111Z info asyncdb: answered=65922/s inflight=695 (max 786) pool size=256 open=256 in_use=252.3 idle=3.7 missing=0 waited=65866 dropped=0 | statement mean=10864us p99=57344us | request mean=10865us p99=57344us | hold~3830us +2026-10-11T14:20:08.111Z info asyncdb: threads=68 cpu=745% hot(>=50%)=0 warm(>=10%)=64 top=[14,13,13,13,13,13]% sleeps=67204/s preempted=8109/s faults=95881/s io_uring_workers=2 +2026-10-11T14:20:09.114Z info asyncdb: answered=69918/s inflight=706 (max 773) pool size=256 open=256 in_use=254.3 idle=1.7 missing=0 waited=69971 dropped=0 | statement mean=10224us p99=57344us | request mean=10225us p99=57344us | hold~3635us +2026-10-11T14:20:09.114Z info asyncdb: threads=68 cpu=772% hot(>=50%)=0 warm(>=10%)=64 top=[14,14,14,13,13,13]% sleeps=70464/s preempted=9503/s faults=90975/s io_uring_workers=2 +2026-10-11T14:20:10.118Z info asyncdb: answered=68458/s inflight=701 (max 763) pool size=256 open=256 in_use=254.4 idle=1.6 missing=0 waited=68422 dropped=0 | statement mean=10342us p99=53248us | request mean=10343us p99=53248us | hold~3714us +2026-10-11T14:20:10.118Z info asyncdb: threads=68 cpu=751% hot(>=50%)=0 warm(>=10%)=64 top=[14,13,13,13,13,13]% sleeps=68029/s preempted=8715/s faults=91778/s io_uring_workers=2 +2026-10-11T14:20:11.121Z info asyncdb: answered=68342/s inflight=700 (max 754) pool size=256 open=256 in_use=255.4 idle=0.6 missing=0 waited=68341 dropped=0 | statement mean=10220us p99=53248us | request mean=10220us p99=53248us | hold~3736us +2026-10-11T14:20:11.121Z info asyncdb: threads=68 cpu=761% hot(>=50%)=0 warm(>=10%)=64 top=[14,14,14,13,13,13]% sleeps=68279/s preempted=8845/s faults=92372/s io_uring_workers=2 +2026-10-11T14:20:12.125Z info asyncdb: answered=68661/s inflight=680 (max 743) pool size=256 open=256 in_use=254.5 idle=1.5 missing=0 waited=68621 dropped=0 | statement mean=10064us p99=53248us | request mean=10065us p99=53248us | hold~3707us +2026-10-11T14:20:12.125Z info asyncdb: threads=68 cpu=767% hot(>=50%)=0 warm(>=10%)=64 top=[14,13,13,13,13,13]% sleeps=72188/s preempted=8738/s faults=93095/s io_uring_workers=2 +2026-10-11T14:20:13.129Z info asyncdb: answered=68137/s inflight=699 (max 768) pool size=256 open=256 in_use=254.0 idle=2.0 missing=0 waited=68143 dropped=0 | statement mean=10154us p99=57344us | request mean=10154us p99=57344us | hold~3730us +2026-10-11T14:20:13.129Z info asyncdb: threads=68 cpu=753% hot(>=50%)=0 warm(>=10%)=64 top=[14,14,14,14,13,13]% sleeps=73365/s preempted=9073/s faults=92164/s io_uring_workers=2 +2026-10-11T14:20:14.132Z info asyncdb: answered=67693/s inflight=685 (max 753) pool size=256 open=256 in_use=254.5 idle=1.5 missing=0 waited=67627 dropped=0 | statement mean=10039us p99=53248us | request mean=10040us p99=53248us | hold~3760us +2026-10-11T14:20:14.132Z info asyncdb: threads=68 cpu=760% hot(>=50%)=0 warm(>=10%)=64 top=[14,13,13,13,13,13]% sleeps=69513/s preempted=9347/s faults=90432/s io_uring_workers=2 +2026-10-11T14:20:15.136Z info asyncdb: answered=70130/s inflight=673 (max 734) pool size=256 open=256 in_use=255.0 idle=1.0 missing=0 waited=70173 dropped=0 | statement mean=9588us p99=53248us | request mean=9589us p99=53248us | hold~3635us +2026-10-11T14:20:15.136Z info asyncdb: threads=68 cpu=775% hot(>=50%)=0 warm(>=10%)=64 top=[14,14,14,14,13,13]% sleeps=71108/s preempted=8629/s faults=93709/s io_uring_workers=2 +2026-10-11T14:20:16.140Z info asyncdb: answered=68935/s inflight=703 (max 726) pool size=256 open=256 in_use=253.7 idle=2.3 missing=0 waited=69007 dropped=0 | statement mean=9648us p99=53248us | request mean=9649us p99=53248us | hold~3677us +2026-10-11T14:20:16.140Z info asyncdb: threads=68 cpu=767% hot(>=50%)=0 warm(>=10%)=64 top=[14,14,14,14,14,13]% sleeps=71802/s preempted=8847/s faults=93139/s io_uring_workers=2 +2026-10-11T14:20:17.143Z info asyncdb: answered=49835/s inflight=0 (max 709) pool size=256 open=256 in_use=176.7 idle=79.3 missing=0 waited=49303 dropped=0 | statement mean=9543us p99=53248us | request mean=9544us p99=53248us | hold~3536us +2026-10-11T14:20:17.143Z info asyncdb: threads=68 cpu=556% hot(>=50%)=0 warm(>=10%)=10 top=[10,10,10,10,10,10]% sleeps=53120/s preempted=6117/s faults=67606/s io_uring_workers=2 +2026-10-11T14:20:18.149Z info asyncdb: answered=0/s inflight=0 (max 0) pool size=256 open=256 in_use=0.0 idle=256.0 missing=0 waited=0 dropped=0 | statement mean=0us p99=0us | request mean=0us p99=0us | hold~0us +2026-10-11T14:20:18.149Z info asyncdb: threads=68 cpu=0% hot(>=50%)=0 warm(>=10%)=0 top=[0,0,0,0,0,0]% sleeps=35/s preempted=1/s faults=0/s io_uring_workers=2 diff --git a/site/static/logs/async/32000/nilo.log b/site/static/logs/async/32000/nilo.log index 2ca69ee8c..91921780b 100644 --- a/site/static/logs/async/32000/nilo.log +++ b/site/static/logs/async/32000/nilo.log @@ -1,2 +1,5 @@ -info: nilo listening on 0.0.0.0:8080 across 64 thread(s) -info: nilo also listening on https://0.0.0.0:8081 +2026-10-11T14:32:02.562Z info nilo: loaded 20 static file(s) (1758039 bytes held, 486436 of them precompressed files) from "/data/static" onto "/static" +2026-10-11T14:32:02.604Z info nilo listening on 0.0.0.0:8080 across 64 thread(s) +2026-10-11T14:32:02.604Z info nilo also listening on 0.0.0.0:8082 +2026-10-11T14:32:02.604Z info nilo also listening on https://0.0.0.0:8081 +2026-10-11T14:32:02.604Z info nilo also listening on https://0.0.0.0:8443 diff --git a/site/static/logs/baseline-h2/1024/nilo.log b/site/static/logs/baseline-h2/1024/nilo.log new file mode 100644 index 000000000..679831614 --- /dev/null +++ b/site/static/logs/baseline-h2/1024/nilo.log @@ -0,0 +1,5 @@ +2026-10-11T14:20:42.853Z info nilo: loaded 20 static file(s) (1758039 bytes held, 486436 of them precompressed files) from "/data/static" onto "/static" +2026-10-11T14:20:42.909Z info nilo listening on 0.0.0.0:8080 across 64 thread(s) +2026-10-11T14:20:42.909Z info nilo also listening on 0.0.0.0:8082 +2026-10-11T14:20:42.909Z info nilo also listening on https://0.0.0.0:8081 +2026-10-11T14:20:42.909Z info nilo also listening on https://0.0.0.0:8443 diff --git a/site/static/logs/baseline-h2/256/nilo.log b/site/static/logs/baseline-h2/256/nilo.log new file mode 100644 index 000000000..11d5bf1c5 --- /dev/null +++ b/site/static/logs/baseline-h2/256/nilo.log @@ -0,0 +1,5 @@ +2026-10-11T14:20:19.717Z info nilo: loaded 20 static file(s) (1758039 bytes held, 486436 of them precompressed files) from "/data/static" onto "/static" +2026-10-11T14:20:19.773Z info nilo listening on 0.0.0.0:8080 across 64 thread(s) +2026-10-11T14:20:19.773Z info nilo also listening on 0.0.0.0:8082 +2026-10-11T14:20:19.773Z info nilo also listening on https://0.0.0.0:8081 +2026-10-11T14:20:19.773Z info nilo also listening on https://0.0.0.0:8443 diff --git a/site/static/logs/baseline-h2c/1024/nilo.log b/site/static/logs/baseline-h2c/1024/nilo.log new file mode 100644 index 000000000..80078b844 --- /dev/null +++ b/site/static/logs/baseline-h2c/1024/nilo.log @@ -0,0 +1,5 @@ +2026-10-11T14:22:15.928Z info nilo: loaded 20 static file(s) (1758039 bytes held, 486436 of them precompressed files) from "/data/static" onto "/static" +2026-10-11T14:22:15.952Z info nilo listening on 0.0.0.0:8080 across 64 thread(s) +2026-10-11T14:22:15.952Z info nilo also listening on 0.0.0.0:8082 +2026-10-11T14:22:15.952Z info nilo also listening on https://0.0.0.0:8081 +2026-10-11T14:22:15.952Z info nilo also listening on https://0.0.0.0:8443 diff --git a/site/static/logs/baseline-h2c/256/nilo.log b/site/static/logs/baseline-h2c/256/nilo.log new file mode 100644 index 000000000..4fd235d1a --- /dev/null +++ b/site/static/logs/baseline-h2c/256/nilo.log @@ -0,0 +1,5 @@ +2026-10-11T14:21:52.786Z info nilo: loaded 20 static file(s) (1758039 bytes held, 486436 of them precompressed files) from "/data/static" onto "/static" +2026-10-11T14:21:52.843Z info nilo listening on 0.0.0.0:8080 across 64 thread(s) +2026-10-11T14:21:52.843Z info nilo also listening on 0.0.0.0:8082 +2026-10-11T14:21:52.843Z info nilo also listening on https://0.0.0.0:8081 +2026-10-11T14:21:52.843Z info nilo also listening on https://0.0.0.0:8443 diff --git a/site/static/logs/baseline-h2c/4096/nilo.log b/site/static/logs/baseline-h2c/4096/nilo.log new file mode 100644 index 000000000..244f7c77e --- /dev/null +++ b/site/static/logs/baseline-h2c/4096/nilo.log @@ -0,0 +1,5 @@ +2026-10-11T14:22:39.179Z info nilo: loaded 20 static file(s) (1758039 bytes held, 486436 of them precompressed files) from "/data/static" onto "/static" +2026-10-11T14:22:39.206Z info nilo listening on 0.0.0.0:8080 across 64 thread(s) +2026-10-11T14:22:39.206Z info nilo also listening on 0.0.0.0:8082 +2026-10-11T14:22:39.206Z info nilo also listening on https://0.0.0.0:8081 +2026-10-11T14:22:39.206Z info nilo also listening on https://0.0.0.0:8443 diff --git a/site/static/logs/baseline/4096/nilo.log b/site/static/logs/baseline/4096/nilo.log index 2ca69ee8c..40c1383d8 100644 --- a/site/static/logs/baseline/4096/nilo.log +++ b/site/static/logs/baseline/4096/nilo.log @@ -1,2 +1,5 @@ -info: nilo listening on 0.0.0.0:8080 across 64 thread(s) -info: nilo also listening on https://0.0.0.0:8081 +2026-10-11T14:16:52.628Z info nilo: loaded 20 static file(s) (1758039 bytes held, 486436 of them precompressed files) from "/data/static" onto "/static" +2026-10-11T14:16:52.684Z info nilo listening on 0.0.0.0:8080 across 64 thread(s) +2026-10-11T14:16:52.684Z info nilo also listening on 0.0.0.0:8082 +2026-10-11T14:16:52.684Z info nilo also listening on https://0.0.0.0:8081 +2026-10-11T14:16:52.684Z info nilo also listening on https://0.0.0.0:8443 diff --git a/site/static/logs/echo-ws-limited/4096/nilo.log b/site/static/logs/echo-ws-limited/4096/nilo.log index 2ca69ee8c..047bdbd2f 100644 --- a/site/static/logs/echo-ws-limited/4096/nilo.log +++ b/site/static/logs/echo-ws-limited/4096/nilo.log @@ -1,2 +1,5 @@ -info: nilo listening on 0.0.0.0:8080 across 64 thread(s) -info: nilo also listening on https://0.0.0.0:8081 +2026-10-11T14:28:08.479Z info nilo: loaded 20 static file(s) (1758039 bytes held, 486436 of them precompressed files) from "/data/static" onto "/static" +2026-10-11T14:28:08.522Z info nilo listening on 0.0.0.0:8080 across 64 thread(s) +2026-10-11T14:28:08.522Z info nilo also listening on 0.0.0.0:8082 +2026-10-11T14:28:08.522Z info nilo also listening on https://0.0.0.0:8081 +2026-10-11T14:28:08.522Z info nilo also listening on https://0.0.0.0:8443 diff --git a/site/static/logs/echo-ws-limited/512/nilo.log b/site/static/logs/echo-ws-limited/512/nilo.log index 2ca69ee8c..9e9ba2bf5 100644 --- a/site/static/logs/echo-ws-limited/512/nilo.log +++ b/site/static/logs/echo-ws-limited/512/nilo.log @@ -1,2 +1,5 @@ -info: nilo listening on 0.0.0.0:8080 across 64 thread(s) -info: nilo also listening on https://0.0.0.0:8081 +2026-10-11T14:27:44.841Z info nilo: loaded 20 static file(s) (1758039 bytes held, 486436 of them precompressed files) from "/data/static" onto "/static" +2026-10-11T14:27:44.872Z info nilo listening on 0.0.0.0:8080 across 64 thread(s) +2026-10-11T14:27:44.872Z info nilo also listening on 0.0.0.0:8082 +2026-10-11T14:27:44.872Z info nilo also listening on https://0.0.0.0:8081 +2026-10-11T14:27:44.872Z info nilo also listening on https://0.0.0.0:8443 diff --git a/site/static/logs/echo-ws-pipeline/16384/nilo.log b/site/static/logs/echo-ws-pipeline/16384/nilo.log index 2ca69ee8c..7973fa2f7 100644 --- a/site/static/logs/echo-ws-pipeline/16384/nilo.log +++ b/site/static/logs/echo-ws-pipeline/16384/nilo.log @@ -1,2 +1,5 @@ -info: nilo listening on 0.0.0.0:8080 across 64 thread(s) -info: nilo also listening on https://0.0.0.0:8081 +2026-10-11T14:27:21.030Z info nilo: loaded 20 static file(s) (1758039 bytes held, 486436 of them precompressed files) from "/data/static" onto "/static" +2026-10-11T14:27:21.063Z info nilo listening on 0.0.0.0:8080 across 64 thread(s) +2026-10-11T14:27:21.063Z info nilo also listening on 0.0.0.0:8082 +2026-10-11T14:27:21.063Z info nilo also listening on https://0.0.0.0:8081 +2026-10-11T14:27:21.063Z info nilo also listening on https://0.0.0.0:8443 diff --git a/site/static/logs/echo-ws-pipeline/4096/nilo.log b/site/static/logs/echo-ws-pipeline/4096/nilo.log index 2ca69ee8c..242ac0263 100644 --- a/site/static/logs/echo-ws-pipeline/4096/nilo.log +++ b/site/static/logs/echo-ws-pipeline/4096/nilo.log @@ -1,2 +1,5 @@ -info: nilo listening on 0.0.0.0:8080 across 64 thread(s) -info: nilo also listening on https://0.0.0.0:8081 +2026-10-11T14:26:57.329Z info nilo: loaded 20 static file(s) (1758039 bytes held, 486436 of them precompressed files) from "/data/static" onto "/static" +2026-10-11T14:26:57.373Z info nilo listening on 0.0.0.0:8080 across 64 thread(s) +2026-10-11T14:26:57.373Z info nilo also listening on 0.0.0.0:8082 +2026-10-11T14:26:57.373Z info nilo also listening on https://0.0.0.0:8081 +2026-10-11T14:26:57.373Z info nilo also listening on https://0.0.0.0:8443 diff --git a/site/static/logs/echo-ws-pipeline/512/nilo.log b/site/static/logs/echo-ws-pipeline/512/nilo.log index 2ca69ee8c..ed0a4bc8d 100644 --- a/site/static/logs/echo-ws-pipeline/512/nilo.log +++ b/site/static/logs/echo-ws-pipeline/512/nilo.log @@ -1,2 +1,5 @@ -info: nilo listening on 0.0.0.0:8080 across 64 thread(s) -info: nilo also listening on https://0.0.0.0:8081 +2026-10-11T14:26:33.703Z info nilo: loaded 20 static file(s) (1758039 bytes held, 486436 of them precompressed files) from "/data/static" onto "/static" +2026-10-11T14:26:33.762Z info nilo listening on 0.0.0.0:8080 across 64 thread(s) +2026-10-11T14:26:33.762Z info nilo also listening on 0.0.0.0:8082 +2026-10-11T14:26:33.762Z info nilo also listening on https://0.0.0.0:8081 +2026-10-11T14:26:33.762Z info nilo also listening on https://0.0.0.0:8443 diff --git a/site/static/logs/echo-ws/16384/nilo.log b/site/static/logs/echo-ws/16384/nilo.log index 2ca69ee8c..1a7bbc8d4 100644 --- a/site/static/logs/echo-ws/16384/nilo.log +++ b/site/static/logs/echo-ws/16384/nilo.log @@ -1,2 +1,5 @@ -info: nilo listening on 0.0.0.0:8080 across 64 thread(s) -info: nilo also listening on https://0.0.0.0:8081 +2026-10-11T14:26:10.029Z info nilo: loaded 20 static file(s) (1758039 bytes held, 486436 of them precompressed files) from "/data/static" onto "/static" +2026-10-11T14:26:10.076Z info nilo listening on 0.0.0.0:8080 across 64 thread(s) +2026-10-11T14:26:10.076Z info nilo also listening on 0.0.0.0:8082 +2026-10-11T14:26:10.076Z info nilo also listening on https://0.0.0.0:8081 +2026-10-11T14:26:10.076Z info nilo also listening on https://0.0.0.0:8443 diff --git a/site/static/logs/echo-ws/4096/nilo.log b/site/static/logs/echo-ws/4096/nilo.log index 2ca69ee8c..d5706a963 100644 --- a/site/static/logs/echo-ws/4096/nilo.log +++ b/site/static/logs/echo-ws/4096/nilo.log @@ -1,2 +1,5 @@ -info: nilo listening on 0.0.0.0:8080 across 64 thread(s) -info: nilo also listening on https://0.0.0.0:8081 +2026-10-11T14:25:46.320Z info nilo: loaded 20 static file(s) (1758039 bytes held, 486436 of them precompressed files) from "/data/static" onto "/static" +2026-10-11T14:25:46.361Z info nilo listening on 0.0.0.0:8080 across 64 thread(s) +2026-10-11T14:25:46.361Z info nilo also listening on 0.0.0.0:8082 +2026-10-11T14:25:46.361Z info nilo also listening on https://0.0.0.0:8081 +2026-10-11T14:25:46.361Z info nilo also listening on https://0.0.0.0:8443 diff --git a/site/static/logs/echo-ws/512/nilo.log b/site/static/logs/echo-ws/512/nilo.log index 2ca69ee8c..f4d809555 100644 --- a/site/static/logs/echo-ws/512/nilo.log +++ b/site/static/logs/echo-ws/512/nilo.log @@ -1,2 +1,5 @@ -info: nilo listening on 0.0.0.0:8080 across 64 thread(s) -info: nilo also listening on https://0.0.0.0:8081 +2026-10-11T14:25:22.628Z info nilo: loaded 20 static file(s) (1758039 bytes held, 486436 of them precompressed files) from "/data/static" onto "/static" +2026-10-11T14:25:22.680Z info nilo listening on 0.0.0.0:8080 across 64 thread(s) +2026-10-11T14:25:22.680Z info nilo also listening on 0.0.0.0:8082 +2026-10-11T14:25:22.680Z info nilo also listening on https://0.0.0.0:8081 +2026-10-11T14:25:22.680Z info nilo also listening on https://0.0.0.0:8443 diff --git a/site/static/logs/json-comp/16384/nilo.log b/site/static/logs/json-comp/16384/nilo.log index 009cd83f3..eeab01bc5 100644 --- a/site/static/logs/json-comp/16384/nilo.log +++ b/site/static/logs/json-comp/16384/nilo.log @@ -1,312 +1,6 @@ -info: nilo listening on 0.0.0.0:8080 across 64 thread(s) -info: nilo also listening on https://0.0.0.0:8081 -warning: handler GET /json/40 failed after answering: WriteFailed -warning: handler GET /json/50 failed after answering: WriteFailed -warning: handler GET /json/40 failed after answering: WriteFailed -warning: handler GET /json/25 failed after answering: WriteFailed -warning: handler GET /json/50 failed after answering: WriteFailed -warning: handler GET /json/25 failed after answering: WriteFailed -warning: handler GET /json/25 failed after answering: WriteFailed -warning: handler GET /json/40 failed after answering: WriteFailed -warning: handler GET /json/25 failed after answering: WriteFailed -warning: handler GET /json/50 failed after answering: WriteFailed -warning: handler GET /json/40 failed after answering: WriteFailed -warning: handler GET /json/50 failed after answering: WriteFailed -warning: handler GET /json/50 failed after answering: WriteFailed -warning: handler GET /json/25 failed after answering: WriteFailed -warning: handler GET /json/50 failed after answering: WriteFailed -warning: handler GET /json/40 failed after answering: WriteFailed -warning: handler GET /json/50 failed after answering: WriteFailed -warning: handler GET /json/25 failed after answering: WriteFailed -warning: handler GET /json/50 failed after answering: WriteFailed -warning: handler GET /json/50 failed after answering: WriteFailed -warning: handler GET /json/40 failed after answering: WriteFailed -warning: handler GET /json/50 failed after answering: WriteFailed -warning: handler GET /json/50 failed after answering: WriteFailed -warning: handler GET /json/50 failed after answering: WriteFailed -warning: handler GET /json/50 failed after answering: WriteFailed -warning: handler GET /json/50 failed after answering: WriteFailed -warning: handler GET /json/40 failed after answering: WriteFailed -warning: handler GET /json/40 failed after answering: WriteFailed -warning: handler GET /json/50 failed after answering: WriteFailed -warning: handler GET /json/25 failed after answering: WriteFailed -warning: handler GET /json/25 failed after answering: WriteFailed -warning: handler GET /json/25 failed after answering: WriteFailed -warning: handler GET /json/40 failed after answering: WriteFailed -warning: handler GET /json/25 failed after answering: WriteFailed -warning: handler GET /json/40 failed after answering: WriteFailed -warning: handler GET /json/40 failed after answering: WriteFailed -warning: handler GET /json/40 failed after answering: WriteFailed -warning: handler GET /json/40 failed after answering: WriteFailed -warning: handler GET /json/40 failed after answering: WriteFailed -warning: handler GET /json/40 failed after answering: WriteFailed -warning: handler GET /json/40 failed after answering: WriteFailed -warning: handler GET /json/25 failed after answering: WriteFailed -warning: handler GET /json/40 failed after answering: WriteFailed -warning: handler GET /json/40 failed after answering: WriteFailed -warning: handler GET /json/25 failed after answering: WriteFailed -warning: handler GET /json/40 failed after answering: WriteFailed -warning: handler GET /json/50 failed after answering: WriteFailed -warning: handler GET /json/25 failed after answering: WriteFailed -warning: handler GET /json/40 failed after answering: WriteFailed -warning: handler GET /json/40 failed after answering: WriteFailed -warning: handler GET /json/25 failed after answering: WriteFailed -warning: handler GET /json/25 failed after answering: WriteFailed -warning: handler GET /json/40 failed after answering: WriteFailed -warning: handler GET /json/40 failed after answering: WriteFailed -warning: handler GET /json/40 failed after answering: WriteFailed -warning: handler GET /json/25 failed after answering: WriteFailed -warning: handler GET /json/40 failed after answering: WriteFailed -warning: handler GET /json/25 failed after answering: WriteFailed -warning: handler GET /json/40 failed after answering: WriteFailed -warning: handler GET /json/25 failed after answering: WriteFailed -warning: handler GET /json/50 failed after answering: WriteFailed -warning: handler GET /json/50 failed after answering: WriteFailed -warning: handler GET /json/25 failed after answering: WriteFailed -warning: handler GET /json/40 failed after answering: WriteFailed -warning: handler GET /json/25 failed after answering: WriteFailed -warning: handler GET /json/25 failed after answering: WriteFailed -warning: handler GET /json/50 failed after answering: WriteFailed -warning: handler GET /json/40 failed after answering: WriteFailed -warning: handler GET /json/40 failed after answering: WriteFailed -warning: handler GET /json/40 failed after answering: WriteFailed -warning: handler GET /json/25 failed after answering: WriteFailed -warning: handler GET /json/40 failed after answering: WriteFailed -warning: handler GET /json/50 failed after answering: WriteFailed -warning: handler GET /json/50 failed after answering: WriteFailed -warning: handler GET /json/50 failed after answering: WriteFailed -warning: handler GET /json/40 failed after answering: WriteFailed -warning: handler GET /json/25 failed after answering: WriteFailed -warning: handler GET /json/50 failed after answering: WriteFailed -warning: handler GET /json/50 failed after answering: WriteFailed -warning: handler GET /json/25 failed after answering: WriteFailed -warning: handler GET /json/40 failed after answering: WriteFailed -warning: handler GET /json/40 failed after answering: WriteFailed -warning: handler GET /json/40 failed after answering: WriteFailed -warning: handler GET /json/40 failed after answering: WriteFailed -warning: handler GET /json/40 failed after answering: WriteFailed -warning: handler GET /json/40 failed after answering: WriteFailed -warning: handler GET /json/25 failed after answering: WriteFailed -warning: handler GET /json/40 failed after answering: WriteFailed -warning: handler GET /json/40 failed after answering: WriteFailed -warning: handler GET /json/50 failed after answering: WriteFailed -warning: handler GET /json/25 failed after answering: WriteFailed -warning: handler GET /json/25 failed after answering: WriteFailed -warning: handler GET /json/40 failed after answering: WriteFailed -warning: handler GET /json/25 failed after answering: WriteFailed -warning: handler GET /json/25 failed after answering: WriteFailed -warning: handler GET /json/50 failed after answering: WriteFailed -warning: handler GET /json/50 failed after answering: WriteFailed -warning: handler GET /json/40 failed after answering: WriteFailed -warning: handler GET /json/40 failed after answering: WriteFailed -warning: handler GET /json/25 failed after answering: WriteFailed -warning: handler GET /json/25 failed after answering: WriteFailed -warning: handler GET /json/50 failed after answering: WriteFailed -warning: handler GET /json/25 failed after answering: WriteFailed -warning: handler GET /json/40 failed after answering: WriteFailed -warning: handler GET /json/40 failed after answering: WriteFailed -warning: handler GET /json/25 failed after answering: WriteFailed -warning: handler GET /json/25 failed after answering: WriteFailed -warning: handler GET /json/40 failed after answering: WriteFailed -warning: handler GET /json/50 failed after answering: WriteFailed -warning: handler GET /json/40 failed after answering: WriteFailed -warning: handler GET /json/25 failed after answering: WriteFailed -warning: handler GET /json/25 failed after answering: WriteFailed -warning: handler GET /json/25 failed after answering: WriteFailed -warning: handler GET /json/50 failed after answering: WriteFailed -warning: handler GET /json/25 failed after answering: WriteFailed -warning: handler GET /json/50 failed after answering: WriteFailed -warning: handler GET /json/25 failed after answering: WriteFailed -warning: handler GET /json/40 failed after answering: WriteFailed -warning: handler GET /json/50 failed after answering: WriteFailed -warning: handler GET /json/50 failed after answering: WriteFailed -warning: handler GET /json/40 failed after answering: WriteFailed -warning: handler GET /json/40 failed after answering: WriteFailed -warning: handler GET /json/25 failed after answering: WriteFailed -warning: handler GET /json/50 failed after answering: WriteFailed -warning: handler GET /json/50 failed after answering: WriteFailed -warning: handler GET /json/25 failed after answering: WriteFailed -warning: handler GET /json/50 failed after answering: WriteFailed -warning: handler GET /json/40 failed after answering: WriteFailed -warning: handler GET /json/25 failed after answering: WriteFailed -warning: handler GET /json/25 failed after answering: WriteFailed -warning: handler GET /json/50 failed after answering: WriteFailed -warning: handler GET /json/25 failed after answering: WriteFailed -warning: handler GET /json/50 failed after answering: WriteFailed -warning: handler GET /json/50 failed after answering: WriteFailed -warning: handler GET /json/50 failed after answering: WriteFailed -warning: handler GET /json/25 failed after answering: WriteFailed -warning: handler GET /json/40 failed after answering: WriteFailed -warning: handler GET /json/25 failed after answering: WriteFailed -warning: handler GET /json/40 failed after answering: WriteFailed -warning: handler GET /json/50 failed after answering: WriteFailed -warning: handler GET /json/50 failed after answering: WriteFailed -warning: handler GET /json/25 failed after answering: WriteFailed -warning: handler GET /json/50 failed after answering: WriteFailed -warning: handler GET /json/40 failed after answering: WriteFailed -warning: handler GET /json/40 failed after answering: WriteFailed -warning: handler GET /json/50 failed after answering: WriteFailed -warning: handler GET /json/40 failed after answering: WriteFailed -warning: handler GET /json/40 failed after answering: WriteFailed -warning: handler GET /json/50 failed after answering: WriteFailed -warning: handler GET /json/50 failed after answering: WriteFailed -warning: handler GET /json/25 failed after answering: WriteFailed -warning: handler GET /json/40 failed after answering: WriteFailed -warning: handler GET /json/25 failed after answering: WriteFailed -warning: handler GET /json/40 failed after answering: WriteFailed -warning: handler GET /json/40 failed after answering: WriteFailed -warning: handler GET /json/40 failed after answering: WriteFailed -warning: handler GET /json/25 failed after answering: WriteFailed -warning: handler GET /json/50 failed after answering: WriteFailed -warning: handler GET /json/25 failed after answering: WriteFailed -warning: handler GET /json/50 failed after answering: WriteFailed -warning: handler GET /json/25 failed after answering: WriteFailed -warning: handler GET /json/50 failed after answering: WriteFailed -warning: handler GET /json/40 failed after answering: WriteFailed -warning: handler GET /json/40 failed after answering: WriteFailed -warning: handler GET /json/40 failed after answering: WriteFailed -warning: handler GET /json/50 failed after answering: WriteFailed -warning: handler GET /json/25 failed after answering: WriteFailed -warning: handler GET /json/50 failed after answering: WriteFailed -warning: handler GET /json/40 failed after answering: WriteFailed -warning: handler GET /json/50 failed after answering: WriteFailed -warning: handler GET /json/25 failed after answering: WriteFailed -warning: handler GET /json/50 failed after answering: WriteFailed -warning: handler GET /json/40 failed after answering: WriteFailed -warning: handler GET /json/25 failed after answering: WriteFailed -warning: handler GET /json/25 failed after answering: WriteFailed -warning: handler GET /json/25 failed after answering: WriteFailed -warning: handler GET /json/50 failed after answering: WriteFailed -warning: handler GET /json/25 failed after answering: WriteFailed -warning: handler GET /json/25 failed after answering: WriteFailed -warning: handler GET /json/40 failed after answering: WriteFailed -warning: handler GET /json/25 failed after answering: WriteFailed -warning: handler GET /json/50 failed after answering: WriteFailed -warning: handler GET /json/40 failed after answering: WriteFailed -warning: handler GET /json/25 failed after answering: WriteFailed -warning: handler GET /json/50 failed after answering: WriteFailed -warning: handler GET /json/25 failed after answering: WriteFailed -warning: handler GET /json/40 failed after answering: WriteFailed -warning: handler GET /json/25 failed after answering: WriteFailed -warning: handler GET /json/25 failed after answering: WriteFailed -warning: handler GET /json/40 failed after answering: WriteFailed -warning: handler GET /json/25 failed after answering: WriteFailed -warning: handler GET /json/50 failed after answering: WriteFailed -warning: handler GET /json/40 failed after answering: WriteFailed -warning: handler GET /json/50 failed after answering: WriteFailed -warning: handler GET /json/50 failed after answering: WriteFailed -warning: handler GET /json/25 failed after answering: WriteFailed -warning: handler GET /json/50 failed after answering: WriteFailed -warning: handler GET /json/50 failed after answering: WriteFailed -warning: handler GET /json/50 failed after answering: WriteFailed -warning: handler GET /json/25 failed after answering: WriteFailed -warning: handler GET /json/50 failed after answering: WriteFailed -warning: handler GET /json/50 failed after answering: WriteFailed -warning: handler GET /json/25 failed after answering: WriteFailed -warning: handler GET /json/25 failed after answering: WriteFailed -warning: handler GET /json/25 failed after answering: WriteFailed -warning: handler GET /json/50 failed after answering: WriteFailed -warning: handler GET /json/50 failed after answering: WriteFailed -warning: handler GET /json/25 failed after answering: WriteFailed -warning: handler GET /json/40 failed after answering: WriteFailed -warning: handler GET /json/40 failed after answering: WriteFailed -warning: handler GET /json/25 failed after answering: WriteFailed -warning: handler GET /json/25 failed after answering: WriteFailed -warning: handler GET /json/25 failed after answering: WriteFailed -warning: handler GET /json/40 failed after answering: WriteFailed -warning: handler GET /json/40 failed after answering: WriteFailed -warning: handler GET /json/25 failed after answering: WriteFailed -warning: handler GET /json/40 failed after answering: WriteFailed -warning: handler GET /json/50 failed after answering: WriteFailed -warning: handler GET /json/50 failed after answering: WriteFailed -warning: handler GET /json/40 failed after answering: WriteFailed -warning: handler GET /json/25 failed after answering: WriteFailed -warning: handler GET /json/40 failed after answering: WriteFailed -warning: handler GET /json/40 failed after answering: WriteFailed -warning: handler GET /json/40 failed after answering: WriteFailed -warning: handler GET /json/40 failed after answering: WriteFailed -warning: handler GET /json/50 failed after answering: WriteFailed -warning: handler GET /json/40 failed after answering: WriteFailed -warning: handler GET /json/40 failed after answering: WriteFailed -warning: handler GET /json/50 failed after answering: WriteFailed -warning: handler GET /json/50 failed after answering: WriteFailed -warning: handler GET /json/25 failed after answering: WriteFailed -warning: handler GET /json/40 failed after answering: WriteFailed -warning: handler GET /json/25 failed after answering: WriteFailed -warning: handler GET /json/25 failed after answering: WriteFailed -warning: handler GET /json/50 failed after answering: WriteFailed -warning: handler GET /json/40 failed after answering: WriteFailed -warning: handler GET /json/25 failed after answering: WriteFailed -warning: handler GET /json/40 failed after answering: WriteFailed -warning: handler GET /json/50 failed after answering: WriteFailed -warning: handler GET /json/25 failed after answering: WriteFailed -warning: handler GET /json/25 failed after answering: WriteFailed -warning: handler GET /json/40 failed after answering: WriteFailed -warning: handler GET /json/25 failed after answering: WriteFailed -warning: handler GET /json/50 failed after answering: WriteFailed -warning: handler GET /json/25 failed after answering: WriteFailed -warning: handler GET /json/40 failed after answering: WriteFailed -warning: handler GET /json/25 failed after answering: WriteFailed -warning: handler GET /json/25 failed after answering: WriteFailed -warning: handler GET /json/40 failed after answering: WriteFailed -warning: handler GET /json/50 failed after answering: WriteFailed -warning: handler GET /json/40 failed after answering: WriteFailed -warning: handler GET /json/50 failed after answering: WriteFailed -warning: handler GET /json/40 failed after answering: WriteFailed -warning: handler GET /json/40 failed after answering: WriteFailed -warning: handler GET /json/40 failed after answering: WriteFailed -warning: handler GET /json/25 failed after answering: WriteFailed -warning: handler GET /json/40 failed after answering: WriteFailed -warning: handler GET /json/25 failed after answering: WriteFailed -warning: handler GET /json/50 failed after answering: WriteFailed -warning: handler GET /json/25 failed after answering: WriteFailed -warning: handler GET /json/50 failed after answering: WriteFailed -warning: handler GET /json/25 failed after answering: WriteFailed -warning: handler GET /json/25 failed after answering: WriteFailed -warning: handler GET /json/50 failed after answering: WriteFailed -warning: handler GET /json/50 failed after answering: WriteFailed -warning: handler GET /json/50 failed after answering: WriteFailed -warning: handler GET /json/50 failed after answering: WriteFailed -warning: handler GET /json/25 failed after answering: WriteFailed -warning: handler GET /json/40 failed after answering: WriteFailed -warning: handler GET /json/50 failed after answering: WriteFailed -warning: handler GET /json/50 failed after answering: WriteFailed -warning: handler GET /json/25 failed after answering: WriteFailed -warning: handler GET /json/40 failed after answering: WriteFailed -warning: handler GET /json/40 failed after answering: WriteFailed -warning: handler GET /json/25 failed after answering: WriteFailed -warning: handler GET /json/25 failed after answering: WriteFailed -warning: handler GET /json/25 failed after answering: WriteFailed -warning: handler GET /json/50 failed after answering: WriteFailed -warning: handler GET /json/40 failed after answering: WriteFailed -warning: handler GET /json/25 failed after answering: WriteFailed -warning: handler GET /json/40 failed after answering: WriteFailed -warning: handler GET /json/40 failed after answering: WriteFailed -warning: handler GET /json/50 failed after answering: WriteFailed -warning: handler GET /json/25 failed after answering: WriteFailed -warning: handler GET /json/40 failed after answering: WriteFailed -warning: handler GET /json/40 failed after answering: WriteFailed -warning: handler GET /json/25 failed after answering: WriteFailed -warning: handler GET /json/50 failed after answering: WriteFailed -warning: handler GET /json/50 failed after answering: WriteFailed -warning: handler GET /json/40 failed after answering: WriteFailed -warning: handler GET /json/40 failed after answering: WriteFailed -warning: handler GET /json/25 failed after answering: WriteFailed -warning: handler GET /json/50 failed after answering: WriteFailed -warning: handler GET /json/25 failed after answering: WriteFailed -warning: handler GET /json/50 failed after answering: WriteFailed -warning: handler GET /json/40 failed after answering: WriteFailed -warning: handler GET /json/25 failed after answering: WriteFailed -warning: handler GET /json/25 failed after answering: WriteFailed -warning: handler GET /json/25 failed after answering: WriteFailed -warning: handler GET /json/40 failed after answering: WriteFailed -warning: handler GET /json/50 failed after answering: WriteFailed -warning: handler GET /json/25 failed after answering: WriteFailed -warning: handler GET /json/50 failed after answering: WriteFailed -warning: handler GET /json/50 failed after answering: WriteFailed -warning: handler GET /json/25 failed after answering: WriteFailed -warning: handler GET /json/40 failed after answering: WriteFailed -warning: handler GET /json/25 failed after answering: WriteFailed -warning: handler GET /json/25 failed after answering: WriteFailed -warning: handler GET /json/40 failed after answering: WriteFailed -warning: handler GET /json/40 failed after answering: WriteFailed +2026-10-11T14:18:27.549Z info nilo: loaded 20 static file(s) (1758039 bytes held, 486436 of them precompressed files) from "/data/static" onto "/static" +2026-10-11T14:18:27.578Z info nilo listening on 0.0.0.0:8080 across 64 thread(s) +2026-10-11T14:18:27.578Z info nilo also listening on 0.0.0.0:8082 +2026-10-11T14:18:27.578Z info nilo also listening on https://0.0.0.0:8081 +2026-10-11T14:18:27.578Z info nilo also listening on https://0.0.0.0:8443 +2026-10-11T14:18:33.783Z warn handler GET /json/50 failed after answering: WriteFailed request=10789308d6653509 diff --git a/site/static/logs/json-comp/4096/nilo.log b/site/static/logs/json-comp/4096/nilo.log index 2ca69ee8c..0e000253d 100644 --- a/site/static/logs/json-comp/4096/nilo.log +++ b/site/static/logs/json-comp/4096/nilo.log @@ -1,2 +1,5 @@ -info: nilo listening on 0.0.0.0:8080 across 64 thread(s) -info: nilo also listening on https://0.0.0.0:8081 +2026-10-11T14:18:03.764Z info nilo: loaded 20 static file(s) (1758039 bytes held, 486436 of them precompressed files) from "/data/static" onto "/static" +2026-10-11T14:18:03.821Z info nilo listening on 0.0.0.0:8080 across 64 thread(s) +2026-10-11T14:18:03.821Z info nilo also listening on 0.0.0.0:8082 +2026-10-11T14:18:03.821Z info nilo also listening on https://0.0.0.0:8081 +2026-10-11T14:18:03.821Z info nilo also listening on https://0.0.0.0:8443 diff --git a/site/static/logs/json-h2c/1024/nilo.log b/site/static/logs/json-h2c/1024/nilo.log new file mode 100644 index 000000000..dbb515572 --- /dev/null +++ b/site/static/logs/json-h2c/1024/nilo.log @@ -0,0 +1,5 @@ +2026-10-11T14:23:02.522Z info nilo: loaded 20 static file(s) (1758039 bytes held, 486436 of them precompressed files) from "/data/static" onto "/static" +2026-10-11T14:23:02.566Z info nilo listening on 0.0.0.0:8080 across 64 thread(s) +2026-10-11T14:23:02.566Z info nilo also listening on 0.0.0.0:8082 +2026-10-11T14:23:02.566Z info nilo also listening on https://0.0.0.0:8081 +2026-10-11T14:23:02.566Z info nilo also listening on https://0.0.0.0:8443 diff --git a/site/static/logs/json-h2c/4096/nilo.log b/site/static/logs/json-h2c/4096/nilo.log new file mode 100644 index 000000000..74f282fce --- /dev/null +++ b/site/static/logs/json-h2c/4096/nilo.log @@ -0,0 +1,5 @@ +2026-10-11T14:23:25.781Z info nilo: loaded 20 static file(s) (1758039 bytes held, 486436 of them precompressed files) from "/data/static" onto "/static" +2026-10-11T14:23:25.828Z info nilo listening on 0.0.0.0:8080 across 64 thread(s) +2026-10-11T14:23:25.828Z info nilo also listening on 0.0.0.0:8082 +2026-10-11T14:23:25.828Z info nilo also listening on https://0.0.0.0:8081 +2026-10-11T14:23:25.828Z info nilo also listening on https://0.0.0.0:8443 diff --git a/site/static/logs/json-tls/4096/nilo.log b/site/static/logs/json-tls/4096/nilo.log index 2ca69ee8c..7052a5586 100644 --- a/site/static/logs/json-tls/4096/nilo.log +++ b/site/static/logs/json-tls/4096/nilo.log @@ -1,2 +1,5 @@ -info: nilo listening on 0.0.0.0:8080 across 64 thread(s) -info: nilo also listening on https://0.0.0.0:8081 +2026-10-11T14:18:51.418Z info nilo: loaded 20 static file(s) (1758039 bytes held, 486436 of them precompressed files) from "/data/static" onto "/static" +2026-10-11T14:18:51.456Z info nilo listening on 0.0.0.0:8080 across 64 thread(s) +2026-10-11T14:18:51.456Z info nilo also listening on 0.0.0.0:8082 +2026-10-11T14:18:51.456Z info nilo also listening on https://0.0.0.0:8081 +2026-10-11T14:18:51.456Z info nilo also listening on https://0.0.0.0:8443 diff --git a/site/static/logs/latency-10k/1024/nilo.log b/site/static/logs/latency-10k/1024/nilo.log index 2ca69ee8c..f26f08af2 100644 --- a/site/static/logs/latency-10k/1024/nilo.log +++ b/site/static/logs/latency-10k/1024/nilo.log @@ -1,2 +1,5 @@ -info: nilo listening on 0.0.0.0:8080 across 64 thread(s) -info: nilo also listening on https://0.0.0.0:8081 +2026-10-11T14:29:42.570Z info nilo: loaded 20 static file(s) (1758039 bytes held, 486436 of them precompressed files) from "/data/static" onto "/static" +2026-10-11T14:29:42.607Z info nilo listening on 0.0.0.0:8080 across 64 thread(s) +2026-10-11T14:29:42.607Z info nilo also listening on 0.0.0.0:8082 +2026-10-11T14:29:42.607Z info nilo also listening on https://0.0.0.0:8081 +2026-10-11T14:29:42.607Z info nilo also listening on https://0.0.0.0:8443 diff --git a/site/static/logs/latency-1m/1024/nilo.log b/site/static/logs/latency-1m/1024/nilo.log index 2ca69ee8c..923554397 100644 --- a/site/static/logs/latency-1m/1024/nilo.log +++ b/site/static/logs/latency-1m/1024/nilo.log @@ -1,2 +1,5 @@ -info: nilo listening on 0.0.0.0:8080 across 64 thread(s) -info: nilo also listening on https://0.0.0.0:8081 +2026-10-11T14:28:32.173Z info nilo: loaded 20 static file(s) (1758039 bytes held, 486436 of them precompressed files) from "/data/static" onto "/static" +2026-10-11T14:28:32.214Z info nilo listening on 0.0.0.0:8080 across 64 thread(s) +2026-10-11T14:28:32.214Z info nilo also listening on 0.0.0.0:8082 +2026-10-11T14:28:32.214Z info nilo also listening on https://0.0.0.0:8081 +2026-10-11T14:28:32.214Z info nilo also listening on https://0.0.0.0:8443 diff --git a/site/static/logs/latency-500k-8cpu/1024/nilo.log b/site/static/logs/latency-500k-8cpu/1024/nilo.log index 7b8b6db3a..ee2037a69 100644 --- a/site/static/logs/latency-500k-8cpu/1024/nilo.log +++ b/site/static/logs/latency-500k-8cpu/1024/nilo.log @@ -1,2 +1,5 @@ -info: nilo listening on 0.0.0.0:8080 across 8 thread(s) -info: nilo also listening on https://0.0.0.0:8081 +2026-10-11T14:30:53.071Z info nilo: loaded 20 static file(s) (1758039 bytes held, 486436 of them precompressed files) from "/data/static" onto "/static" +2026-10-11T14:30:53.074Z info nilo listening on 0.0.0.0:8080 across 8 thread(s) +2026-10-11T14:30:53.074Z info nilo also listening on 0.0.0.0:8082 +2026-10-11T14:30:53.074Z info nilo also listening on https://0.0.0.0:8081 +2026-10-11T14:30:53.074Z info nilo also listening on https://0.0.0.0:8443 diff --git a/site/static/logs/limited-conn/4096/nilo.log b/site/static/logs/limited-conn/4096/nilo.log index 2ca69ee8c..e19267dfe 100644 --- a/site/static/logs/limited-conn/4096/nilo.log +++ b/site/static/logs/limited-conn/4096/nilo.log @@ -1,2 +1,5 @@ -info: nilo listening on 0.0.0.0:8080 across 64 thread(s) -info: nilo also listening on https://0.0.0.0:8081 +2026-10-11T14:17:40.012Z info nilo: loaded 20 static file(s) (1758039 bytes held, 486436 of them precompressed files) from "/data/static" onto "/static" +2026-10-11T14:17:40.054Z info nilo listening on 0.0.0.0:8080 across 64 thread(s) +2026-10-11T14:17:40.055Z info nilo also listening on 0.0.0.0:8082 +2026-10-11T14:17:40.055Z info nilo also listening on https://0.0.0.0:8081 +2026-10-11T14:17:40.055Z info nilo also listening on https://0.0.0.0:8443 diff --git a/site/static/logs/pipelined/4096/nilo.log b/site/static/logs/pipelined/4096/nilo.log index 2ca69ee8c..27142360c 100644 --- a/site/static/logs/pipelined/4096/nilo.log +++ b/site/static/logs/pipelined/4096/nilo.log @@ -1,2 +1,5 @@ -info: nilo listening on 0.0.0.0:8080 across 64 thread(s) -info: nilo also listening on https://0.0.0.0:8081 +2026-10-11T14:17:16.414Z info nilo: loaded 20 static file(s) (1758039 bytes held, 486436 of them precompressed files) from "/data/static" onto "/static" +2026-10-11T14:17:16.458Z info nilo listening on 0.0.0.0:8080 across 64 thread(s) +2026-10-11T14:17:16.458Z info nilo also listening on 0.0.0.0:8082 +2026-10-11T14:17:16.458Z info nilo also listening on https://0.0.0.0:8081 +2026-10-11T14:17:16.458Z info nilo also listening on https://0.0.0.0:8443 diff --git a/site/static/logs/static-h2/1024/nilo.log b/site/static/logs/static-h2/1024/nilo.log new file mode 100644 index 000000000..6cbff7ae4 --- /dev/null +++ b/site/static/logs/static-h2/1024/nilo.log @@ -0,0 +1,5 @@ +2026-10-11T14:21:29.479Z info nilo: loaded 20 static file(s) (1758039 bytes held, 486436 of them precompressed files) from "/data/static" onto "/static" +2026-10-11T14:21:29.531Z info nilo listening on 0.0.0.0:8080 across 64 thread(s) +2026-10-11T14:21:29.531Z info nilo also listening on 0.0.0.0:8082 +2026-10-11T14:21:29.531Z info nilo also listening on https://0.0.0.0:8081 +2026-10-11T14:21:29.531Z info nilo also listening on https://0.0.0.0:8443 diff --git a/site/static/logs/static-h2/256/nilo.log b/site/static/logs/static-h2/256/nilo.log new file mode 100644 index 000000000..8d5eb8ae1 --- /dev/null +++ b/site/static/logs/static-h2/256/nilo.log @@ -0,0 +1,5 @@ +2026-10-11T14:21:06.147Z info nilo: loaded 20 static file(s) (1758039 bytes held, 486436 of them precompressed files) from "/data/static" onto "/static" +2026-10-11T14:21:06.197Z info nilo listening on 0.0.0.0:8080 across 64 thread(s) +2026-10-11T14:21:06.197Z info nilo also listening on 0.0.0.0:8082 +2026-10-11T14:21:06.197Z info nilo also listening on https://0.0.0.0:8081 +2026-10-11T14:21:06.197Z info nilo also listening on https://0.0.0.0:8443 diff --git a/site/static/logs/unary-grpc-tls/1024/nilo.log b/site/static/logs/unary-grpc-tls/1024/nilo.log new file mode 100644 index 000000000..77d2ccfcb --- /dev/null +++ b/site/static/logs/unary-grpc-tls/1024/nilo.log @@ -0,0 +1,5 @@ +2026-10-11T14:24:58.963Z info nilo: loaded 20 static file(s) (1758039 bytes held, 486436 of them precompressed files) from "/data/static" onto "/static" +2026-10-11T14:24:59.004Z info nilo listening on 0.0.0.0:8080 across 64 thread(s) +2026-10-11T14:24:59.004Z info nilo also listening on 0.0.0.0:8082 +2026-10-11T14:24:59.004Z info nilo also listening on https://0.0.0.0:8081 +2026-10-11T14:24:59.004Z info nilo also listening on https://0.0.0.0:8443 diff --git a/site/static/logs/unary-grpc-tls/256/nilo.log b/site/static/logs/unary-grpc-tls/256/nilo.log new file mode 100644 index 000000000..a22aca842 --- /dev/null +++ b/site/static/logs/unary-grpc-tls/256/nilo.log @@ -0,0 +1,5 @@ +2026-10-11T14:24:35.764Z info nilo: loaded 20 static file(s) (1758039 bytes held, 486436 of them precompressed files) from "/data/static" onto "/static" +2026-10-11T14:24:35.808Z info nilo listening on 0.0.0.0:8080 across 64 thread(s) +2026-10-11T14:24:35.808Z info nilo also listening on 0.0.0.0:8082 +2026-10-11T14:24:35.808Z info nilo also listening on https://0.0.0.0:8081 +2026-10-11T14:24:35.808Z info nilo also listening on https://0.0.0.0:8443 diff --git a/site/static/logs/unary-grpc/1024/nilo.log b/site/static/logs/unary-grpc/1024/nilo.log new file mode 100644 index 000000000..64b906baf --- /dev/null +++ b/site/static/logs/unary-grpc/1024/nilo.log @@ -0,0 +1,5 @@ +2026-10-11T14:24:12.398Z info nilo: loaded 20 static file(s) (1758039 bytes held, 486436 of them precompressed files) from "/data/static" onto "/static" +2026-10-11T14:24:12.443Z info nilo listening on 0.0.0.0:8080 across 64 thread(s) +2026-10-11T14:24:12.443Z info nilo also listening on 0.0.0.0:8082 +2026-10-11T14:24:12.443Z info nilo also listening on https://0.0.0.0:8081 +2026-10-11T14:24:12.443Z info nilo also listening on https://0.0.0.0:8443 diff --git a/site/static/logs/unary-grpc/256/nilo.log b/site/static/logs/unary-grpc/256/nilo.log new file mode 100644 index 000000000..61bf784ea --- /dev/null +++ b/site/static/logs/unary-grpc/256/nilo.log @@ -0,0 +1,5 @@ +2026-10-11T14:23:49.229Z info nilo: loaded 20 static file(s) (1758039 bytes held, 486436 of them precompressed files) from "/data/static" onto "/static" +2026-10-11T14:23:49.275Z info nilo listening on 0.0.0.0:8080 across 64 thread(s) +2026-10-11T14:23:49.275Z info nilo also listening on 0.0.0.0:8082 +2026-10-11T14:23:49.275Z info nilo also listening on https://0.0.0.0:8081 +2026-10-11T14:23:49.275Z info nilo also listening on https://0.0.0.0:8443