diff --git a/frameworks/vanilla-epoll/Dockerfile b/frameworks/vanilla-epoll/Dockerfile index 56d3cc9d7..11259ef82 100644 --- a/frameworks/vanilla-epoll/Dockerfile +++ b/frameworks/vanilla-epoll/Dockerfile @@ -6,40 +6,52 @@ RUN apt-get -qq update && \ cmake curl bzip2 python3 && \ rm -rf /var/lib/apt/lists/* -# Pinned, reproducible V at master commit 02015a7c (built from source). Moved off -# the 0.5.1 tag: the codegen regression that forced the pin (single-element array -# push 4-7x slower, vlang/v#27468) is fixed (vlang/v#27470), and the vanilla library -# now uses `ArrayFlags.managed` (the buf_view non-marking window) which only exists -# on post-0.5.1 V. `make` bootstraps via the matching vc; if a much later rebuild -# ever fails to bootstrap, pin vlang/vc to the commit cut for this V. -RUN git clone https://github.com/vlang/v /opt/v && \ - cd /opt/v && git checkout 02015a7ce111e4d0cfd5b5d78711ad0db7586936 && \ - make && ln -s /opt/v/v /usr/local/bin/v +# Pinned, reproducible V at master commit b99970bd (0.5.2, built from source). The +# removed `json` module is replaced by x.json2 in main.v (encode with +# escape_unicode, so the /json bodies stay byte-identical). +# +# The bootstrap is pinned too. A bare `make` clones vlang/vc and vlang/tccbin at +# their CURRENT heads, so a fixed V source gets built by whatever compiler vc +# holds that day: that is what broke every V entry in #1288 ("C function C.open +# was already declared with a different signature"), and vc head has since +# failed in other ways. vc 2cbaf6bc is vc's newest snapshot (generated from V +# 0c41fadb, 40 commits earlier; vc has none for b99970bd yet), so it is what +# `make` bootstraps this V with today; tccbin d6e7ac1b is the head of tccbin's +# thirdparty-linux-amd64 branch, and `local=1` makes `make` build with both +# instead of pulling. +# +# Each repo is fetched at its one pinned commit (depth 1) rather than cloned: +# a full clone of v, vc and tccbin is hundreds of MB and a slow or flaky link +# stalls it past the validator's timeout; this is ~30 MB. +RUN git init -q /opt/v && cd /opt/v && \ + git fetch -q --depth 1 https://github.com/vlang/v b99970bd438a7bdcdfbe38f74d9364db801d5439 && \ + git checkout -q FETCH_HEAD && \ + git init -q vc && \ + git -C vc fetch -q --depth 1 https://github.com/vlang/vc 2cbaf6bc2367937cd5f0b4ef923d1ef9aad613b3 && \ + git -C vc checkout -q FETCH_HEAD && \ + git init -q thirdparty/tcc && \ + git -C thirdparty/tcc fetch -q --depth 1 https://github.com/vlang/tccbin d6e7ac1b1bcc98aed734a6ecbfa8509f24606c74 && \ + git -C thirdparty/tcc checkout -q FETCH_HEAD && \ + make local=1 && ln -s /opt/v/v /usr/local/bin/v -# Install the vanilla HTTP server as the `vanilla` module (import vanilla.http_server), -# pinned to a specific commit: reproducible, and with NO per-build network call to -# detect changes. The previous approach `ADD`ed the GitHub API main-ref URL to cache-bust -# whenever main moved, but that hit api.github.com on every build and a transient 504 -# (or rate-limit) failed the whole build (MDA2AV/HttpArena#895). To pick up upstream -# library fixes, bump this commit. +# Install vanilla as the `vanilla` module (import vanilla.server, vanilla.core, ...), +# pinned to a specific commit: reproducible, with NO per-build network call to +# detect changes. The previous approach `ADD`ed the GitHub API main-ref URL to +# cache-bust whenever main moved, but that hit api.github.com on every build and a +# transient 504 (or rate-limit) failed the whole build (MDA2AV/HttpArena#895). To +# pick up upstream library fixes, bump this commit. # -# Pinned to vanilla main @be46940 — carries enghitalo/vanilla#101 (epoll async-runtime -# hardening, the twins found while building the io_uring async runtime #99: a `.done` -# resume now DRAINS requests pipelined behind a parked one that were already buffered; -# drain_pipelined deactivates a fully-drained queue inline BEFORE the serve that may -# re-park — the old trailing epilogue stranded such re-parks; and a watch registered by -# a handler whose park was rejected is torn down instead of leaking an active entry on -# a soon-reused client_fd). Also #96 (epoll TLS stateful make_state fix; inert for this -# entry's stateless TLS listener) and #94/#99 (io_uring-only). Previously @b189036 — the lib-wide alloc audit (#72 pg_async, #73 -# static_assets, #74 TLS buffer pooling), kTLS record offload for json-tls -# (enghitalo/vanilla#79; after the Mbed TLS handshake the kernel does TLS 1.3 record -# AES-128-GCM via setsockopt TLS_TX+TLS_RX, so the epoll worker's steady-state -# read/write are plain recv/send), PLUS static_assets `url_prefix` (#80) and -# core.queue_buf borrowed send (#81) — this entry serves /static/* through the -# audited static_assets module (precompressed .br/.gz negotiation + ETag/Vary, -# sendfile for the large siblings) instead of a hand-rolled identity-only map. -RUN git clone https://github.com/enghitalo/vanilla /root/.vmodules/vanilla && \ - git -C /root/.vmodules/vanilla checkout be46940b624363ed93991d3166f950143ee14c7b +# Pinned to vanilla main @091c014: top-level modules and one handler contract +# (core.Handler returning core.Step, watches through core.EventLoop), which main.v +# uses for both listeners. /static/* goes through the static_assets module on both: +# precompressed .br/.gz negotiation + ETag/Vary, snapshots that follow the disk +# (enghitalo/vanilla#180), and sendfile for bodies of 16 KiB or more, on :8080 and, +# over kTLS, on the :8081 TLS listener (enghitalo/vanilla#181; a userspace-TLS +# connection gets the bytes from RAM). Fetched at that one commit. +RUN git init -q /root/.vmodules/vanilla && \ + git -C /root/.vmodules/vanilla fetch -q --depth 1 https://github.com/enghitalo/vanilla \ + 091c014a0191afd7e740b84f5599b9b1fc1fd914 && \ + git -C /root/.vmodules/vanilla checkout -q FETCH_HEAD # Mbed TLS 4 for the json-tls profile. The vanilla `tls` module's C shim # (vanilla_tls.c, built with `-d vanilla_tls`) targets the Mbed TLS 4.x API @@ -49,11 +61,22 @@ RUN git clone https://github.com/enghitalo/vanilla /root/.vmodules/vanilla && \ # tls_mbedtls_d_vanilla_tls.c.v (-L/usr/local/lib -lmbedtls -lmbedx509 # -lmbedcrypto). 4.x also produces libtfpsacrypto (the TF-PSA-Crypto split), # linked transitively. Headers land in /usr/local/include for the build. +# +# mbedtls-rsa-sign-cache.patch (against 4.1.0): unpatched, every PSA RSA +# signature re-parses the key and regenerates the RSA blinding values from +# scratch, which was most of each TLS 1.3 handshake with the harness's +# RSA-2048 certificate (~11 ms of CPU). The patch keeps the signing key's +# parsed context in a per-thread cache, so blinding is updated by squaring +# as with any long-lived mbedtls_rsa_context; with -O3 -march=native a +# handshake costs ~8 ms. That is what 8gbit (512 fresh connections) and +# json-tls (4096) pay up front before the first request is answered. ARG MBEDTLS_VERSION=4.1.0 +COPY mbedtls-rsa-sign-cache.patch /tmp/ RUN curl -fsSL -o /tmp/mbedtls.tar.bz2 \ "https://github.com/Mbed-TLS/mbedtls/releases/download/mbedtls-${MBEDTLS_VERSION}/mbedtls-${MBEDTLS_VERSION}.tar.bz2" && \ tar -xf /tmp/mbedtls.tar.bz2 -C /tmp && \ cd "/tmp/mbedtls-${MBEDTLS_VERSION}" && \ + patch -p1 < /tmp/mbedtls-rsa-sign-cache.patch && \ # THREAD-SAFETY (load-bearing): vanilla runs N TLS worker threads, each driving # TLS 1.3 handshakes through Mbed TLS's PSA crypto, whose key store is a GLOBAL, # process-wide table. Without MBEDTLS_THREADING_C the concurrent handshakes race @@ -65,7 +88,7 @@ RUN curl -fsSL -o /tmp/mbedtls.tar.bz2 \ python3 tf-psa-crypto/scripts/config.py set MBEDTLS_THREADING_C && \ python3 tf-psa-crypto/scripts/config.py set MBEDTLS_THREADING_PTHREAD && \ cmake -S "/tmp/mbedtls-${MBEDTLS_VERSION}" -B /tmp/mbedtls-build \ - -DCMAKE_BUILD_TYPE=Release \ + -DCMAKE_BUILD_TYPE=Release -DCMAKE_C_FLAGS_RELEASE="-O3 -march=native -DNDEBUG" \ -DUSE_SHARED_MBEDTLS_LIBRARY=On -DUSE_STATIC_MBEDTLS_LIBRARY=Off \ -DENABLE_TESTING=Off -DENABLE_PROGRAMS=Off \ -DCMAKE_INSTALL_PREFIX=/usr/local && \ @@ -95,4 +118,8 @@ COPY --from=build /app/server /server # bind-mounts the cert/key at /certs and the server reads /certs/server.{crt,key} # (override via TLS_CERT/TLS_KEY); with no cert mounted it self-signs. EXPOSE 8080 8081 -CMD ["/server"] +# One worker per CPU the container may run on. vanilla defaults to nr_cpus, +# which reads the host's online CPUs (128 on the bench box) and ignores the +# cpuset, so a 64-CPU profile started 128 workers and latency-500k-8cpu would +# start 128 on 8. nproc honours the cpuset; an explicit VANILLA_WORKERS wins. +CMD ["/bin/sh", "-c", "VANILLA_WORKERS=${VANILLA_WORKERS:-$(nproc)} exec /server"] diff --git a/frameworks/vanilla-epoll/main.v b/frameworks/vanilla-epoll/main.v index d1e253734..9aeb38bf5 100644 --- a/frameworks/vanilla-epoll/main.v +++ b/frameworks/vanilla-epoll/main.v @@ -1,16 +1,16 @@ module main -import vanilla.http_server -import vanilla.http_server.http1_1.request_parser -import vanilla.http_server.core -import vanilla.http_server.tls -import vanilla.http_server.static_assets +import vanilla.server +import vanilla.http1_1.request_parser +import vanilla.core +import vanilla.tls +import vanilla.static_assets import vanilla.pg_async -import json +import x.json2 as json import os -import runtime import strings import sync +import time import compress.gzip struct Rating { @@ -70,7 +70,10 @@ mut: crud []CrudSlot crud_mu &sync.RwMutex = unsafe { nil } gz map[u64][]u8 // json-comp: (count<<32)|m -> gzipped response bytes - gz_mu &sync.RwMutex = unsafe { nil } + // production-stack /api/me: user-id-indexed slab, same shape as `crud` + users []CrudSlot + users_mu &sync.RwMutex = unsafe { nil } + gz_mu &sync.RwMutex = unsafe { nil } } // CrudSlot is one entry of the id-indexed crud cache slab. `buf` is the rendered @@ -80,8 +83,9 @@ mut: // the next MISS to reuse (no time-based expiry — see the SharedRO.crud note). struct CrudSlot { mut: - buf []u8 - valid bool + buf []u8 + valid bool + expires u64 // time.sys_mono_now() deadline; a HIT needs now < expires } // crud GET/PUT ids are `{RAND:1:50000}`; index the slab directly (1..50000). Index 0 @@ -92,7 +96,21 @@ const crud_cache_slots = 50001 // so a slot's buffer, allocated once on first MISS, never reallocates. const crud_cache_bufcap = 512 -// WorkerCtx is the per-worker state handed to every handler call as ac.state +// Cache-aside TTLs for production-stack (the spec caps items at 1 s, users at +// 30 s). The same slab serves /crud/items, which keeps the 1 s item TTL. +const item_ttl_ns = u64(1_000_000_000) +const user_ttl_ns = u64(30_000_000_000) + +// /api/me ids index the users slab directly; the seed's ids are small, and an id +// past the slab is served uncached rather than growing it. +const user_cache_slots = 1024 + +// static_revalidate_ms: how often each static representation is re-checked against +// its file (one stat(2) per window, by the first request after it opens); 0 checks +// on every request. +const static_revalidate_ms = 100 + +// WorkerCtx is the per-worker state handed to every handler call as worker_state // (the make_state contract). Each worker owns its own async Postgres pool (no // lock); the caches live in the shared `ro` (mutex-guarded) so X-Cache hits // survive SO_REUSEPORT routing the two probe requests to different workers. @@ -119,7 +137,7 @@ mut: params_buf []?[]u8 // Reused Stash free-list: park() borrows a Stash here instead of heap-allocating one // per request; on_db_ready returns it on the terminal .done path only (NOT on the - // not-ready re-arm, where it stays live as the watch udata — incl. a FIX 3 dead + // not-ready re-arm, where it stays live as the watch payload — incl. a FIX 3 dead // tombstone that keeps it referenced until its orphaned reply drains). stash_pool []&Stash // Reused /fortunes row buffer: messages are BORROWED views into the Result frames @@ -131,6 +149,11 @@ mut: // was the /baseline11 chunked-POST leak (~6 GiB at 3.8M req/s in the arena // baseline mix). dechunk_buf []u8 + // Idle one-shot timerfds for /delay: start_delay pops one instead of calling + // timerfd_create, on_delay_elapsed pushes it back instead of closing it. A + // recycled fd is still registered with the worker's poller, so re-arming it + // costs a timerfd_settime and a re-watch rather than create + add + close. + timer_fds []int } // Stash is the per-request state that must survive across the park (the request @@ -150,6 +173,8 @@ const k_crud_get = u8(3) const k_crud_list = u8(4) const k_crud_create = u8(5) const k_crud_update = u8(6) +const k_api_update = u8(7) +const k_api_me = u8(8) // ── zero-alloc write helpers (push_many, never single-element `<<`) ────────── @@ -303,8 +328,8 @@ const service_unavailable = 'HTTP/1.1 503 Service Unavailable\r\nServer: vanilla // ── async handler ──────────────────────────────────────────────────────────── -fn handle(req_buffer []u8, mut out []u8, mut ac core.AsyncCtx) core.AsyncStep { - mut w := unsafe { &WorkerCtx(ac.state) } +fn handle(req_buffer []u8, mut out []u8, _ int, worker_state voidptr, mut event_loop core.EventLoop) core.Step { + mut w := unsafe { &WorkerCtx(worker_state) } // Skip-decode fast path: the fixed /pipeline plaintext (highest-RPS test) blits // its response before ANY parsing. The request is already framed by the caller, // so decode_into/parse_http1_request_line add nothing here (~17% of the request). @@ -331,6 +356,11 @@ fn handle(req_buffer []u8, mut out []u8, mut ac core.AsyncCtx) core.AsyncStep { } qpos := target.index_u8(`?`) route := if qpos < 0 { target } else { unsafe { tos(target.str, qpos) } } + // RFC 9112 §9.6: a request carrying the `close` connection option gets its + // final response and then the connection closes (.close flushes first). + // Only the synchronous routes below answer with `done`; the DB routes finish + // in their continuation. + done := if has_close_option(req) { core.Step.close } else { core.Step.done } if route == '/baseline11' { mut sum := qint(req, qk_a) + qint(req, qk_b) @@ -338,27 +368,37 @@ fn handle(req_buffer []u8, mut out []u8, mut ac core.AsyncCtx) core.AsyncStep { sum += w.body_int(req) } w.emit_int(mut out, 'text/plain', sum) - return .done + return done + } else if route == '/baseline2' { + // the gateway profiles' query-sum endpoint (GET only), behind the edge proxy + w.emit_int(mut out, 'text/plain', qint(req, qk_a) + qint(req, qk_b)) + return done + } else if route.starts_with('/api/items/') { + // production-stack: the edge verified the JWT; GET is cache-aside, POST writes + id := int(parse_u_at(route, 11)) + if method == 'POST' { + return w.start_api_update(mut out, mut event_loop, id, req) + } + return w.start_crud_get(mut out, mut event_loop, id) + } else if route == '/api/me' { + return w.start_api_me(mut out, mut event_loop, req) + } else if route == '/public/baseline' { + w.emit_int(mut out, 'text/plain', qint(req, qk_a) + qint(req, qk_b)) + return done + } else if route.starts_with('/public/json/') { + w.serve_json(mut out, req, parse_u_at(route, 13)) + return done } else if route == '/echo' { w.echo(mut out, req) - return .done + return done } else if route.starts_with('/json/') { - count := clamp_count(parse_u_at(route, 6), w.ro.dataset.len) - mut m := qint(req, qk_m) - if m == 0 { - m = 1 - } - if accepts_gzip(req) { - w.write_json_gzip(mut out, count, m) - } else { - w.write_json_response(mut out, count, m) - } - return .done + w.serve_json(mut out, req, parse_u_at(route, 6)) + return done } else if route == '/async-db' { - return w.start_async_db(mut out, mut ac, qint(req, qk_min), qint(req, qk_max), qint(req, + return w.start_async_db(mut out, mut event_loop, qint(req, qk_min), qint(req, qk_max), qint(req, qk_limit)) } else if route == '/fortunes' { - return w.start_fortunes(mut out, mut ac) + return w.start_fortunes(mut out, mut event_loop) } else if route.starts_with('/static/') { // Canonical static serving via the lib's static_assets module: negotiates the // precompressed .br/.gz sibling per Accept-Encoding (the arena sends @@ -367,29 +407,40 @@ fn handle(req_buffer []u8, mut out []u8, mut ac core.AsyncCtx) core.AsyncStep { // ONE audited implementation instead of a second hand-rolled identity-only // path that ignored Accept-Encoding. Mounted at /static/; emits via the same // core.queue_file sendfile handoff the worker already drains. - w.ro.asv.respond_into(req_buffer, mut out) or { wb(mut out, not_found) } - return .done + w.ro.asv.respond_req_into(&req, mut out) + return done } else if route == '/crud/items' { if method == 'POST' { - return w.start_crud_create(mut out, mut ac, req) + return w.start_crud_create(mut out, mut event_loop, req) } - return w.start_crud_list(mut out, mut ac, qstr_slice(req, qk_category), qint(req, qk_page), + return w.start_crud_list(mut out, mut event_loop, qstr_slice(req, qk_category), qint(req, qk_page), qint(req, qk_limit)) } else if route.starts_with('/crud/items/') { id := int(parse_u_at(route, 12)) if method == 'PUT' { - return w.start_crud_update(mut out, mut ac, id, req) + return w.start_crud_update(mut out, mut event_loop, id, req) + } + return w.start_crud_get(mut out, mut event_loop, id) + } else if route.starts_with('/delay/') { + ms := parse_delay_ms(route) + if ms < 0 { + wb(mut out, not_found) + return done } - return w.start_crud_get(mut out, mut ac, id) + if ms == 0 { + w.emit_int(mut out, 'text/plain', 0) + return done + } + return w.start_delay(mut out, mut event_loop, ms) } wb(mut out, not_found) - return .done + return done } // park submits a query and parks the request on its connection, stashing the // render kind (+ id/page for the routes that need them) for the continuation. // On a pool/flush failure it answers synchronously with `fallback`. -fn (mut w WorkerCtx) park(mut out []u8, mut ac core.AsyncCtx, query_text string, params []?[]u8, kind u8, id int, page i64, fallback []u8) core.AsyncStep { +fn (mut w WorkerCtx) park(mut out []u8, mut event_loop core.EventLoop, query_text string, params []?[]u8, kind u8, id int, page i64, fallback []u8) core.Step { // Pick the least-loaded connection (shortest pipeline). Cross-request // pipelining: a connection multiplexes up to max_inflight queries, so we shed // only when every connection is at the cap — not when a connection is merely @@ -431,18 +482,19 @@ fn (mut w WorkerCtx) park(mut out []u8, mut ac core.AsyncCtx, query_text string, // One watch per parked request on the connection's fd. When several requests // share a connection the reactor auto-promotes the fd to a FIFO queue and fans // each reply out in submission order (queue[k] ↔ the connection's inflight[k]). - // watch_persistent: the fd is a POOLED connection — if this client disconnects + // watch_fd_persistent: the fd is a POOLED connection — if this client disconnects // mid-query the runtime must drain the orphaned reply and keep the connection // open for reuse, never close it (a close would force a reconnect + re-auth). - ac.watch_persistent(w.pool.fd(idx), .readable, on_db_ready, voidptr(st)) + event_loop.watch_fd_persistent(w.pool.fd(idx), .readable, on_db_ready, voidptr(st)) return .suspend } // on_db_ready resumes a parked request when its PG socket is readable: pump the -// result, render by kind, release the connection. -fn on_db_ready(mut out []u8, mut ac core.AsyncCtx) core.AsyncStep { - mut w := unsafe { &WorkerCtx(ac.state) } - st := unsafe { &Stash(ac.udata) } +// result, render by kind, release the connection. The ready fd and its error flag +// go unused: st.conn_idx already names the connection. +fn on_db_ready(mut out []u8, _ int, _ bool, watch_payload voidptr, worker_state voidptr, mut event_loop core.EventLoop) core.Step { + mut w := unsafe { &WorkerCtx(worker_state) } + st := unsafe { &Stash(watch_payload) } mut c := w.pool.conn(st.conn_idx) // async_on_readable pops THIS request's reply: the reactor runs the connection's // parked requests front-first and replies arrive in submit order, so the FIFO @@ -455,11 +507,12 @@ fn on_db_ready(mut out []u8, mut ac core.AsyncCtx) core.AsyncStep { } if !poll.ready { // Re-arm persistent: the single-watch path clears the slot before running this - // continuation, so the re-arm is a fresh entry — watch_persistent re-stamps the - // pool-owned flag that a plain watch would drop. (more bytes to come) - // NOTE: do NOT recycle st here — it stays live as the watch udata (incl. a FIX 3 + // continuation, so the re-arm is a fresh entry — watch_fd_persistent re-stamps the + // pool-owned flag that a plain watch_fd would drop. (more bytes to come) + // NOTE: do NOT recycle st here — it stays live as the watch payload (incl. a FIX 3 // dead tombstone) until the reply completes on a later edge. - ac.watch_persistent(w.pool.fd(st.conn_idx), .readable, on_db_ready, ac.udata) + event_loop.watch_fd_persistent(w.pool.fd(st.conn_idx), .readable, on_db_ready, + watch_payload) return .suspend } res := poll.result @@ -470,6 +523,8 @@ fn on_db_ready(mut out []u8, mut ac core.AsyncCtx) core.AsyncStep { k_crud_list { w.render_crud_list(mut out, res, st.page) } k_crud_create { wb(mut out, created) } k_crud_update { w.render_crud_update(mut out, st.id) } + k_api_update { w.render_api_update(mut out, st.id) } + k_api_me { w.render_api_me(mut out, res, st.id) } else { wb(mut out, not_found) } } // No release: a pipelined connection is not held exclusively. Its in-flight @@ -481,7 +536,7 @@ fn on_db_ready(mut out []u8, mut ac core.AsyncCtx) core.AsyncStep { // return_stash recycles a finished request's Stash onto the per-worker free-list. Call // ONLY on a terminal .done path — never on the .suspend re-arm, where st stays live as -// the watch udata. Bounded so a burst doesn't grow the list without limit. +// the watch payload. Bounded so a burst doesn't grow the list without limit. @[inline] fn (mut w WorkerCtx) return_stash(st &Stash) { if w.stash_pool.len < 64 { @@ -489,6 +544,208 @@ fn (mut w WorkerCtx) return_stash(st &Stash) { } } +// ── /delay/{ms} (async profile) ───────────────────────────────────────────── + +#include + +fn C.timerfd_create(clockid int, flags int) int +fn C.timerfd_settime(fd int, flags int, new_value voidptr, old_value voidptr) int + +// timer_pool_max bounds a worker's free-list of idle timerfds. The profile holds +// ~32000/workers requests in flight per worker; past the bound a finished timer +// is closed instead of kept. +const timer_pool_max = 4096 + +// parse_delay_ms reads {ms} from `/delay/{ms}`: 1-9 decimal digits and nothing +// after them. Anything else is -1 (404). +@[direct_array_access] +fn parse_delay_ms(route string) i64 { + start := '/delay/'.len + if route.len == start || route.len - start > 9 { + return -1 + } + mut n := i64(0) + for i := start; i < route.len; i++ { + c := route[i] + if c < `0` || c > `9` { + return -1 + } + n = n * 10 + i64(c - `0`) + } + return n +} + +// start_delay parks the request on a one-shot timerfd armed for `ms`; the worker +// keeps serving its other connections and on_delay_elapsed answers when the +// timer fires. The delay rides along as the watch payload. +fn (mut w WorkerCtx) start_delay(mut out []u8, mut event_loop core.EventLoop, ms i64) core.Step { + mut tfd := -1 + if w.timer_fds.len > 0 { + tfd = w.timer_fds.pop() + } else { + tfd = C.timerfd_create(C.CLOCK_MONOTONIC, C.TFD_NONBLOCK | C.TFD_CLOEXEC) + if tfd < 0 { + wb(mut out, service_unavailable) + return .done + } + } + // struct itimerspec: it_interval {sec, nsec} = 0 (one-shot), it_value {sec, nsec} + mut spec := [4]i64{} + spec[2] = ms / 1000 + spec[3] = (ms % 1000) * 1_000_000 + if C.timerfd_settime(tfd, 0, unsafe { voidptr(&spec[0]) }, unsafe { nil }) != 0 { + C.close(tfd) + wb(mut out, service_unavailable) + return .done + } + event_loop.watch_fd(tfd, .readable, on_delay_elapsed, voidptr(usize(ms))) + return .suspend +} + +// on_delay_elapsed answers a parked /delay request. It only answers once the +// timerfd reports an expiration: a wake without one (a stale io_uring poll +// completion for a closed fd whose number was reused, say) re-arms and keeps +// waiting, so no response can leave before its delay has elapsed. +fn on_delay_elapsed(mut out []u8, ready_fd int, ready_fd_error bool, watch_payload voidptr, worker_state voidptr, mut event_loop core.EventLoop) core.Step { + mut w := unsafe { &WorkerCtx(worker_state) } + tfd := ready_fd + mut expirations := u64(0) + if C.read(tfd, &expirations, 8) != 8 { + if ready_fd_error { + C.close(tfd) + wb(mut out, service_unavailable) + return .done + } + event_loop.watch_fd(tfd, .readable, on_delay_elapsed, watch_payload) + return .suspend + } + if w.timer_fds.len < timer_pool_max { + w.timer_fds << tfd + } else { + C.close(tfd) + } + w.emit_int(mut out, 'text/plain', i64(usize(watch_payload))) + return .done +} + +// serve_json answers /json/{count} (and production-stack's /public/json/{count}): +// gzip from the lazy per-(count, m) cache when the client accepts it. +fn (mut w WorkerCtx) serve_json(mut out []u8, req request_parser.HttpRequest, n i64) { + count := clamp_count(n, w.ro.dataset.len) + mut m := qint(req, qk_m) + if m == 0 { + m = 1 + } + if accepts_gzip(req) { + w.write_json_gzip(mut out, count, m) + } else { + w.write_json_response(mut out, count, m) + } +} + +// ── production-stack /api (behind the edge's JWT auth_request) ────────────── + +const no_content = 'HTTP/1.1 204 No Content\r\nServer: vanilla\r\nConnection: keep-alive\r\n\r\n'.bytes() + +const unauthorized = 'HTTP/1.1 401 Unauthorized\r\nServer: vanilla\r\nContent-Length: 0\r\nConnection: keep-alive\r\n\r\n'.bytes() + +// start_api_update is POST /api/items/{id}: {"name","price","quantity"} parsed in +// place (borrowed views, no allocation), UPDATE, then render_api_update drops the +// cached item and answers 204. +fn (mut w WorkerCtx) start_api_update(mut out []u8, mut event_loop core.EventLoop, id int, req request_parser.HttpRequest) core.Step { + body := unsafe { req.buffer[req.body.start..req.body.start + req.body.len] } + name := json_string_field_borrowed(body, '"name"') or { + wb(mut out, bad_request) + return .done + } + price := json_i64_field(body, '"price"') or { + wb(mut out, bad_request) + return .done + } + quantity := json_i64_field(body, '"quantity"') or { + wb(mut out, bad_request) + return .done + } + w.reset_params() + w.push_int(i64(id)) + w.push_bytes(name) + w.push_int(price) + w.push_int(quantity) + return w.park(mut out, mut event_loop, 'UPDATE items SET name = \$2, price = \$3, quantity = \$4 WHERE id = \$1', + w.params_buf, k_api_update, id, 0, service_unavailable) +} + +fn (mut w WorkerCtx) render_api_update(mut out []u8, id int) { + // invalidate after the write, so the next GET re-reads the updated row + if id >= 1 && id < crud_cache_slots { + w.ro.crud_mu.@lock() + w.ro.crud[id].valid = false + w.ro.crud_mu.unlock() + } + wb(mut out, no_content) +} + +// start_api_me is GET /api/me: cache-aside on the user named by the edge's +// X-User-Id (set from the verified JWT), 30 s TTL. +fn (mut w WorkerCtx) start_api_me(mut out []u8, mut event_loop core.EventLoop, req request_parser.HttpRequest) core.Step { + uid := req.get_header_value_slice('X-User-Id') or { + wb(mut out, unauthorized) + return .done + } + id := int(parse_u_at(unsafe { tos(&req.buffer[uid.start], uid.len) }, 0)) + if id >= 1 && id < user_cache_slots { + now := time.sys_mono_now() + mut hit := false + w.ro.users_mu.@rlock() + s := w.ro.users[id] + if s.valid && s.buf.len > 0 && now < s.expires { + unsafe { w.scratch.len = 0 } + w.scratch << s.buf + hit = true + } + w.ro.users_mu.runlock() + if hit { + emit_xcache(mut out, 'application/json', w.scratch, 'HIT') + return .done + } + } + w.reset_params() + w.push_int(i64(id)) + return w.park(mut out, mut event_loop, 'SELECT id, name, email, plan FROM users WHERE id = \$1', + w.params_buf, k_api_me, id, 0, service_unavailable) +} + +fn (mut w WorkerCtx) render_api_me(mut out []u8, res pg_async.Result, id int) { + mut rows := res.rows() + row := rows.next() or { + wb(mut out, not_found) + return + } + unsafe { w.scratch.len = 0 } + ws(mut w.scratch, '{"id":') + wi(mut w.scratch, i64(row.int4(0) or { 0 })) + ws(mut w.scratch, ',"name":"') + ws_json_str(mut w.scratch, row.text(1) or { ''.bytes() }) + ws(mut w.scratch, '","email":"') + ws_json_str(mut w.scratch, row.text(2) or { ''.bytes() }) + ws(mut w.scratch, '","plan":"') + ws_json_str(mut w.scratch, row.text(3) or { ''.bytes() }) + ws(mut w.scratch, '"}') + if id >= 1 && id < user_cache_slots { + w.ro.users_mu.@lock() + mut slot := &w.ro.users[id] + if slot.buf.cap == 0 { + slot.buf = []u8{cap: crud_cache_bufcap} + } + unsafe { slot.buf.len = 0 } + slot.buf << w.scratch + slot.valid = true + slot.expires = time.sys_mono_now() + user_ttl_ns + w.ro.users_mu.unlock() + } + emit_xcache(mut out, 'application/json', w.scratch, 'MISS') +} + fn (w &WorkerCtx) render_error(mut out []u8, kind u8) { match kind { k_async_db { @@ -504,6 +761,9 @@ fn (w &WorkerCtx) render_error(mut out []u8, kind u8) { k_crud_get { wb(mut out, not_found) } + k_api_update, k_api_me { + wb(mut out, service_unavailable) + } else { wb(mut out, bad_request) } @@ -549,7 +809,7 @@ const fortunes_fallback = '
Fortunes') @@ -650,17 +910,33 @@ fn (mut w WorkerCtx) render_fortunes(mut out []u8, res pg_async.Result) { emit(mut out, 'text/html; charset=utf-8', w.scratch) } -// cmp_fortune_message orders fortunes by message, lexicographically by bytes — V has no -// `<` on []u8, so the sort needs an explicit comparator (returns <0 / 0 / >0). -fn cmp_fortune_message(a &Fortune, b &Fortune) int { +fn C.qsort(base voidptr, nmemb usize, size usize, compar voidptr) + +// sort_fortunes orders the ~200 rows by message with libc qsort. sort_with_compare is a +// merge sort whose scratch copy comes from V's malloc, which on a GC build is the +// collector's allocator (and under -gc none a V allocation that must be freed by +// hand); qsort's scratch, when it needs one, comes from libc malloc and is freed +// inside the call, so the per-request sort never touches the GC heap. +fn sort_fortunes(mut a []Fortune) { + C.qsort(a.data, usize(a.len), sizeof(Fortune), voidptr(cmp_fortune)) +} + +fn cmp_fortune(a &Fortune, b &Fortune) int { + return cmp_message(a.message, b.message) +} + +// cmp_message orders messages lexicographically by bytes — V has no `<` on []u8 +// (returns <0 / 0 / >0). +@[direct_array_access] +fn cmp_message(a []u8, b []u8) int { mut i := 0 - for i < a.message.len && i < b.message.len { - if a.message[i] != b.message[i] { - return int(a.message[i]) - int(b.message[i]) + for i < a.len && i < b.len { + if a[i] != b[i] { + return int(a[i]) - int(b[i]) } i++ } - return a.message.len - b.message.len + return a.len - b.len } // ── /crud ──────────────────────────────────────────────────────────────────── @@ -669,7 +945,7 @@ fn cmp_fortune_message(a &Fortune, b &Fortune) int { // the total come back together — one park instead of two queries. const crud_list_sql = 'SELECT id, name, category, price, quantity, active, tags, rating_score, rating_count, count(*) OVER() FROM items WHERE category = \$1 ORDER BY id LIMIT \$2 OFFSET \$3' -fn (mut w WorkerCtx) start_crud_list(mut out []u8, mut ac core.AsyncCtx, category []u8, page i64, limit i64) core.AsyncStep { +fn (mut w WorkerCtx) start_crud_list(mut out []u8, mut event_loop core.EventLoop, category []u8, page i64, limit i64) core.Step { mut p := page if p < 1 { p = 1 @@ -686,7 +962,7 @@ fn (mut w WorkerCtx) start_crud_list(mut out []u8, mut ac core.AsyncCtx, categor w.push_bytes(category) // borrowed view into the request buffer (qstr_slice) w.push_int(lim) w.push_int(offset) - return w.park(mut out, mut ac, crud_list_sql, w.params_buf, k_crud_list, 0, p, crud_list_fallback) + return w.park(mut out, mut event_loop, crud_list_sql, w.params_buf, k_crud_list, 0, p, crud_list_fallback) } fn (mut w WorkerCtx) render_crud_list(mut out []u8, res pg_async.Result, page i64) { @@ -712,16 +988,17 @@ fn (mut w WorkerCtx) render_crud_list(mut out []u8, res pg_async.Result, page i6 emit(mut out, 'application/json', w.scratch) } -fn (mut w WorkerCtx) start_crud_get(mut out []u8, mut ac core.AsyncCtx, id int) core.AsyncStep { +fn (mut w WorkerCtx) start_crud_get(mut out []u8, mut event_loop core.EventLoop, id int) core.Step { // Cache-aside lookup against the id-indexed slab. Snapshot the cached body into // the per-worker scratch UNDER the read-lock, then build the response unlocked: // the slot buffer is reused in place, so a bare ref must not outlive the lock (a // concurrent MISS-refill would mutate it). The read-lock hold is one memcpy. mut hit := false if id >= 1 && id < crud_cache_slots { + now := time.sys_mono_now() w.ro.crud_mu.@rlock() s := w.ro.crud[id] - if s.valid && s.buf.len > 0 { + if s.valid && s.buf.len > 0 && now < s.expires { unsafe { w.scratch.len = 0 } w.scratch << s.buf hit = true @@ -735,7 +1012,7 @@ fn (mut w WorkerCtx) start_crud_get(mut out []u8, mut ac core.AsyncCtx, id int) } w.reset_params() w.push_int(i64(id)) - return w.park(mut out, mut ac, + return w.park(mut out, mut event_loop, 'SELECT id, name, category, price, quantity, active, tags, rating_score, rating_count FROM items WHERE id = \$1', w.params_buf, k_crud_get, id, 0, service_unavailable) } @@ -766,12 +1043,13 @@ fn (mut w WorkerCtx) render_crud_get(mut out []u8, res pg_async.Result, id int) unsafe { slot.buf.len = 0 } slot.buf << w.scratch slot.valid = true + slot.expires = time.sys_mono_now() + item_ttl_ns w.ro.crud_mu.unlock() } emit_xcache(mut out, 'application/json', w.scratch, 'MISS') } -fn (mut w WorkerCtx) start_crud_create(mut out []u8, mut ac core.AsyncCtx, req request_parser.HttpRequest) core.AsyncStep { +fn (mut w WorkerCtx) start_crud_create(mut out []u8, mut event_loop core.EventLoop, req request_parser.HttpRequest) core.Step { body := unsafe { req.buffer[req.body.start..req.body.start + req.body.len] } if c := parse_crud_body_fast(body, true) { w.reset_params() @@ -780,12 +1058,12 @@ fn (mut w WorkerCtx) start_crud_create(mut out []u8, mut ac core.AsyncCtx, req r w.push_bytes(c.category) w.push_int(c.price) w.push_int(c.quantity) - return w.park(mut out, mut ac, + return w.park(mut out, mut event_loop, "INSERT INTO items (id, name, category, price, quantity, active, tags, rating_score, rating_count) VALUES (\$1, \$2, \$3, \$4, \$5, true, '[]', 0, 0) ON CONFLICT (id) DO UPDATE SET name = EXCLUDED.name, category = EXCLUDED.category, price = EXCLUDED.price, quantity = EXCLUDED.quantity", w.params_buf, k_crud_create, 0, 0, service_unavailable) } raw := unsafe { tos(&req.buffer[req.body.start], req.body.len) } - c := json.decode(CrudCreate, raw) or { + c := json.decode[CrudCreate](raw) or { wb(mut out, bad_request) return .done } @@ -795,12 +1073,12 @@ fn (mut w WorkerCtx) start_crud_create(mut out []u8, mut ac core.AsyncCtx, req r w.push_bytes(unsafe { c.category.str.vbytes(c.category.len) }) w.push_int(i64(c.price)) w.push_int(i64(c.quantity)) - return w.park(mut out, mut ac, + return w.park(mut out, mut event_loop, "INSERT INTO items (id, name, category, price, quantity, active, tags, rating_score, rating_count) VALUES (\$1, \$2, \$3, \$4, \$5, true, '[]', 0, 0) ON CONFLICT (id) DO UPDATE SET name = EXCLUDED.name, category = EXCLUDED.category, price = EXCLUDED.price, quantity = EXCLUDED.quantity", w.params_buf, k_crud_create, 0, 0, service_unavailable) } -fn (mut w WorkerCtx) start_crud_update(mut out []u8, mut ac core.AsyncCtx, id int, req request_parser.HttpRequest) core.AsyncStep { +fn (mut w WorkerCtx) start_crud_update(mut out []u8, mut event_loop core.EventLoop, id int, req request_parser.HttpRequest) core.Step { body := unsafe { req.buffer[req.body.start..req.body.start + req.body.len] } if c := parse_crud_body_fast(body, false) { w.reset_params() @@ -809,12 +1087,12 @@ fn (mut w WorkerCtx) start_crud_update(mut out []u8, mut ac core.AsyncCtx, id in w.push_bytes(c.category) w.push_int(c.price) w.push_int(c.quantity) - return w.park(mut out, mut ac, + return w.park(mut out, mut event_loop, 'UPDATE items SET name = \$2, category = \$3, price = \$4, quantity = \$5 WHERE id = \$1', w.params_buf, k_crud_update, id, 0, service_unavailable) } raw := unsafe { tos(&req.buffer[req.body.start], req.body.len) } - c := json.decode(CrudCreate, raw) or { + c := json.decode[CrudCreate](raw) or { wb(mut out, bad_request) return .done } @@ -824,7 +1102,7 @@ fn (mut w WorkerCtx) start_crud_update(mut out []u8, mut ac core.AsyncCtx, id in w.push_bytes(unsafe { c.category.str.vbytes(c.category.len) }) w.push_int(i64(c.price)) w.push_int(i64(c.quantity)) - return w.park(mut out, mut ac, + return w.park(mut out, mut event_loop, 'UPDATE items SET name = \$2, category = \$3, price = \$4, quantity = \$5 WHERE id = \$1', w.params_buf, k_crud_update, id, 0, service_unavailable) } @@ -845,8 +1123,8 @@ fn (mut w WorkerCtx) render_crud_update(mut out []u8, id int) { // write_json_into is the transport-agnostic /json serializer: it only APPENDS // response bytes to `out`, so the plaintext path (via WorkerCtx) and the json-tls -// path (a stateless TLS handler) share it verbatim. `ro` is read-only and nothing -// per-request is heap-allocated. Content-Length is precomputed from the SAME +// path (the TLS listener's handler, which gets its TlsWorker as worker_state) +// share it verbatim. `ro` is read-only and nothing per-request is heap-allocated. Content-Length is precomputed from the SAME // values the body emits, so the framed length can never desync from the body // (no response-splitting / smuggling surface). fn write_json_into(ro &SharedRO, mut out []u8, count int, m i64) { @@ -949,12 +1227,18 @@ fn (w &WorkerCtx) json_body(count int, m i64) string { // the bytes that actually arrived, never from Content-Length, which a chunked // POST does not carry at all. fn (mut w WorkerCtx) echo(mut out []u8, req request_parser.HttpRequest) { + echo_into(mut out, req, mut w.dechunk_buf) +} + +// echo_into is /echo for both listeners (plaintext :8080 and the 8gbit TLS +// listener on :8081); `scratch` is the caller's reused dechunk buffer. +fn echo_into(mut out []u8, req request_parser.HttpRequest, mut scratch []u8) { if te := req.get_header_value_slice('Transfer-Encoding') { val := unsafe { tos(&req.buffer[te.start], te.len) } if val.contains('chunked') { - unsafe { w.dechunk_buf.len = 0 } - dechunk_into(mut w.dechunk_buf, req.buffer, req.body.start, req.body.len) - emit(mut out, 'application/octet-stream', w.dechunk_buf) + unsafe { scratch.len = 0 } + dechunk_into(mut scratch, req.buffer, req.body.start, req.body.len) + emit(mut out, 'application/octet-stream', scratch) return } } @@ -1156,6 +1440,35 @@ fn parse_hex_slice(buf []u8, start int, length int) int { return int(n) } +// is_token_sep: the bytes that can border a token in a Connection list. +@[inline] +fn is_token_sep(c u8) bool { + return c == `,` || c == ` ` || c == `\t` +} + +// has_close_option reports whether the Connection header lists the `close` +// option: a case-insensitive token in a comma-separated list (RFC 9110 §7.6.1), +// matched in place without allocating (this binary may run -gc none). +@[direct_array_access] +fn has_close_option(req request_parser.HttpRequest) bool { + c := req.get_header_value_slice('Connection') or { return false } + end := c.start + c.len + mut i := c.start + for i + 5 <= end { + if (req.buffer[i] | 0x20) == `c` && (req.buffer[i + 1] | 0x20) == `l` + && (req.buffer[i + 2] | 0x20) == `o` && (req.buffer[i + 3] | 0x20) == `s` + && (req.buffer[i + 4] | 0x20) == `e` { + before := i == c.start || is_token_sep(req.buffer[i - 1]) + after := i + 5 == end || is_token_sep(req.buffer[i + 5]) + if before && after { + return true + } + } + i++ + } + return false +} + fn accepts_gzip(req request_parser.HttpRequest) bool { ae := req.get_header_value_slice('Accept-Encoding') or { return false } return unsafe { tos(&req.buffer[ae.start], ae.len) }.contains('gzip') @@ -1297,6 +1610,20 @@ fn parse_db_url(u string) pg_async.ConnConfig { } } +// TlsWorker is the per-worker state of the TLS listener: the reused dechunk +// buffer /echo needs for a chunked body (a per-request buffer would leak +// under -gc none). +struct TlsWorker { +mut: + dechunk_buf []u8 +} + +fn new_tls_worker() voidptr { + return &TlsWorker{ + dechunk_buf: []u8{cap: 16384} + } +} + // load_tls_config builds the json-tls server's TLS config. It reads the cert/key // the HttpArena harness bind-mounts at /certs (overridable via TLS_CERT/TLS_KEY). // If NO cert is mounted (local dev), it falls back to a fresh self-signed cert — @@ -1304,6 +1631,24 @@ fn parse_db_url(u string) pg_async.ConnConfig { // cert IS present but the key is missing/unreadable, it FAILS LOUDLY rather than // silently self-signing, so a real misconfiguration can't slip through as "works // but with the wrong identity". TLS 1.3 + ALPN http/1.1 are fixed by the tls shim. +// connect_pool brings up a worker's pool, retrying for up to 30 s while +// Postgres refuses connections. The postgres image answers pg_isready and psql +// over its unix socket while the init-time server is still up, then restarts +// to listen on TCP, so a server started right after "ready" can meet a refused +// connect for a moment. +fn connect_pool(cfg pg_async.ConnConfig, size int) &pg_async.PgPool { + mut last := '' + for _ in 0 .. 150 { + if pool := pg_async.new_pool(cfg, size) { + return pool + } else { + last = err.msg() + } + time.sleep(200 * time.millisecond) + } + panic('vanilla-epoll: pg pool bring-up failed: ${last}') +} + fn load_tls_config() &tls.Config { cert_path := os.getenv_opt('TLS_CERT') or { '/certs/server.crt' } key_path := os.getenv_opt('TLS_KEY') or { '/certs/server.key' } @@ -1338,7 +1683,10 @@ fn main() { if total < 1 { total = 64 } - workers := runtime.nr_cpus() + // Same count the server starts with (VANILLA_WORKERS, which the image sets from + // the container's cpuset; nr_cpus otherwise), so the budget splits across the + // workers that actually run rather than the host's CPU count. + workers := core.max_thread_pool_size mut per_worker := total / workers if per_worker < 1 { per_worker = 1 @@ -1346,33 +1694,39 @@ fn main() { dataset_path := os.getenv_opt('DATASET_PATH') or { '/data/dataset.json' } dataset_raw := os.read_file(dataset_path) or { '[]' } - dataset := json.decode([]DatasetItem, dataset_raw) or { []DatasetItem{} } + dataset := json.decode[[]DatasetItem](dataset_raw) or { []DatasetItem{} } mut prefixes := []string{cap: dataset.len} for it in dataset { - enc := json.encode(it) + // escape_unicode: the byte-exact output of the removed `json` module's encode + // (non-ASCII as \uXXXX), so the /json bodies don't change with the toolchain. + enc := json.encode(it, escape_unicode: true) prefixes << enc#[..-1] + ',"total":' } static_dir := os.getenv_opt('STATIC_DIR') or { '/data/static' } - // Canonical static server: loads every asset PLUS its .br/.gz siblings once, - // mounts them at /static/, and negotiates Accept-Encoding per request (serving - // the precompressed body when accepted). Replaces the former hand-rolled, - // identity-only map that ignored Accept-Encoding and always shipped the raw - // file. spa_fallback is off: the arena fixture set has no SPA entrypoint. + // Canonical static server, mounted at /static/ on both listeners: negotiates the + // precompressed .br/.gz sibling per Accept-Encoding (the arena sends + // `br;q=1, gzip;q=0.8`), with ETag/Vary/Cache-Control. spa_fallback is off: the + // arena fixture set has no SPA entrypoint. + // follow_disk: the cache follows the disk (engine rule: replace a file and the + // next response carries the new bytes). Each representation is an immutable + // snapshot re-checked with one stat(2) per REVALIDATE window and rebuilt when + // the file's (dev, ino, size, mtime, ctime) changed. + // sendfile_min_bytes: representations >= 16 KiB keep an fd and go out with + // sendfile(2) where the worker can hand them off: the plain epoll worker and + // kTLS connections on :8081 (the kernel encrypts the pages). + // memory_fallback: those representations keep their bytes in RAM too, so a + // worker that cannot sendfile them (io_uring's borrowed send, a userspace-TLS + // connection) sends from memory instead of reading the file per request. asv := static_assets.new(static_assets.Config{ - root: static_dir - url_prefix: '/static/' - spa_fallback: '' - // Serve any representation >= 16 KiB from disk with sendfile(2) instead of - // preloading + copying it through the per-connection write buffer. The arena - // .br siblings are small (<256 KiB, the default threshold), so the default - // would copy each ~33-47 KiB .br into every connection's write_buf, which the - // pool then retains — a per-connection RSS balloon at high conn counts (CI - // measured +168% mem, ~1 GiB at 6800 conns). 16 KiB sendfiles the large .br - // (the balloon drivers) zero-copy while still preloading the tiny ones (cheap - // memcpy, negligible write_buf growth) — flat RSS + best throughput in A/B. + root: static_dir + url_prefix: '/static/' + spa_fallback: '' sendfile_min_bytes: 16 * 1024 + memory_fallback: true + follow_disk: true + revalidate_ms: static_revalidate_ms }) or { panic('vanilla-epoll: static_assets init failed: ${err}') } ro := &SharedRO{ @@ -1381,29 +1735,45 @@ fn main() { asv: asv crud: []CrudSlot{len: crud_cache_slots} crud_mu: sync.new_rwmutex() + users: []CrudSlot{len: user_cache_slots} + users_mu: sync.new_rwmutex() gz: map[u64][]u8{} gz_mu: sync.new_rwmutex() } // ── json-tls profile: the same /json handler over HTTPS on :8081 ─────────── - // A SECOND server because tls_config is server-wide. It serves ONLY /json - // (404 for everything else) so the TLS port exposes the minimal surface the - // profile needs — no /static, /echo, /crud or DB routes. The handler is a - // STATELESS request_handler (no make_state, sidestepping the TLS worker's - // stateful path) capturing the read-only `ro`; it reuses write_json_into - // verbatim, so the bytes are identical to the plaintext /json. Mbed TLS 1.3, - // ALPN http/1.1 (set by the tls shim) → curl --http1.1 negotiates 1.1. - tls_handler := fn [ro] (req_buffer []u8, fd int, mut out []u8) ! { + // A SECOND server because tls_config is server-wide. It serves ONLY /json, /echo + // and /static (404 for everything else) so the TLS port exposes the minimal + // surface the json-tls, 8gbit and static-tls profiles need — no /crud or DB + // routes. On a kTLS connection a /static body of 16 KiB or more goes out with + // sendfile(2), headers coalesced into its first record; on a userspace-TLS + // connection it is sent from memory (memory_fallback). The + // handler captures the read-only `ro` and gets its TlsWorker (the /echo dechunk + // buffer) as worker_state from make_state. It must stay synchronous (.done): the + // TLS worker has no watch reactor, so a .suspend would drop the connection. It + // reuses write_json_into verbatim, so the bytes are identical to the plaintext + // /json. Mbed TLS 1.3, ALPN http/1.1 (set by the tls shim) → curl --http1.1 + // negotiates 1.1. + tls_handler := fn [ro] (req_buffer []u8, mut out []u8, client_fd int, worker_state voidptr, mut event_loop core.EventLoop) core.Step { + mut tw := unsafe { &TlsWorker(worker_state) } mut req := request_parser.HttpRequest{ buffer: req_buffer } if !request_parser.decode_into(mut req) { wb(mut out, bad_request) - return + return .done } target := unsafe { tos(&req.buffer[req.path.start], req.path.len) } qpos := target.index_u8(`?`) route := if qpos < 0 { target } else { unsafe { tos(target.str, qpos) } } + if route.starts_with('/static/') { + ro.asv.respond_req_into(&req, mut out) + return .done + } + if route == '/echo' { + echo_into(mut out, req, mut tw.dechunk_buf) + return .done + } if route.starts_with('/json/') { count := clamp_count(parse_u_at(route, 6), ro.dataset.len) mut m := qint(req, qk_m) @@ -1411,9 +1781,10 @@ fn main() { m = 1 } write_json_into(ro, mut out, count, m) - return + return .done } wb(mut out, not_found) + return .done } // Port is fixed to 8081 by the HttpArena harness; TLS_PORT lets local runs pick // a free port (the harness injects nothing, so the default is the contract). @@ -1421,19 +1792,21 @@ fn main() { if tls_port <= 0 { tls_port = 8081 } - tls_server := http_server.new_server(http_server.ServerConfig{ + tls_server := server.new_server(server.ServerConfig{ port: tls_port io_multiplexing: .epoll - limits: http_server.Limits{ - // json-tls requests are tiny GETs; a small ceiling bounds per-conn - // memory and shrinks the DoS surface (the TLS port takes no bodies). - max_request_bytes: 64 * 1024 + limits: server.Limits{ + // json-tls sends tiny GETs; 8gbit POSTs 10 KB to /echo and validation + // goes up to 100 KB, chunked included. 256 KiB covers that with room + // for chunk framing and still bounds a connection's read buffer. + max_request_bytes: 256 * 1024 } - request_handler: tls_handler + handler: tls_handler + make_state: new_tls_worker tls_config: load_tls_config() })! // run() blocks in the accept loop, so the TLS server runs on its own thread - // while the plaintext server.run() below blocks main. run() has a value-mut + // while the plaintext srv.run() below blocks main. run() has a value-mut // receiver, so spawn it via a closure with a local mut copy (each Server is // independent — own socket, workers and counters). spawn fn [tls_server] () { @@ -1441,17 +1814,15 @@ fn main() { s.run() }() - mut server := http_server.new_server(http_server.ServerConfig{ + mut srv := server.new_server(server.ServerConfig{ port: 8080 io_multiplexing: .epoll - limits: http_server.Limits{ + limits: server.Limits{ max_request_bytes: 32 * 1024 * 1024 } - async_handler: handle + handler: handle make_state: fn [ro, cfg, per_worker] () voidptr { - pool := pg_async.new_pool(cfg, per_worker) or { - panic('vanilla-epoll: pg pool bring-up failed: ${err}') - } + pool := connect_pool(cfg, per_worker) w := &WorkerCtx{ ro: ro pool: pool @@ -1461,9 +1832,10 @@ fn main() { stash_pool: []&Stash{cap: 64} // Stash free-list fortunes_buf: []Fortune{cap: 256} // reused /fortunes rows dechunk_buf: []u8{cap: 4096} // reused chunked-body scratch + timer_fds: []int{cap: 64} // recycled /delay timerfds } return voidptr(w) } })! - server.run() + srv.run() } diff --git a/frameworks/vanilla-epoll/mbedtls-rsa-sign-cache.patch b/frameworks/vanilla-epoll/mbedtls-rsa-sign-cache.patch new file mode 100644 index 000000000..016cc06b8 --- /dev/null +++ b/frameworks/vanilla-epoll/mbedtls-rsa-sign-cache.patch @@ -0,0 +1,101 @@ +--- a/tf-psa-crypto/drivers/builtin/src/psa_crypto_rsa.c ++++ b/tf-psa-crypto/drivers/builtin/src/psa_crypto_rsa.c +@@ -306,6 +306,68 @@ + return PSA_SUCCESS; + } + ++/* vanilla (HttpArena) patch: per-thread cache of the signing key's parsed RSA ++ * context. ++ * ++ * Unpatched, every psa_sign_hash() re-parses the key into a fresh ++ * mbedtls_rsa_context, so mbedtls_rsa_private() finds no blinding values and ++ * regenerates them from scratch (a random value, its modular inverse and an ++ * exponentiation) before signing. For a TLS 1.3 server with an RSA ++ * certificate that is most of every handshake's CertificateVerify. A ++ * long-lived context, as the legacy RSA API always had, updates its blinding ++ * values by squaring instead. ++ * ++ * The cache is thread-local, so there is no locking and no thread ever sees ++ * another's (mutable) blinding state. It holds one key, compared byte for ++ * byte, so a different or re-imported key simply reloads. The entry lives as ++ * long as the thread. */ ++static __thread mbedtls_rsa_context *vanilla_sign_rsa = NULL; ++static __thread uint8_t *vanilla_sign_key = NULL; ++static __thread size_t vanilla_sign_key_len = 0; ++ ++static psa_status_t vanilla_rsa_sign_context(psa_key_type_t type, ++ const uint8_t *key_buffer, ++ size_t key_buffer_size, ++ mbedtls_rsa_context **p_rsa, ++ int *cached) ++{ ++ psa_status_t status; ++ mbedtls_rsa_context *rsa = NULL; ++ uint8_t *copy; ++ ++ if (vanilla_sign_rsa != NULL && vanilla_sign_key_len == key_buffer_size && ++ memcmp(vanilla_sign_key, key_buffer, key_buffer_size) == 0) { ++ *p_rsa = vanilla_sign_rsa; ++ *cached = 1; ++ return PSA_SUCCESS; ++ } ++ status = mbedtls_psa_rsa_load_representation(type, key_buffer, ++ key_buffer_size, &rsa); ++ *p_rsa = rsa; ++ *cached = 0; ++ if (status != PSA_SUCCESS) { ++ return status; ++ } ++ copy = mbedtls_calloc(1, key_buffer_size); ++ if (copy == NULL) { ++ return PSA_SUCCESS; /* sign uncached; the caller frees rsa */ ++ } ++ memcpy(copy, key_buffer, key_buffer_size); ++ if (vanilla_sign_rsa != NULL) { ++ mbedtls_rsa_free(vanilla_sign_rsa); ++ mbedtls_free(vanilla_sign_rsa); ++ } ++ if (vanilla_sign_key != NULL) { ++ mbedtls_platform_zeroize(vanilla_sign_key, vanilla_sign_key_len); ++ mbedtls_free(vanilla_sign_key); ++ } ++ vanilla_sign_rsa = rsa; ++ vanilla_sign_key = copy; ++ vanilla_sign_key_len = key_buffer_size; ++ *cached = 1; ++ return PSA_SUCCESS; ++} ++ + psa_status_t mbedtls_psa_rsa_sign_hash( + const psa_key_attributes_t *attributes, + const uint8_t *key_buffer, size_t key_buffer_size, +@@ -316,11 +378,12 @@ + mbedtls_rsa_context *rsa = NULL; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_md_type_t md_alg; ++ int cached = 0; + +- status = mbedtls_psa_rsa_load_representation(attributes->type, +- key_buffer, +- key_buffer_size, +- &rsa); ++ status = vanilla_rsa_sign_context(attributes->type, ++ key_buffer, ++ key_buffer_size, ++ &rsa, &cached); + if (status != PSA_SUCCESS) { + goto exit; + } +@@ -377,8 +440,10 @@ + status = mbedtls_to_psa_error(ret); + + exit: +- mbedtls_rsa_free(rsa); +- mbedtls_free(rsa); ++ if (!cached) { ++ mbedtls_rsa_free(rsa); ++ mbedtls_free(rsa); ++ } + + return status; + } diff --git a/frameworks/vanilla-epoll/meta.json b/frameworks/vanilla-epoll/meta.json index 48f20a081..203545fd6 100644 --- a/frameworks/vanilla-epoll/meta.json +++ b/frameworks/vanilla-epoll/meta.json @@ -3,15 +3,17 @@ "language": "V", "type": "engine", "engine": "epoll", - "description": "vanilla is a minimalist, high-performance HTTP server written in V: multi-threaded, non-blocking epoll I/O, lock-free, copy-free, SO_REUSEPORT. Handlers are pure (request)->[]u8 returning raw response bytes. JSON is built in a single allocation with precomputed prefixes (no per-request reflection); json-comp gzips on Accept-Encoding; json-tls terminates TLS 1.3 (Mbed TLS 4) on :8081 with ALPN http/1.1, reusing the same allocation-free /json serializer; static assets are preloaded into memory; fortunes renders the DB rows + a runtime row with HTML escaping; async-db uses the stdlib db.pg ConnectionPool. Pinned V 0.5.1 (prebuilt release). crud uses an in-memory cache-aside (X-Cache MISS/HIT, invalidated on update) \u2014 no Redis required.", + "description": "vanilla is a minimalist, high-performance HTTP server written in V: multi-threaded, non-blocking epoll I/O, lock-free, copy-free, SO_REUSEPORT. Handlers are pure (request)->[]u8 returning raw response bytes. JSON is built in a single allocation with precomputed prefixes (no per-request reflection); json-comp gzips on Accept-Encoding; json-tls terminates TLS 1.3 (Mbed TLS 4) on :8081 with ALPN http/1.1, reusing the same allocation-free /json serializer; static-tls serves the 20 /static files on :8081 through vanilla's static_assets (br/gzip negotiation; snapshots re-checked against the disk, so a replaced file is served at once), sending bodies of 16 KiB or more with sendfile(2) over kTLS; fortunes renders the DB rows + a runtime row with HTML escaping; async-db/crud/fortunes use the native async pg_async driver with per-worker pipelined pools. Pinned V master (built from source, bootstrap pinned). async parks each /delay/{ms} on a one-shot timerfd from a per-worker free-list and answers only once it reports an expiration; 8gbit echoes the POST body on the :8081 TLS listener (Content-Length or chunked, per-worker dechunk buffer); production-stack's /api cache-aside (X-Cache MISS/HIT, 1 s items / 30 s users TTL, invalidated on write) runs in-process \u2014 no Redis required. One worker per CPU of the container's cpuset.", "repo": "https://github.com/enghitalo/vanilla", - "enabled": false, + "enabled": true, "tests": [ - "baseline", "latency-1m", "latency-10k", + "baseline", "async", "latency-1m", "latency-10k", "latency-500k-8cpu", "pipelined", "limited-conn", "json-comp", "json-tls", + "static-tls", + "8gbit", "async-db", "fortunes" ], diff --git a/frameworks/vanilla-gateway/compose.gateway-h3.yml b/frameworks/vanilla-gateway/compose.gateway-h3.yml new file mode 100644 index 000000000..baf66d5d7 --- /dev/null +++ b/frameworks/vanilla-gateway/compose.gateway-h3.yml @@ -0,0 +1,46 @@ +# gateway-h3 - the same two services as compose.gateway.yml, reached over QUIC. +# Stock Caddy binds 8443 on tcp and udp with `protocols h1 h2 h3`, serves +# /static/* from disk and forwards the rest to the vanilla-epoll image over +# loopback HTTP/1.1. Every entry on this profile measures within a few percent +# behind the same Caddy edge, so the split is the even one they use. +services: + proxy: + build: + context: ./proxy-caddy + network_mode: host + cpuset: "${PROXY_CPUSET:-0-15,64-79}" + ulimits: + memlock: -1 + nofile: + soft: 1048576 + hard: 1048576 + security_opt: + - seccomp:unconfined + volumes: + - ${CERTS_DIR}:/certs:ro + - ${DATA_DIR}/static:/data/static:ro + depends_on: + - server + + server: + build: + context: ../vanilla-epoll + dockerfile: Dockerfile + network_mode: host + cpuset: "${SERVER_CPUSET:-16-31,80-95}" + ulimits: + memlock: -1 + nofile: + soft: 1048576 + hard: 1048576 + security_opt: + - seccomp:unconfined + environment: + - DATABASE_URL=${DATABASE_URL} + # Postgres allows 256; split evenly across the server's workers + - DATABASE_MAX_CONN=256 + - DATASET_PATH=/data/dataset.json + volumes: + - ${DATA_DIR}/dataset.json:/data/dataset.json:ro + # the image also mounts its static handler at boot; Caddy serves /static here + - ${DATA_DIR}/static:/data/static:ro diff --git a/frameworks/vanilla-gateway/compose.gateway.yml b/frameworks/vanilla-gateway/compose.gateway.yml new file mode 100644 index 000000000..afd31d8f1 --- /dev/null +++ b/frameworks/vanilla-gateway/compose.gateway.yml @@ -0,0 +1,49 @@ +# gateway-64 - stock nginx (TLS + h2 on 8443) in front of the vanilla-epoll +# image, which serves /baseline2, /json and /async-db on 8080. nginx serves +# /static/* from disk and forwards the rest over loopback HTTP/1.1 through a +# keepalive pool. +# +# The split follows the nginx entries that lead this profile: terminating TLS +# under multiplexed h2 is the heavier half, so the edge gets 20 cores against +# the server's 12. Sweep it with PROXY_CPUSET / SERVER_CPUSET. +services: + proxy: + build: + context: ./proxy-nginx + network_mode: host + cpuset: "${PROXY_CPUSET:-0-19,64-83}" + ulimits: + memlock: -1 + nofile: + soft: 1048576 + hard: 1048576 + security_opt: + - seccomp:unconfined + volumes: + - ${CERTS_DIR}:/certs:ro + - ${DATA_DIR}/static:/data/static:ro + depends_on: + - server + + server: + build: + context: ../vanilla-epoll + dockerfile: Dockerfile + network_mode: host + cpuset: "${SERVER_CPUSET:-20-31,84-95}" + ulimits: + memlock: -1 + nofile: + soft: 1048576 + hard: 1048576 + security_opt: + - seccomp:unconfined + environment: + - DATABASE_URL=${DATABASE_URL} + # Postgres allows 256; split evenly across the server's workers + - DATABASE_MAX_CONN=256 + - DATASET_PATH=/data/dataset.json + volumes: + - ${DATA_DIR}/dataset.json:/data/dataset.json:ro + # the image also mounts its static handler at boot; nginx serves /static here + - ${DATA_DIR}/static:/data/static:ro diff --git a/frameworks/vanilla-gateway/meta.json b/frameworks/vanilla-gateway/meta.json new file mode 100644 index 000000000..a88d97ab4 --- /dev/null +++ b/frameworks/vanilla-gateway/meta.json @@ -0,0 +1,16 @@ +{ + "display_name": "vanilla-epoll", + "language": "V", + "type": "engine", + "engine": "epoll", + "description": "vanilla-epoll behind a stock edge for the gateway profiles: nginx terminates TLS + h2 (gateway-64) and Caddy terminates QUIC + h3 (gateway-h3); both serve /static/* from disk and forward /baseline2, /json and /async-db to the vanilla-epoll image over loopback HTTP/1.1 with a 2048-connection keepalive pool. The server is the vanilla-epoll entry unchanged (same Dockerfile), one worker per CPU of its cpuset, async pg_async pools, and /json served gzip from its lazy per-(count, m) cache when the edge forwards Accept-Encoding.", + "repo": "https://github.com/enghitalo/vanilla", + "enabled": true, + "tests": [ + "gateway-64", + "gateway-h3" + ], + "maintainers": [ + "enghitalo" + ] +} diff --git a/frameworks/vanilla-gateway/proxy-caddy/Caddyfile b/frameworks/vanilla-gateway/proxy-caddy/Caddyfile new file mode 100644 index 000000000..1978ce971 --- /dev/null +++ b/frameworks/vanilla-gateway/proxy-caddy/Caddyfile @@ -0,0 +1,38 @@ +# vanilla gateway-h3 edge. +# +# Stock Caddy terminates TLS and h3 on 8443, serves /static/* from disk and +# forwards the dynamic endpoints to the vanilla-epoll server on loopback. +{ + admin off + auto_https off + servers { + protocols h1 h2 h3 + } +} + +https://localhost:8443 { + tls /certs/server.crt /certs/server.key + + # served from disk by the proxy; precompressed prefers the .br / .gz + # sidecars per Accept-Encoding (root /data + /static/foo -> /data/static/foo) + handle /static/* { + root * /data + file_server { + precompressed br gzip + } + } + + # /baseline2, /json, /async-db: plain HTTP/1.1 with a large keepalive pool, + # so streams multiplexed over one QUIC connection fan out across the + # server's workers + handle { + reverse_proxy 127.0.0.1:8080 { + transport http { + versions 1.1 + keepalive 5m + keepalive_idle_conns 2048 + keepalive_idle_conns_per_host 2048 + } + } + } +} diff --git a/frameworks/vanilla-gateway/proxy-caddy/Dockerfile b/frameworks/vanilla-gateway/proxy-caddy/Dockerfile new file mode 100644 index 000000000..7263f7f51 --- /dev/null +++ b/frameworks/vanilla-gateway/proxy-caddy/Dockerfile @@ -0,0 +1,9 @@ +# Stock Caddy, which ships h3 in the base image. gateway-h3 only; gateway-64 uses +# the nginx edge in ../proxy-nginx. +FROM caddy:2-alpine + +COPY Caddyfile /etc/caddy/Caddyfile + +EXPOSE 8443/tcp 8443/udp + +CMD ["caddy", "run", "--config", "/etc/caddy/Caddyfile", "--adapter", "caddyfile"] diff --git a/frameworks/vanilla-gateway/proxy-nginx/Dockerfile b/frameworks/vanilla-gateway/proxy-nginx/Dockerfile new file mode 100644 index 000000000..b45436eb3 --- /dev/null +++ b/frameworks/vanilla-gateway/proxy-nginx/Dockerfile @@ -0,0 +1,8 @@ +# Stock nginx for gateway-64 (TLS + h2). gateway-h3 uses the Caddy edge in ../proxy-caddy. +FROM nginx:1.27-alpine + +COPY nginx.conf /etc/nginx/nginx.conf + +EXPOSE 8443/tcp + +CMD ["nginx", "-g", "daemon off;"] diff --git a/frameworks/vanilla-gateway/proxy-nginx/nginx.conf b/frameworks/vanilla-gateway/proxy-nginx/nginx.conf new file mode 100644 index 000000000..56f149912 --- /dev/null +++ b/frameworks/vanilla-gateway/proxy-nginx/nginx.conf @@ -0,0 +1,66 @@ +# vanilla gateway-64 edge, nginx. +# +# nginx terminates TLS and h2 on 8443, serves /static/* from disk and forwards +# the rest to the vanilla-epoll server over loopback HTTP/1.1 through a +# keepalive pool, so the streams multiplexed on each client connection fan out +# across the server's workers instead of queueing behind one upstream socket. + +worker_processes auto; +worker_rlimit_nofile 1048576; + +events { + worker_connections 65535; + multi_accept on; +} + +http { + include /etc/nginx/mime.types; + default_type application/octet-stream; + + sendfile on; + tcp_nopush on; + tcp_nodelay on; + + # precompressed .gz sidecars straight from disk, nothing compressed per request + gzip_static on; + gzip_vary on; + + keepalive_timeout 65; + # the generator holds its connections for the whole run: never close one on a count + keepalive_requests 1000000; + + access_log off; + error_log /dev/stderr warn; + + upstream backend { + server 127.0.0.1:8080; + keepalive 2048; + keepalive_requests 1000000; + keepalive_timeout 300s; + } + + server { + listen 8443 ssl; + http2 on; + + ssl_certificate /certs/server.crt; + ssl_certificate_key /certs/server.key; + ssl_protocols TLSv1.2 TLSv1.3; + ssl_prefer_server_ciphers off; + + # the profile has the proxy serve these from disk, never the server + location /static/ { + alias /data/static/; + expires off; + add_header Cache-Control "no-cache"; + } + + # /baseline2, /json, /async-db: the vanilla-epoll server + location / { + proxy_pass http://backend; + proxy_http_version 1.1; + proxy_set_header Connection ""; + proxy_set_header Host $host; + } + } +} diff --git a/frameworks/vanilla-h2c/Dockerfile b/frameworks/vanilla-h2c/Dockerfile index 8e637bc7c..9887f8a5b 100644 --- a/frameworks/vanilla-h2c/Dockerfile +++ b/frameworks/vanilla-h2c/Dockerfile @@ -5,27 +5,48 @@ RUN apt-get -qq update && \ ca-certificates build-essential git liburing-dev && \ rm -rf /var/lib/apt/lists/* -# Pinned, reproducible V at master commit 5fb31f25 (0.5.2, built from source), -# the commit this entry was validated against. `make` bootstraps via the -# matching vc; if a much later rebuild ever fails to bootstrap, pin vlang/vc to -# the commit cut for this V. -RUN git clone https://github.com/vlang/v /opt/v && \ - cd /opt/v && git checkout 5fb31f25bd9b056cc63cedc51b669073658b41a8 && \ - make && ln -s /opt/v/v /usr/local/bin/v +# Pinned, reproducible V at master commit b99970bd (0.5.2, built from source), +# the commit this entry was validated against. +# +# The bootstrap is pinned too. A bare `make` clones vlang/vc and vlang/tccbin at +# their CURRENT heads, so a fixed V source gets built by whatever compiler vc +# holds that day: that is what broke every V entry in #1288 ("C function C.open +# was already declared with a different signature"), and vc head has since +# failed in other ways. vc 2cbaf6bc is vc's newest snapshot (generated from V +# 0c41fadb, 40 commits earlier; vc has none for b99970bd yet), so it is what +# `make` bootstraps this V with today; tccbin d6e7ac1b is the head of tccbin's +# thirdparty-linux-amd64 branch, and `local=1` makes `make` build with both +# instead of pulling. +# +# Each repo is fetched at its one pinned commit (depth 1) rather than cloned: +# a full clone of v, vc and tccbin is hundreds of MB and a slow or flaky link +# stalls it past the validator's timeout; this is ~30 MB. +RUN git init -q /opt/v && cd /opt/v && \ + git fetch -q --depth 1 https://github.com/vlang/v b99970bd438a7bdcdfbe38f74d9364db801d5439 && \ + git checkout -q FETCH_HEAD && \ + git init -q vc && \ + git -C vc fetch -q --depth 1 https://github.com/vlang/vc 2cbaf6bc2367937cd5f0b4ef923d1ef9aad613b3 && \ + git -C vc checkout -q FETCH_HEAD && \ + git init -q thirdparty/tcc && \ + git -C thirdparty/tcc fetch -q --depth 1 https://github.com/vlang/tccbin d6e7ac1b1bcc98aed734a6ecbfa8509f24606c74 && \ + git -C thirdparty/tcc checkout -q FETCH_HEAD && \ + make local=1 && ln -s /opt/v/v /usr/local/bin/v # Install vanilla as the `vanilla` module (import vanilla.*), pinned to a # specific commit: reproducible, with NO per-build network call to detect # changes. To pick up upstream library fixes, bump this commit. # -# Pinned to vanilla main @f1a9691 — the commit that carries the HTTP/2 -# implementation (enghitalo/vanilla#122's http2 story) landed on top of the -# conn-mode seam (#136): a self-contained RFC 9113/7541 codec — HPACK (static + -# dynamic table, canonical Huffman, decoded-block ceiling), the frame codec, -# and the connection state machine with send-side flow control — serving -# cleartext h2c over the takeover seam, hardened against a live h2spec CI gate. -# This entry composes that machine with a small application handler; see main.v. -RUN git clone https://github.com/enghitalo/vanilla /root/.vmodules/vanilla && \ - git -C /root/.vmodules/vanilla checkout f1a96919587b6ba15a1dd9154cd1d75d10cb2a3e +# Pinned to vanilla main @091c014. It has response trailers +# (enghitalo/vanilla#174), which unary-grpc needs to send grpc-status after +# the message, and no allocation per request in http2 (#175): HPACK literals +# decoded into a per-connection arena and copied into the stream's pooled +# storage, and a fixed stream table instead of a map. Under -gc none the +# old path kept ~200 B per request (10 GiB in a 5 s run); RSS is now flat +# per request. Fetched at that one commit. +RUN git init -q /root/.vmodules/vanilla && \ + git -C /root/.vmodules/vanilla fetch -q --depth 1 https://github.com/enghitalo/vanilla \ + 091c014a0191afd7e740b84f5599b9b1fc1fd914 && \ + git -C /root/.vmodules/vanilla checkout -q FETCH_HEAD WORKDIR /app COPY . . @@ -42,6 +63,11 @@ RUN apt-get -qq update && \ rm -rf /var/lib/apt/lists/* COPY --from=build /app/server /server -# h2c, prior-knowledge, on 8082 (HttpArena's cleartext HTTP/2 port). -EXPOSE 8082 -CMD ["/server"] +# h2c, prior-knowledge, on 8082 (HttpArena's cleartext HTTP/2 port) and on +# 8080, where the harness drives unary gRPC. +EXPOSE 8080 8082 +# One worker per CPU the container may run on. vanilla defaults to nr_cpus, +# which reads the host's online CPUs (128 on the bench box) and ignores the +# cpuset, so a 64-CPU profile started 128 workers and latency-500k-8cpu would +# start 128 on 8. nproc honours the cpuset; an explicit VANILLA_WORKERS wins. +CMD ["/bin/sh", "-c", "VANILLA_WORKERS=${VANILLA_WORKERS:-$(nproc)} exec /server"] diff --git a/frameworks/vanilla-h2c/main.v b/frameworks/vanilla-h2c/main.v index 1e43dfcb3..11b1076f0 100644 --- a/frameworks/vanilla-h2c/main.v +++ b/frameworks/vanilla-h2c/main.v @@ -17,9 +17,13 @@ module main // the connection dropped, never a 200. HttpArena's validator asserts this so // the benchmark can't silently measure h1 throughput on the h2c port. // -// Routes (the two h2c profiles): +// Routes (the two h2c profiles, plus unary-grpc): // GET /baseline2?a=&b= -> text/plain, the integer sum a+b // GET /json/{count}?m= -> application/json, {"items":[...],"count":N} +// POST /benchmark.BenchmarkService/GetSum -> gRPC SumReply{result: a+b} +// +// The same handlers also listen on :8080, the port the harness drives unary +// gRPC on (h2c prior-knowledge there too). // The /json body reuses the vanilla /json profile's shape verbatim: the same // /data/dataset.json, the same precomputed per-item prefixes, total = // price*quantity*m. Multi-threaded, SO_REUSEPORT, lock-free, -gc none. @@ -136,24 +140,35 @@ fn parse_u_at(s string, start int) i64 { } // q_int reads integer query parameter `key` from a full request-target string -// (e.g. "/baseline2?a=13&b=42"). Returns 0 when the key is absent. +// (e.g. "/baseline2?a=13&b=42"). Returns 0 when the key is absent. It indexes +// into target: slicing substrings (target[a..], query[i..eq] == key) would +// heap-copy each one, allocations per request that -gc none never frees. +@[direct_array_access] fn q_int(target string, key string) i64 { qpos := target.index_u8(`?`) if qpos < 0 { return 0 } - query := target[qpos + 1..] - mut i := 0 - for i < query.len { + mut i := qpos + 1 + for i < target.len { mut eq := i - for eq < query.len && query[eq] != `=` && query[eq] != `&` { + for eq < target.len && target[eq] != `=` && target[eq] != `&` { eq++ } - if eq < query.len && query[eq] == `=` && query[i..eq] == key { - return parse_u_at(query, eq + 1) + if eq < target.len && target[eq] == `=` && eq - i == key.len { + mut same := true + for k in 0 .. key.len { + if target[i + k] != key[k] { + same = false + break + } + } + if same { + return parse_u_at(target, eq + 1) + } } mut amp := eq - for amp < query.len && query[amp] != `&` { + for amp < target.len && target[amp] != `&` { amp++ } i = amp + 1 @@ -187,29 +202,178 @@ fn write_json_body(ro &SharedRO, mut out []u8, count int, m i64) { // ── HTTP/2 response framing ────────────────────────────────────────────────── +// H2cConn is one flipped connection's state (the takeover_state): the http2 +// machine plus the buffers every request on it reuses. Allocated once per +// connection; nothing on the request path allocates (the binary is -gc none, +// where a per-request buffer would never be freed). +struct H2cConn { +mut: + conn &http2.ServerConn = unsafe { nil } + reqs []http2.Http2Request + block []u8 + body []u8 +} + // respond appends a 200 HEADERS block (:status + content-type) and the body as // DATA (END_STREAM on the header frame when the body is empty). -fn respond(mut conn http2.ServerConn, stream_id u32, ctype string, body []u8, mut out []u8) { - mut block := []u8{cap: 32} - http2.encode_status(mut block, 200) - http2.encode_literal(mut block, 'content-type', ctype) - conn.write_response_headers(mut out, stream_id, block, body.len == 0) +fn respond(mut hc H2cConn, stream_id u32, ctype string, body []u8, mut out []u8) { + hc.block.clear() + http2.encode_status(mut hc.block, 200) + http2.encode_literal(mut hc.block, 'content-type', ctype) + hc.conn.write_response_headers(mut out, stream_id, hc.block, body.len == 0) if body.len > 0 { - conn.write_response_data(mut out, stream_id, body) + hc.conn.write_response_data(mut out, stream_id, body) } } // respond_status answers with a bodiless status (400 malformed / 404). -fn respond_status(mut conn http2.ServerConn, stream_id u32, status int, mut out []u8) { - mut block := []u8{cap: 8} - http2.encode_status(mut block, status) - conn.write_response_headers(mut out, stream_id, block, true) +fn respond_status(mut hc H2cConn, stream_id u32, status int, mut out []u8) { + hc.block.clear() + http2.encode_status(mut hc.block, status) + hc.conn.write_response_headers(mut out, stream_id, hc.block, true) +} + +// ── unary gRPC: benchmark.BenchmarkService/GetSum ──────────────────────────── + +const grpc_path = '/benchmark.BenchmarkService/GetSum' + +// The fixed header blocks, encoded once: the response head, the OK trailers, +// and the trailers-only answer for a request that is not a valid SumRequest. +const grpc_head_block = grpc_block(200, 'content-type', 'application/grpc') +const grpc_ok_trailers = grpc_block(0, 'grpc-status', '0') +const grpc_invalid = grpc_invalid_block() + +fn grpc_block(status int, name string, value string) []u8 { + mut b := []u8{} + if status > 0 { + http2.encode_status(mut b, status) + } + http2.encode_literal(mut b, name, value) + return b +} + +fn grpc_invalid_block() []u8 { + mut b := grpc_block(200, 'content-type', 'application/grpc') + http2.encode_literal(mut b, 'grpc-status', '3') // INVALID_ARGUMENT + return b +} + +// read_varint decodes a protobuf varint at buf[pos..end]: (value, next pos), +// or next pos -1 when it is truncated or longer than 10 bytes. +@[direct_array_access] +fn read_varint(buf []u8, pos int, end int) (u64, int) { + mut v := u64(0) + mut shift := u32(0) + mut i := pos + for i < end && shift < 70 { + c := buf[i] + i++ + v |= u64(c & 0x7f) << shift + if c & 0x80 == 0 { + return v, i + } + shift += 7 + } + return 0, -1 +} + +// decode_sum_request parses a length-prefixed SumRequest (field 1 `a`, field 2 +// `b`, both int32 varints) out of a gRPC request body, skipping unknown fields +// of every wire type. ok=false for a compressed frame, a length that does not +// match the body, or a malformed message. +@[direct_array_access] +fn decode_sum_request(body []u8) (i64, i64, bool) { + if body.len < 5 || body[0] != 0 { + return 0, 0, false + } + n := int(u32(body[1]) << 24 | u32(body[2]) << 16 | u32(body[3]) << 8 | u32(body[4])) + if n != body.len - 5 { + return 0, 0, false + } + end := body.len + mut a := i64(0) + mut b := i64(0) + mut i := 5 + for i < end { + key, next := read_varint(body, i, end) + if next < 0 { + return 0, 0, false + } + i = next + match key & 7 { + 0 { + v, after := read_varint(body, i, end) + if after < 0 { + return 0, 0, false + } + i = after + // int32 is sign-extended to 64 bits on the wire + if key >> 3 == 1 { + a = i64(i32(u32(v))) + } else if key >> 3 == 2 { + b = i64(i32(u32(v))) + } + } + 1 { + i += 8 + } + 2 { + l, after := read_varint(body, i, end) + if after < 0 { + return 0, 0, false + } + i = after + int(l) + } + 5 { + i += 4 + } + else { + return 0, 0, false + } + } + if i > end { + return 0, 0, false + } + } + return a, b, true +} + +// serve_grpc_sum answers GetSum: HEADERS, the SumReply frame as DATA without +// END_STREAM, then `grpc-status: 0` as trailers (they wait behind the DATA if +// flow control parks it). +fn serve_grpc_sum(mut hc H2cConn, req http2.Http2Request, mut out []u8) { + a, b, ok := decode_sum_request(req.body) + if !ok { + hc.conn.write_response_headers(mut out, req.stream_id, grpc_invalid, true) + return + } + sum := i32(a + b) + hc.body.clear() + // 5-byte gRPC prefix: uncompressed flag + big-endian length, patched below + for _ in 0 .. 5 { + hc.body << u8(0) + } + if sum != 0 { + // proto3 omits a zero; a negative int32 goes out as a 10-byte varint + hc.body << 0x08 + mut v := u64(i64(sum)) + for v >= 0x80 { + hc.body << u8(v) | 0x80 + v >>= 7 + } + hc.body << u8(v) + } + msg_len := hc.body.len - 5 + hc.body[4] = u8(msg_len) + hc.conn.write_response_headers(mut out, req.stream_id, grpc_head_block, false) + hc.conn.write_response_body(mut out, req.stream_id, hc.body, false) + hc.conn.write_response_trailers(mut out, req.stream_id, grpc_ok_trailers) } // ── routing ────────────────────────────────────────────────────────────────── // serve_request routes ONE complete http2 request and appends its response. -fn serve_request(mut conn http2.ServerConn, ro &SharedRO, req http2.Http2Request, mut out []u8) { +fn serve_request(mut hc H2cConn, ro &SharedRO, req http2.Http2Request, mut out []u8) { mut method := '' mut target := '' for f in req.headers { @@ -220,15 +384,23 @@ fn serve_request(mut conn http2.ServerConn, ro &SharedRO, req http2.Http2Request } } if method.len == 0 || target.len == 0 { - respond_status(mut conn, req.stream_id, 400, mut out) + respond_status(mut hc, req.stream_id, 400, mut out) + return + } + if target == grpc_path { + if method != 'POST' { + respond_status(mut hc, req.stream_id, 405, mut out) + return + } + serve_grpc_sum(mut hc, req, mut out) return } qpos := target.index_u8(`?`) - route := if qpos < 0 { target } else { target[..qpos] } + route := if qpos < 0 { target } else { unsafe { tos(target.str, qpos) } } if route == baseline2_route { - mut body := []u8{cap: 24} - wi(mut body, q_int(target, 'a') + q_int(target, 'b')) - respond(mut conn, req.stream_id, ctype_text, body, mut out) + hc.body.clear() + wi(mut hc.body, q_int(target, 'a') + q_int(target, 'b')) + respond(mut hc, req.stream_id, ctype_text, hc.body, mut out) return } if route.starts_with(json_route_prefix) { @@ -237,12 +409,12 @@ fn serve_request(mut conn http2.ServerConn, ro &SharedRO, req http2.Http2Request if m == 0 { m = 1 } - mut body := []u8{cap: 512} - write_json_body(ro, mut body, count, m) - respond(mut conn, req.stream_id, ctype_json, body, mut out) + hc.body.clear() + write_json_body(ro, mut hc.body, count, m) + respond(mut hc, req.stream_id, ctype_json, hc.body, mut out) return } - respond_status(mut conn, req.stream_id, 404, mut out) + respond_status(mut hc, req.stream_id, 404, mut out) } // ── connection handlers ────────────────────────────────────────────────────── @@ -259,12 +431,17 @@ fn handle(req []u8, mut res []u8, client_fd int, worker_state voidptr, mut event if slice_eq(hr.buffer, hr.method, pri_method) && slice_eq(hr.buffer, hr.path, star_target) { // Takeover FIRST: only answer with the server preface if this worker // can actually flip the connection's mode. - mut conn := http2.new_server_conn() - if !core.queue_takeover(h2c_conn, voidptr(conn)) { + mut hc := &H2cConn{ + conn: http2.new_server_conn() + reqs: []http2.Http2Request{cap: 128} + block: []u8{cap: 64} + body: []u8{cap: 4096} + } + if !core.queue_takeover(h2c_conn, voidptr(hc)) { res << cannot_takeover return .close } - conn.write_server_preface(mut res) + hc.conn.write_server_preface(mut res) return .done } res << h1_not_supported @@ -274,15 +451,15 @@ fn handle(req []u8, mut res []u8, client_fd int, worker_state voidptr, mut event // h2c_conn is the core.ConnHandler for a flipped connection: the ServerConn // consumes frames (answering SETTINGS/PING/WINDOW_UPDATE itself) and surfaces // complete requests, routed through serve_request. The routes are synchronous, -// so the connection never suspends. takeover_state is the ServerConn; +// so the connection never suspends. takeover_state is the H2cConn; // worker_state is the shared read-only dataset. fn h2c_conn(buf []u8, mut out []u8, client_fd int, takeover_state voidptr, worker_state voidptr, mut event_loop core.EventLoop) (int, core.Step) { - mut conn := unsafe { &http2.ServerConn(takeover_state) } + mut hc := unsafe { &H2cConn(takeover_state) } ro := unsafe { &SharedRO(worker_state) } - mut reqs := []http2.Http2Request{} - consumed, closing := conn.consume(buf, mut out, mut reqs) - for req in reqs { - serve_request(mut conn, ro, req, mut out) + hc.reqs.clear() + consumed, closing := hc.conn.consume(buf, mut out, mut hc.reqs) + for i in 0 .. hc.reqs.len { + serve_request(mut hc, ro, hc.reqs[i], mut out) } if closing { return consumed, core.Step.close @@ -303,6 +480,21 @@ fn main() { dataset: dataset prefixes: prefixes } + // :8080 serves the same routes for unary-grpc, which the harness drives + // there. Its own server (own socket and workers), run on a thread while the + // :8082 one blocks main below. + grpc_srv := server.new_server(server.ServerConfig{ + port: 8080 + io_multiplexing: server.IOBackend.epoll + handler: handle + make_state: fn [ro] () voidptr { + return voidptr(ro) + } + })! + spawn fn [grpc_srv] () { + mut s := grpc_srv + s.run() + }() // h2c on :8082 (HttpArena's h2c port). The takeover seam is epoll-first // (vanilla#136): on other backends queue_takeover reports false and the // preface is answered 501 instead of a dead SETTINGS. diff --git a/frameworks/vanilla-h2c/meta.json b/frameworks/vanilla-h2c/meta.json index aae8fd37c..661d0cfdc 100644 --- a/frameworks/vanilla-h2c/meta.json +++ b/frameworks/vanilla-h2c/meta.json @@ -3,12 +3,13 @@ "language": "V", "type": "engine", "engine": "epoll", - "description": "HTTP/2 cleartext (h2c, prior-knowledge) on vanilla's conn-mode seam: one epoll engine drives the RFC 9113 state machine behind a ConnHandler. The client's PRI * HTTP/2.0 preface parses as an ordinary request; the HTTP handler flips the connection over (core.queue_takeover), appends the server SETTINGS preface, and every later burst is fed to the http2 machine instead of the HTTP/1.1 parser. The http2 module is a self-contained RFC 9113/7541 codec: HPACK (static + dynamic table, canonical Huffman decode, decoded-block ceiling), frame codec, and a stream state machine with send-side flow control, hardened against a live h2spec CI gate. Requests surface only when COMPLETE (END_STREAM); responses are HPACK-encoded HEADERS + DATA. The :8082 listener is h2c-only — a plain HTTP/1.1 request is refused 505, never a 200, so the benchmark cannot silently measure h1 throughput. /json reuses the vanilla /json shape (same dataset, precomputed per-item prefixes, total = price*quantity*m). Multi-threaded, SO_REUSEPORT, lock-free, -gc none. Pinned V 0.5.2 (prebuilt from source).", + "description": "HTTP/2 cleartext (h2c, prior-knowledge) on vanilla's conn-mode seam: one epoll engine drives the RFC 9113 state machine behind a ConnHandler. The client's PRI * HTTP/2.0 preface parses as an ordinary request; the HTTP handler flips the connection over (core.queue_takeover), appends the server SETTINGS preface, and every later burst is fed to the http2 machine instead of the HTTP/1.1 parser. The http2 module is a self-contained RFC 9113/7541 codec: HPACK (static + dynamic table, canonical Huffman decode, decoded-block ceiling), frame codec, and a stream state machine with send-side flow control, hardened against a live h2spec CI gate. Requests surface only when COMPLETE (END_STREAM); responses are HPACK-encoded HEADERS + DATA. The :8082 listener is h2c-only — a plain HTTP/1.1 request is refused 505, never a 200, so the benchmark cannot silently measure h1 throughput. /json reuses the vanilla /json shape (same dataset, precomputed per-item prefixes, total = price*quantity*m). unary-grpc runs on the same machine on :8080: GetSum decodes the length-prefixed SumRequest (a protobuf varint loop that skips unknown fields), answers HEADERS + the SumReply as DATA without END_STREAM, then grpc-status 0 as trailers, which wait behind any DATA parked on flow control (enghitalo/vanilla#174). Each connection reuses its request list and buffers; the gRPC header blocks are encoded once. Multi-threaded, SO_REUSEPORT, lock-free, -gc none. Pinned V 0.5.2 (prebuilt from source).", "repo": "https://github.com/enghitalo/vanilla", - "enabled": false, + "enabled": true, "tests": [ "baseline-h2c", - "json-h2c" + "json-h2c", + "unary-grpc" ], "maintainers": [ "enghitalo" diff --git a/frameworks/vanilla-io_uring/Dockerfile b/frameworks/vanilla-io_uring/Dockerfile index fbb365625..9e3d53928 100644 --- a/frameworks/vanilla-io_uring/Dockerfile +++ b/frameworks/vanilla-io_uring/Dockerfile @@ -6,39 +6,52 @@ RUN apt-get -qq update && \ cmake curl bzip2 python3 && \ rm -rf /var/lib/apt/lists/* -# Pinned, reproducible V at master commit 02015a7c (built from source). Master is -# now preferred over the 0.5.1 tag: the codegen regression that forced 0.5.1 (single- -# element array push 4-7x slower, vlang/v#27468) is fixed (vlang/v#27470), and the -# code uses the modern pooled Go-style db.pg (vlang/v#27265). 02015a7c descends from -# cef604a26, so it keeps the Boehm GC free-space-divisor fix (vlang/v#27560, fixes -# vlang/v#27555) that recovers the default-GC throughput regression seen in the -# c0624b2..6c4d26f range (verified ancestor; the c..02015a7c range adds no GC change). -# For a current master commit, `make` bootstraps via the matching vc; if a much later -# rebuild ever fails to bootstrap, pin vlang/vc to the commit cut for this V. -RUN git clone https://github.com/vlang/v /opt/v && \ - cd /opt/v && git checkout 02015a7ce111e4d0cfd5b5d78711ad0db7586936 && \ - make && ln -s /opt/v/v /usr/local/bin/v +# Pinned, reproducible V at master commit b99970bd (0.5.2, built from source). The +# removed `json` module is replaced by x.json2 in main.v (encode with +# escape_unicode, so the /json bodies stay byte-identical). +# +# The bootstrap is pinned too. A bare `make` clones vlang/vc and vlang/tccbin at +# their CURRENT heads, so a fixed V source gets built by whatever compiler vc +# holds that day: that is what broke every V entry in #1288 ("C function C.open +# was already declared with a different signature"), and vc head has since +# failed in other ways. vc 2cbaf6bc is vc's newest snapshot (generated from V +# 0c41fadb, 40 commits earlier; vc has none for b99970bd yet), so it is what +# `make` bootstraps this V with today; tccbin d6e7ac1b is the head of tccbin's +# thirdparty-linux-amd64 branch, and `local=1` makes `make` build with both +# instead of pulling. +# +# Each repo is fetched at its one pinned commit (depth 1) rather than cloned: +# a full clone of v, vc and tccbin is hundreds of MB and a slow or flaky link +# stalls it past the validator's timeout; this is ~30 MB. +RUN git init -q /opt/v && cd /opt/v && \ + git fetch -q --depth 1 https://github.com/vlang/v b99970bd438a7bdcdfbe38f74d9364db801d5439 && \ + git checkout -q FETCH_HEAD && \ + git init -q vc && \ + git -C vc fetch -q --depth 1 https://github.com/vlang/vc 2cbaf6bc2367937cd5f0b4ef923d1ef9aad613b3 && \ + git -C vc checkout -q FETCH_HEAD && \ + git init -q thirdparty/tcc && \ + git -C thirdparty/tcc fetch -q --depth 1 https://github.com/vlang/tccbin d6e7ac1b1bcc98aed734a6ecbfa8509f24606c74 && \ + git -C thirdparty/tcc checkout -q FETCH_HEAD && \ + make local=1 && ln -s /opt/v/v /usr/local/bin/v -# Install the vanilla HTTP server as the `vanilla` module (import vanilla.http_server), +# Install vanilla as the `vanilla` module (import vanilla.server, vanilla.core, ...), # pinned to a specific commit: reproducible, with NO per-build network call to detect # changes. The previous approach `ADD`ed the GitHub API main-ref URL to cache-bust when # main moved, but that hit api.github.com every build and a transient 504/rate-limit # failed the whole build (MDA2AV/HttpArena#895). Bump this commit to pick up lib fixes. # -# Pinned to vanilla main @be46940 — carries enghitalo/vanilla#99 (async runtime for -# the io_uring backend via oneshot IORING_OP_POLL_ADD), which this entry needs, and -# #101 (epoll async-runtime hardening — resume drains buffered pipelined requests, -# inline queue-drain deactivation, watch-then-reject teardown; the json-tls listener -# here runs on the epoll backend, stateless, so #101 is inert for this entry but keeps -# both entries on ONE lib SHA): main.v is now the vanilla-epoll entry's async_handler + pg_async code -# verbatim (DB queries PARK on the PG socket instead of blocking the ring worker — -# enghitalo/vanilla#83); an older pin REJECTS async_handler on io_uring at new_server() -# and panics on boot. Also carries #94 (make_state on io_uring), #96 (epoll TLS stateful -# fix), the lib-wide alloc audit (#72/#73/#74) and kTLS record offload (#79). The -# io_uring backend has no TLS, so the json-tls listener runs on the lib's epoll backend -# on :8081 (see main.v). -RUN git clone https://github.com/enghitalo/vanilla /root/.vmodules/vanilla && \ - git -C /root/.vmodules/vanilla checkout be46940b624363ed93991d3166f950143ee14c7b +# Pinned to vanilla main @091c014, the same commit as vanilla-epoll: one handler +# contract (core.Handler returning core.Step, watches through core.EventLoop) on +# both backends, so main.v is the vanilla-epoll code with the io_uring backend +# selected; DB queries PARK on the PG socket (oneshot IORING_OP_POLL_ADD) instead of +# blocking the ring worker. The io_uring backend has no TLS, so the json-tls, +# static-tls and 8gbit listener runs on the lib's epoll backend on :8081 with kTLS +# record offload and sendfile for static bodies (see main.v). Fetched at that one +# commit. +RUN git init -q /root/.vmodules/vanilla && \ + git -C /root/.vmodules/vanilla fetch -q --depth 1 https://github.com/enghitalo/vanilla \ + 091c014a0191afd7e740b84f5599b9b1fc1fd914 && \ + git -C /root/.vmodules/vanilla checkout -q FETCH_HEAD # Mbed TLS 4 for the json-tls profile (the epoll TLS listener on :8081). The vanilla # `tls` C shim (built with -d vanilla_tls) targets the Mbed TLS 4.x API; Debian apt @@ -46,15 +59,26 @@ RUN git clone https://github.com/enghitalo/vanilla /root/.vmodules/vanilla && \ # tarball into /usr/local. THREAD-SAFETY: enable MBEDTLS_THREADING_C + # MBEDTLS_THREADING_PTHREAD — the TLS workers share Mbed TLS's global PSA key store, # which races (heap-use-after-free) under concurrent handshakes without the mutex. +# +# mbedtls-rsa-sign-cache.patch (against 4.1.0): unpatched, every PSA RSA +# signature re-parses the key and regenerates the RSA blinding values from +# scratch, which was most of each TLS 1.3 handshake with the harness's +# RSA-2048 certificate (~11 ms of CPU). The patch keeps the signing key's +# parsed context in a per-thread cache, so blinding is updated by squaring +# as with any long-lived mbedtls_rsa_context; with -O3 -march=native a +# handshake costs ~8 ms. That is what 8gbit (512 fresh connections) and +# json-tls (4096) pay up front before the first request is answered. ARG MBEDTLS_VERSION=4.1.0 +COPY mbedtls-rsa-sign-cache.patch /tmp/ RUN curl -fsSL -o /tmp/mbedtls.tar.bz2 \ "https://github.com/Mbed-TLS/mbedtls/releases/download/mbedtls-${MBEDTLS_VERSION}/mbedtls-${MBEDTLS_VERSION}.tar.bz2" && \ tar -xf /tmp/mbedtls.tar.bz2 -C /tmp && \ cd "/tmp/mbedtls-${MBEDTLS_VERSION}" && \ + patch -p1 < /tmp/mbedtls-rsa-sign-cache.patch && \ python3 tf-psa-crypto/scripts/config.py set MBEDTLS_THREADING_C && \ python3 tf-psa-crypto/scripts/config.py set MBEDTLS_THREADING_PTHREAD && \ cmake -S "/tmp/mbedtls-${MBEDTLS_VERSION}" -B /tmp/mbedtls-build \ - -DCMAKE_BUILD_TYPE=Release \ + -DCMAKE_BUILD_TYPE=Release -DCMAKE_C_FLAGS_RELEASE="-O3 -march=native -DNDEBUG" \ -DUSE_SHARED_MBEDTLS_LIBRARY=On -DUSE_STATIC_MBEDTLS_LIBRARY=Off \ -DENABLE_TESTING=Off -DENABLE_PROGRAMS=Off \ -DCMAKE_INSTALL_PREFIX=/usr/local && \ @@ -86,4 +110,8 @@ COPY --from=build /app/server /server # backend). The harness bind-mounts the cert/key at /certs (override via # TLS_CERT/TLS_KEY); with no cert mounted the server self-signs. EXPOSE 8080 8081 -CMD ["/server"] +# One worker per CPU the container may run on. vanilla defaults to nr_cpus, +# which reads the host's online CPUs (128 on the bench box) and ignores the +# cpuset, so a 64-CPU profile started 128 workers and latency-500k-8cpu would +# start 128 on 8. nproc honours the cpuset; an explicit VANILLA_WORKERS wins. +CMD ["/bin/sh", "-c", "VANILLA_WORKERS=${VANILLA_WORKERS:-$(nproc)} exec /server"] diff --git a/frameworks/vanilla-io_uring/main.v b/frameworks/vanilla-io_uring/main.v index 550faf419..17809bfc5 100644 --- a/frameworks/vanilla-io_uring/main.v +++ b/frameworks/vanilla-io_uring/main.v @@ -1,16 +1,16 @@ module main -import vanilla.http_server -import vanilla.http_server.http1_1.request_parser -import vanilla.http_server.core -import vanilla.http_server.tls -import vanilla.http_server.static_assets +import vanilla.server +import vanilla.http1_1.request_parser +import vanilla.core +import vanilla.tls +import vanilla.static_assets import vanilla.pg_async -import json +import x.json2 as json import os -import runtime import strings import sync +import time import compress.gzip struct Rating { @@ -70,7 +70,10 @@ mut: crud []CrudSlot crud_mu &sync.RwMutex = unsafe { nil } gz map[u64][]u8 // json-comp: (count<<32)|m -> gzipped response bytes - gz_mu &sync.RwMutex = unsafe { nil } + // production-stack /api/me: user-id-indexed slab, same shape as `crud` + users []CrudSlot + users_mu &sync.RwMutex = unsafe { nil } + gz_mu &sync.RwMutex = unsafe { nil } } // CrudSlot is one entry of the id-indexed crud cache slab. `buf` is the rendered @@ -80,8 +83,9 @@ mut: // the next MISS to reuse (no time-based expiry — see the SharedRO.crud note). struct CrudSlot { mut: - buf []u8 - valid bool + buf []u8 + valid bool + expires u64 // time.sys_mono_now() deadline; a HIT needs now < expires } // crud GET/PUT ids are `{RAND:1:50000}`; index the slab directly (1..50000). Index 0 @@ -92,7 +96,21 @@ const crud_cache_slots = 50001 // so a slot's buffer, allocated once on first MISS, never reallocates. const crud_cache_bufcap = 512 -// WorkerCtx is the per-worker state handed to every handler call as ac.state +// Cache-aside TTLs for production-stack (the spec caps items at 1 s, users at +// 30 s). The same slab serves /crud/items, which keeps the 1 s item TTL. +const item_ttl_ns = u64(1_000_000_000) +const user_ttl_ns = u64(30_000_000_000) + +// /api/me ids index the users slab directly; the seed's ids are small, and an id +// past the slab is served uncached rather than growing it. +const user_cache_slots = 1024 + +// static_revalidate_ms: how often each static representation is re-checked against +// its file (one stat(2) per window, by the first request after it opens); 0 checks +// on every request. +const static_revalidate_ms = 100 + +// WorkerCtx is the per-worker state handed to every handler call as worker_state // (the make_state contract). Each worker owns its own async Postgres pool (no // lock); the caches live in the shared `ro` (mutex-guarded) so X-Cache hits // survive SO_REUSEPORT routing the two probe requests to different workers. @@ -119,7 +137,7 @@ mut: params_buf []?[]u8 // Reused Stash free-list: park() borrows a Stash here instead of heap-allocating one // per request; on_db_ready returns it on the terminal .done path only (NOT on the - // not-ready re-arm, where it stays live as the watch udata — incl. a FIX 3 dead + // not-ready re-arm, where it stays live as the watch payload — incl. a FIX 3 dead // tombstone that keeps it referenced until its orphaned reply drains). stash_pool []&Stash // Reused /fortunes row buffer: messages are BORROWED views into the Result frames @@ -131,6 +149,11 @@ mut: // was the /baseline11 chunked-POST leak (~6 GiB at 3.8M req/s in the arena // baseline mix). dechunk_buf []u8 + // Idle one-shot timerfds for /delay: start_delay pops one instead of calling + // timerfd_create, on_delay_elapsed pushes it back instead of closing it. A + // recycled fd is still registered with the worker's poller, so re-arming it + // costs a timerfd_settime and a re-watch rather than create + add + close. + timer_fds []int } // Stash is the per-request state that must survive across the park (the request @@ -150,6 +173,8 @@ const k_crud_get = u8(3) const k_crud_list = u8(4) const k_crud_create = u8(5) const k_crud_update = u8(6) +const k_api_update = u8(7) +const k_api_me = u8(8) // ── zero-alloc write helpers (push_many, never single-element `<<`) ────────── @@ -303,8 +328,8 @@ const service_unavailable = 'HTTP/1.1 503 Service Unavailable\r\nServer: vanilla // ── async handler ──────────────────────────────────────────────────────────── -fn handle(req_buffer []u8, mut out []u8, mut ac core.AsyncCtx) core.AsyncStep { - mut w := unsafe { &WorkerCtx(ac.state) } +fn handle(req_buffer []u8, mut out []u8, _ int, worker_state voidptr, mut event_loop core.EventLoop) core.Step { + mut w := unsafe { &WorkerCtx(worker_state) } // Skip-decode fast path: the fixed /pipeline plaintext (highest-RPS test) blits // its response before ANY parsing. The request is already framed by the caller, // so decode_into/parse_http1_request_line add nothing here (~17% of the request). @@ -331,6 +356,11 @@ fn handle(req_buffer []u8, mut out []u8, mut ac core.AsyncCtx) core.AsyncStep { } qpos := target.index_u8(`?`) route := if qpos < 0 { target } else { unsafe { tos(target.str, qpos) } } + // RFC 9112 §9.6: a request carrying the `close` connection option gets its + // final response and then the connection closes (.close flushes first). + // Only the synchronous routes below answer with `done`; the DB routes finish + // in their continuation. + done := if has_close_option(req) { core.Step.close } else { core.Step.done } if route == '/baseline11' { mut sum := qint(req, qk_a) + qint(req, qk_b) @@ -338,27 +368,37 @@ fn handle(req_buffer []u8, mut out []u8, mut ac core.AsyncCtx) core.AsyncStep { sum += w.body_int(req) } w.emit_int(mut out, 'text/plain', sum) - return .done + return done + } else if route == '/baseline2' { + // the gateway profiles' query-sum endpoint (GET only), behind the edge proxy + w.emit_int(mut out, 'text/plain', qint(req, qk_a) + qint(req, qk_b)) + return done + } else if route.starts_with('/api/items/') { + // production-stack: the edge verified the JWT; GET is cache-aside, POST writes + id := int(parse_u_at(route, 11)) + if method == 'POST' { + return w.start_api_update(mut out, mut event_loop, id, req) + } + return w.start_crud_get(mut out, mut event_loop, id) + } else if route == '/api/me' { + return w.start_api_me(mut out, mut event_loop, req) + } else if route == '/public/baseline' { + w.emit_int(mut out, 'text/plain', qint(req, qk_a) + qint(req, qk_b)) + return done + } else if route.starts_with('/public/json/') { + w.serve_json(mut out, req, parse_u_at(route, 13)) + return done } else if route == '/echo' { w.echo(mut out, req) - return .done + return done } else if route.starts_with('/json/') { - count := clamp_count(parse_u_at(route, 6), w.ro.dataset.len) - mut m := qint(req, qk_m) - if m == 0 { - m = 1 - } - if accepts_gzip(req) { - w.write_json_gzip(mut out, count, m) - } else { - w.write_json_response(mut out, count, m) - } - return .done + w.serve_json(mut out, req, parse_u_at(route, 6)) + return done } else if route == '/async-db' { - return w.start_async_db(mut out, mut ac, qint(req, qk_min), qint(req, qk_max), qint(req, + return w.start_async_db(mut out, mut event_loop, qint(req, qk_min), qint(req, qk_max), qint(req, qk_limit)) } else if route == '/fortunes' { - return w.start_fortunes(mut out, mut ac) + return w.start_fortunes(mut out, mut event_loop) } else if route.starts_with('/static/') { // Canonical static serving via the lib's static_assets module: negotiates the // precompressed .br/.gz sibling per Accept-Encoding (the arena sends @@ -367,29 +407,40 @@ fn handle(req_buffer []u8, mut out []u8, mut ac core.AsyncCtx) core.AsyncStep { // ONE audited implementation instead of a second hand-rolled identity-only // path that ignored Accept-Encoding. Mounted at /static/; emits via the same // core.queue_file sendfile handoff the worker already drains. - w.ro.asv.respond_into(req_buffer, mut out) or { wb(mut out, not_found) } - return .done + w.ro.asv.respond_req_into(&req, mut out) + return done } else if route == '/crud/items' { if method == 'POST' { - return w.start_crud_create(mut out, mut ac, req) + return w.start_crud_create(mut out, mut event_loop, req) } - return w.start_crud_list(mut out, mut ac, qstr_slice(req, qk_category), qint(req, qk_page), + return w.start_crud_list(mut out, mut event_loop, qstr_slice(req, qk_category), qint(req, qk_page), qint(req, qk_limit)) } else if route.starts_with('/crud/items/') { id := int(parse_u_at(route, 12)) if method == 'PUT' { - return w.start_crud_update(mut out, mut ac, id, req) + return w.start_crud_update(mut out, mut event_loop, id, req) + } + return w.start_crud_get(mut out, mut event_loop, id) + } else if route.starts_with('/delay/') { + ms := parse_delay_ms(route) + if ms < 0 { + wb(mut out, not_found) + return done } - return w.start_crud_get(mut out, mut ac, id) + if ms == 0 { + w.emit_int(mut out, 'text/plain', 0) + return done + } + return w.start_delay(mut out, mut event_loop, ms) } wb(mut out, not_found) - return .done + return done } // park submits a query and parks the request on its connection, stashing the // render kind (+ id/page for the routes that need them) for the continuation. // On a pool/flush failure it answers synchronously with `fallback`. -fn (mut w WorkerCtx) park(mut out []u8, mut ac core.AsyncCtx, query_text string, params []?[]u8, kind u8, id int, page i64, fallback []u8) core.AsyncStep { +fn (mut w WorkerCtx) park(mut out []u8, mut event_loop core.EventLoop, query_text string, params []?[]u8, kind u8, id int, page i64, fallback []u8) core.Step { // Pick the least-loaded connection (shortest pipeline). Cross-request // pipelining: a connection multiplexes up to max_inflight queries, so we shed // only when every connection is at the cap — not when a connection is merely @@ -431,18 +482,19 @@ fn (mut w WorkerCtx) park(mut out []u8, mut ac core.AsyncCtx, query_text string, // One watch per parked request on the connection's fd. When several requests // share a connection the reactor auto-promotes the fd to a FIFO queue and fans // each reply out in submission order (queue[k] ↔ the connection's inflight[k]). - // watch_persistent: the fd is a POOLED connection — if this client disconnects + // watch_fd_persistent: the fd is a POOLED connection — if this client disconnects // mid-query the runtime must drain the orphaned reply and keep the connection // open for reuse, never close it (a close would force a reconnect + re-auth). - ac.watch_persistent(w.pool.fd(idx), .readable, on_db_ready, voidptr(st)) + event_loop.watch_fd_persistent(w.pool.fd(idx), .readable, on_db_ready, voidptr(st)) return .suspend } // on_db_ready resumes a parked request when its PG socket is readable: pump the -// result, render by kind, release the connection. -fn on_db_ready(mut out []u8, mut ac core.AsyncCtx) core.AsyncStep { - mut w := unsafe { &WorkerCtx(ac.state) } - st := unsafe { &Stash(ac.udata) } +// result, render by kind, release the connection. The ready fd and its error flag +// go unused: st.conn_idx already names the connection. +fn on_db_ready(mut out []u8, _ int, _ bool, watch_payload voidptr, worker_state voidptr, mut event_loop core.EventLoop) core.Step { + mut w := unsafe { &WorkerCtx(worker_state) } + st := unsafe { &Stash(watch_payload) } mut c := w.pool.conn(st.conn_idx) // async_on_readable pops THIS request's reply: the reactor runs the connection's // parked requests front-first and replies arrive in submit order, so the FIFO @@ -455,11 +507,12 @@ fn on_db_ready(mut out []u8, mut ac core.AsyncCtx) core.AsyncStep { } if !poll.ready { // Re-arm persistent: the single-watch path clears the slot before running this - // continuation, so the re-arm is a fresh entry — watch_persistent re-stamps the - // pool-owned flag that a plain watch would drop. (more bytes to come) - // NOTE: do NOT recycle st here — it stays live as the watch udata (incl. a FIX 3 + // continuation, so the re-arm is a fresh entry — watch_fd_persistent re-stamps the + // pool-owned flag that a plain watch_fd would drop. (more bytes to come) + // NOTE: do NOT recycle st here — it stays live as the watch payload (incl. a FIX 3 // dead tombstone) until the reply completes on a later edge. - ac.watch_persistent(w.pool.fd(st.conn_idx), .readable, on_db_ready, ac.udata) + event_loop.watch_fd_persistent(w.pool.fd(st.conn_idx), .readable, on_db_ready, + watch_payload) return .suspend } res := poll.result @@ -470,6 +523,8 @@ fn on_db_ready(mut out []u8, mut ac core.AsyncCtx) core.AsyncStep { k_crud_list { w.render_crud_list(mut out, res, st.page) } k_crud_create { wb(mut out, created) } k_crud_update { w.render_crud_update(mut out, st.id) } + k_api_update { w.render_api_update(mut out, st.id) } + k_api_me { w.render_api_me(mut out, res, st.id) } else { wb(mut out, not_found) } } // No release: a pipelined connection is not held exclusively. Its in-flight @@ -481,7 +536,7 @@ fn on_db_ready(mut out []u8, mut ac core.AsyncCtx) core.AsyncStep { // return_stash recycles a finished request's Stash onto the per-worker free-list. Call // ONLY on a terminal .done path — never on the .suspend re-arm, where st stays live as -// the watch udata. Bounded so a burst doesn't grow the list without limit. +// the watch payload. Bounded so a burst doesn't grow the list without limit. @[inline] fn (mut w WorkerCtx) return_stash(st &Stash) { if w.stash_pool.len < 64 { @@ -489,6 +544,208 @@ fn (mut w WorkerCtx) return_stash(st &Stash) { } } +// ── /delay/{ms} (async profile) ───────────────────────────────────────────── + +#include + +fn C.timerfd_create(clockid int, flags int) int +fn C.timerfd_settime(fd int, flags int, new_value voidptr, old_value voidptr) int + +// timer_pool_max bounds a worker's free-list of idle timerfds. The profile holds +// ~32000/workers requests in flight per worker; past the bound a finished timer +// is closed instead of kept. +const timer_pool_max = 4096 + +// parse_delay_ms reads {ms} from `/delay/{ms}`: 1-9 decimal digits and nothing +// after them. Anything else is -1 (404). +@[direct_array_access] +fn parse_delay_ms(route string) i64 { + start := '/delay/'.len + if route.len == start || route.len - start > 9 { + return -1 + } + mut n := i64(0) + for i := start; i < route.len; i++ { + c := route[i] + if c < `0` || c > `9` { + return -1 + } + n = n * 10 + i64(c - `0`) + } + return n +} + +// start_delay parks the request on a one-shot timerfd armed for `ms`; the worker +// keeps serving its other connections and on_delay_elapsed answers when the +// timer fires. The delay rides along as the watch payload. +fn (mut w WorkerCtx) start_delay(mut out []u8, mut event_loop core.EventLoop, ms i64) core.Step { + mut tfd := -1 + if w.timer_fds.len > 0 { + tfd = w.timer_fds.pop() + } else { + tfd = C.timerfd_create(C.CLOCK_MONOTONIC, C.TFD_NONBLOCK | C.TFD_CLOEXEC) + if tfd < 0 { + wb(mut out, service_unavailable) + return .done + } + } + // struct itimerspec: it_interval {sec, nsec} = 0 (one-shot), it_value {sec, nsec} + mut spec := [4]i64{} + spec[2] = ms / 1000 + spec[3] = (ms % 1000) * 1_000_000 + if C.timerfd_settime(tfd, 0, unsafe { voidptr(&spec[0]) }, unsafe { nil }) != 0 { + C.close(tfd) + wb(mut out, service_unavailable) + return .done + } + event_loop.watch_fd(tfd, .readable, on_delay_elapsed, voidptr(usize(ms))) + return .suspend +} + +// on_delay_elapsed answers a parked /delay request. It only answers once the +// timerfd reports an expiration: a wake without one (a stale io_uring poll +// completion for a closed fd whose number was reused, say) re-arms and keeps +// waiting, so no response can leave before its delay has elapsed. +fn on_delay_elapsed(mut out []u8, ready_fd int, ready_fd_error bool, watch_payload voidptr, worker_state voidptr, mut event_loop core.EventLoop) core.Step { + mut w := unsafe { &WorkerCtx(worker_state) } + tfd := ready_fd + mut expirations := u64(0) + if C.read(tfd, &expirations, 8) != 8 { + if ready_fd_error { + C.close(tfd) + wb(mut out, service_unavailable) + return .done + } + event_loop.watch_fd(tfd, .readable, on_delay_elapsed, watch_payload) + return .suspend + } + if w.timer_fds.len < timer_pool_max { + w.timer_fds << tfd + } else { + C.close(tfd) + } + w.emit_int(mut out, 'text/plain', i64(usize(watch_payload))) + return .done +} + +// serve_json answers /json/{count} (and production-stack's /public/json/{count}): +// gzip from the lazy per-(count, m) cache when the client accepts it. +fn (mut w WorkerCtx) serve_json(mut out []u8, req request_parser.HttpRequest, n i64) { + count := clamp_count(n, w.ro.dataset.len) + mut m := qint(req, qk_m) + if m == 0 { + m = 1 + } + if accepts_gzip(req) { + w.write_json_gzip(mut out, count, m) + } else { + w.write_json_response(mut out, count, m) + } +} + +// ── production-stack /api (behind the edge's JWT auth_request) ────────────── + +const no_content = 'HTTP/1.1 204 No Content\r\nServer: vanilla\r\nConnection: keep-alive\r\n\r\n'.bytes() + +const unauthorized = 'HTTP/1.1 401 Unauthorized\r\nServer: vanilla\r\nContent-Length: 0\r\nConnection: keep-alive\r\n\r\n'.bytes() + +// start_api_update is POST /api/items/{id}: {"name","price","quantity"} parsed in +// place (borrowed views, no allocation), UPDATE, then render_api_update drops the +// cached item and answers 204. +fn (mut w WorkerCtx) start_api_update(mut out []u8, mut event_loop core.EventLoop, id int, req request_parser.HttpRequest) core.Step { + body := unsafe { req.buffer[req.body.start..req.body.start + req.body.len] } + name := json_string_field_borrowed(body, '"name"') or { + wb(mut out, bad_request) + return .done + } + price := json_i64_field(body, '"price"') or { + wb(mut out, bad_request) + return .done + } + quantity := json_i64_field(body, '"quantity"') or { + wb(mut out, bad_request) + return .done + } + w.reset_params() + w.push_int(i64(id)) + w.push_bytes(name) + w.push_int(price) + w.push_int(quantity) + return w.park(mut out, mut event_loop, 'UPDATE items SET name = \$2, price = \$3, quantity = \$4 WHERE id = \$1', + w.params_buf, k_api_update, id, 0, service_unavailable) +} + +fn (mut w WorkerCtx) render_api_update(mut out []u8, id int) { + // invalidate after the write, so the next GET re-reads the updated row + if id >= 1 && id < crud_cache_slots { + w.ro.crud_mu.@lock() + w.ro.crud[id].valid = false + w.ro.crud_mu.unlock() + } + wb(mut out, no_content) +} + +// start_api_me is GET /api/me: cache-aside on the user named by the edge's +// X-User-Id (set from the verified JWT), 30 s TTL. +fn (mut w WorkerCtx) start_api_me(mut out []u8, mut event_loop core.EventLoop, req request_parser.HttpRequest) core.Step { + uid := req.get_header_value_slice('X-User-Id') or { + wb(mut out, unauthorized) + return .done + } + id := int(parse_u_at(unsafe { tos(&req.buffer[uid.start], uid.len) }, 0)) + if id >= 1 && id < user_cache_slots { + now := time.sys_mono_now() + mut hit := false + w.ro.users_mu.@rlock() + s := w.ro.users[id] + if s.valid && s.buf.len > 0 && now < s.expires { + unsafe { w.scratch.len = 0 } + w.scratch << s.buf + hit = true + } + w.ro.users_mu.runlock() + if hit { + emit_xcache(mut out, 'application/json', w.scratch, 'HIT') + return .done + } + } + w.reset_params() + w.push_int(i64(id)) + return w.park(mut out, mut event_loop, 'SELECT id, name, email, plan FROM users WHERE id = \$1', + w.params_buf, k_api_me, id, 0, service_unavailable) +} + +fn (mut w WorkerCtx) render_api_me(mut out []u8, res pg_async.Result, id int) { + mut rows := res.rows() + row := rows.next() or { + wb(mut out, not_found) + return + } + unsafe { w.scratch.len = 0 } + ws(mut w.scratch, '{"id":') + wi(mut w.scratch, i64(row.int4(0) or { 0 })) + ws(mut w.scratch, ',"name":"') + ws_json_str(mut w.scratch, row.text(1) or { ''.bytes() }) + ws(mut w.scratch, '","email":"') + ws_json_str(mut w.scratch, row.text(2) or { ''.bytes() }) + ws(mut w.scratch, '","plan":"') + ws_json_str(mut w.scratch, row.text(3) or { ''.bytes() }) + ws(mut w.scratch, '"}') + if id >= 1 && id < user_cache_slots { + w.ro.users_mu.@lock() + mut slot := &w.ro.users[id] + if slot.buf.cap == 0 { + slot.buf = []u8{cap: crud_cache_bufcap} + } + unsafe { slot.buf.len = 0 } + slot.buf << w.scratch + slot.valid = true + slot.expires = time.sys_mono_now() + user_ttl_ns + w.ro.users_mu.unlock() + } + emit_xcache(mut out, 'application/json', w.scratch, 'MISS') +} + fn (w &WorkerCtx) render_error(mut out []u8, kind u8) { match kind { k_async_db { @@ -504,6 +761,9 @@ fn (w &WorkerCtx) render_error(mut out []u8, kind u8) { k_crud_get { wb(mut out, not_found) } + k_api_update, k_api_me { + wb(mut out, service_unavailable) + } else { wb(mut out, bad_request) } @@ -549,7 +809,7 @@ const fortunes_fallback = '
idmessage
Fortunes') @@ -650,17 +910,33 @@ fn (mut w WorkerCtx) render_fortunes(mut out []u8, res pg_async.Result) { emit(mut out, 'text/html; charset=utf-8', w.scratch) } -// cmp_fortune_message orders fortunes by message, lexicographically by bytes — V has no -// `<` on []u8, so the sort needs an explicit comparator (returns <0 / 0 / >0). -fn cmp_fortune_message(a &Fortune, b &Fortune) int { +fn C.qsort(base voidptr, nmemb usize, size usize, compar voidptr) + +// sort_fortunes orders the ~200 rows by message with libc qsort. sort_with_compare is a +// merge sort whose scratch copy comes from V's malloc, which on a GC build is the +// collector's allocator (and under -gc none a V allocation that must be freed by +// hand); qsort's scratch, when it needs one, comes from libc malloc and is freed +// inside the call, so the per-request sort never touches the GC heap. +fn sort_fortunes(mut a []Fortune) { + C.qsort(a.data, usize(a.len), sizeof(Fortune), voidptr(cmp_fortune)) +} + +fn cmp_fortune(a &Fortune, b &Fortune) int { + return cmp_message(a.message, b.message) +} + +// cmp_message orders messages lexicographically by bytes — V has no `<` on []u8 +// (returns <0 / 0 / >0). +@[direct_array_access] +fn cmp_message(a []u8, b []u8) int { mut i := 0 - for i < a.message.len && i < b.message.len { - if a.message[i] != b.message[i] { - return int(a.message[i]) - int(b.message[i]) + for i < a.len && i < b.len { + if a[i] != b[i] { + return int(a[i]) - int(b[i]) } i++ } - return a.message.len - b.message.len + return a.len - b.len } // ── /crud ──────────────────────────────────────────────────────────────────── @@ -669,7 +945,7 @@ fn cmp_fortune_message(a &Fortune, b &Fortune) int { // the total come back together — one park instead of two queries. const crud_list_sql = 'SELECT id, name, category, price, quantity, active, tags, rating_score, rating_count, count(*) OVER() FROM items WHERE category = \$1 ORDER BY id LIMIT \$2 OFFSET \$3' -fn (mut w WorkerCtx) start_crud_list(mut out []u8, mut ac core.AsyncCtx, category []u8, page i64, limit i64) core.AsyncStep { +fn (mut w WorkerCtx) start_crud_list(mut out []u8, mut event_loop core.EventLoop, category []u8, page i64, limit i64) core.Step { mut p := page if p < 1 { p = 1 @@ -686,7 +962,7 @@ fn (mut w WorkerCtx) start_crud_list(mut out []u8, mut ac core.AsyncCtx, categor w.push_bytes(category) // borrowed view into the request buffer (qstr_slice) w.push_int(lim) w.push_int(offset) - return w.park(mut out, mut ac, crud_list_sql, w.params_buf, k_crud_list, 0, p, crud_list_fallback) + return w.park(mut out, mut event_loop, crud_list_sql, w.params_buf, k_crud_list, 0, p, crud_list_fallback) } fn (mut w WorkerCtx) render_crud_list(mut out []u8, res pg_async.Result, page i64) { @@ -712,16 +988,17 @@ fn (mut w WorkerCtx) render_crud_list(mut out []u8, res pg_async.Result, page i6 emit(mut out, 'application/json', w.scratch) } -fn (mut w WorkerCtx) start_crud_get(mut out []u8, mut ac core.AsyncCtx, id int) core.AsyncStep { +fn (mut w WorkerCtx) start_crud_get(mut out []u8, mut event_loop core.EventLoop, id int) core.Step { // Cache-aside lookup against the id-indexed slab. Snapshot the cached body into // the per-worker scratch UNDER the read-lock, then build the response unlocked: // the slot buffer is reused in place, so a bare ref must not outlive the lock (a // concurrent MISS-refill would mutate it). The read-lock hold is one memcpy. mut hit := false if id >= 1 && id < crud_cache_slots { + now := time.sys_mono_now() w.ro.crud_mu.@rlock() s := w.ro.crud[id] - if s.valid && s.buf.len > 0 { + if s.valid && s.buf.len > 0 && now < s.expires { unsafe { w.scratch.len = 0 } w.scratch << s.buf hit = true @@ -735,7 +1012,7 @@ fn (mut w WorkerCtx) start_crud_get(mut out []u8, mut ac core.AsyncCtx, id int) } w.reset_params() w.push_int(i64(id)) - return w.park(mut out, mut ac, + return w.park(mut out, mut event_loop, 'SELECT id, name, category, price, quantity, active, tags, rating_score, rating_count FROM items WHERE id = \$1', w.params_buf, k_crud_get, id, 0, service_unavailable) } @@ -766,12 +1043,13 @@ fn (mut w WorkerCtx) render_crud_get(mut out []u8, res pg_async.Result, id int) unsafe { slot.buf.len = 0 } slot.buf << w.scratch slot.valid = true + slot.expires = time.sys_mono_now() + item_ttl_ns w.ro.crud_mu.unlock() } emit_xcache(mut out, 'application/json', w.scratch, 'MISS') } -fn (mut w WorkerCtx) start_crud_create(mut out []u8, mut ac core.AsyncCtx, req request_parser.HttpRequest) core.AsyncStep { +fn (mut w WorkerCtx) start_crud_create(mut out []u8, mut event_loop core.EventLoop, req request_parser.HttpRequest) core.Step { body := unsafe { req.buffer[req.body.start..req.body.start + req.body.len] } if c := parse_crud_body_fast(body, true) { w.reset_params() @@ -780,12 +1058,12 @@ fn (mut w WorkerCtx) start_crud_create(mut out []u8, mut ac core.AsyncCtx, req r w.push_bytes(c.category) w.push_int(c.price) w.push_int(c.quantity) - return w.park(mut out, mut ac, + return w.park(mut out, mut event_loop, "INSERT INTO items (id, name, category, price, quantity, active, tags, rating_score, rating_count) VALUES (\$1, \$2, \$3, \$4, \$5, true, '[]', 0, 0) ON CONFLICT (id) DO UPDATE SET name = EXCLUDED.name, category = EXCLUDED.category, price = EXCLUDED.price, quantity = EXCLUDED.quantity", w.params_buf, k_crud_create, 0, 0, service_unavailable) } raw := unsafe { tos(&req.buffer[req.body.start], req.body.len) } - c := json.decode(CrudCreate, raw) or { + c := json.decode[CrudCreate](raw) or { wb(mut out, bad_request) return .done } @@ -795,12 +1073,12 @@ fn (mut w WorkerCtx) start_crud_create(mut out []u8, mut ac core.AsyncCtx, req r w.push_bytes(unsafe { c.category.str.vbytes(c.category.len) }) w.push_int(i64(c.price)) w.push_int(i64(c.quantity)) - return w.park(mut out, mut ac, + return w.park(mut out, mut event_loop, "INSERT INTO items (id, name, category, price, quantity, active, tags, rating_score, rating_count) VALUES (\$1, \$2, \$3, \$4, \$5, true, '[]', 0, 0) ON CONFLICT (id) DO UPDATE SET name = EXCLUDED.name, category = EXCLUDED.category, price = EXCLUDED.price, quantity = EXCLUDED.quantity", w.params_buf, k_crud_create, 0, 0, service_unavailable) } -fn (mut w WorkerCtx) start_crud_update(mut out []u8, mut ac core.AsyncCtx, id int, req request_parser.HttpRequest) core.AsyncStep { +fn (mut w WorkerCtx) start_crud_update(mut out []u8, mut event_loop core.EventLoop, id int, req request_parser.HttpRequest) core.Step { body := unsafe { req.buffer[req.body.start..req.body.start + req.body.len] } if c := parse_crud_body_fast(body, false) { w.reset_params() @@ -809,12 +1087,12 @@ fn (mut w WorkerCtx) start_crud_update(mut out []u8, mut ac core.AsyncCtx, id in w.push_bytes(c.category) w.push_int(c.price) w.push_int(c.quantity) - return w.park(mut out, mut ac, + return w.park(mut out, mut event_loop, 'UPDATE items SET name = \$2, category = \$3, price = \$4, quantity = \$5 WHERE id = \$1', w.params_buf, k_crud_update, id, 0, service_unavailable) } raw := unsafe { tos(&req.buffer[req.body.start], req.body.len) } - c := json.decode(CrudCreate, raw) or { + c := json.decode[CrudCreate](raw) or { wb(mut out, bad_request) return .done } @@ -824,7 +1102,7 @@ fn (mut w WorkerCtx) start_crud_update(mut out []u8, mut ac core.AsyncCtx, id in w.push_bytes(unsafe { c.category.str.vbytes(c.category.len) }) w.push_int(i64(c.price)) w.push_int(i64(c.quantity)) - return w.park(mut out, mut ac, + return w.park(mut out, mut event_loop, 'UPDATE items SET name = \$2, category = \$3, price = \$4, quantity = \$5 WHERE id = \$1', w.params_buf, k_crud_update, id, 0, service_unavailable) } @@ -845,8 +1123,8 @@ fn (mut w WorkerCtx) render_crud_update(mut out []u8, id int) { // write_json_into is the transport-agnostic /json serializer: it only APPENDS // response bytes to `out`, so the plaintext path (via WorkerCtx) and the json-tls -// path (a stateless TLS handler) share it verbatim. `ro` is read-only and nothing -// per-request is heap-allocated. Content-Length is precomputed from the SAME +// path (the TLS listener's handler, which gets its TlsWorker as worker_state) +// share it verbatim. `ro` is read-only and nothing per-request is heap-allocated. Content-Length is precomputed from the SAME // values the body emits, so the framed length can never desync from the body // (no response-splitting / smuggling surface). fn write_json_into(ro &SharedRO, mut out []u8, count int, m i64) { @@ -949,12 +1227,18 @@ fn (w &WorkerCtx) json_body(count int, m i64) string { // the bytes that actually arrived, never from Content-Length, which a chunked // POST does not carry at all. fn (mut w WorkerCtx) echo(mut out []u8, req request_parser.HttpRequest) { + echo_into(mut out, req, mut w.dechunk_buf) +} + +// echo_into is /echo for both listeners (plaintext :8080 and the 8gbit TLS +// listener on :8081); `scratch` is the caller's reused dechunk buffer. +fn echo_into(mut out []u8, req request_parser.HttpRequest, mut scratch []u8) { if te := req.get_header_value_slice('Transfer-Encoding') { val := unsafe { tos(&req.buffer[te.start], te.len) } if val.contains('chunked') { - unsafe { w.dechunk_buf.len = 0 } - dechunk_into(mut w.dechunk_buf, req.buffer, req.body.start, req.body.len) - emit(mut out, 'application/octet-stream', w.dechunk_buf) + unsafe { scratch.len = 0 } + dechunk_into(mut scratch, req.buffer, req.body.start, req.body.len) + emit(mut out, 'application/octet-stream', scratch) return } } @@ -1156,6 +1440,35 @@ fn parse_hex_slice(buf []u8, start int, length int) int { return int(n) } +// is_token_sep: the bytes that can border a token in a Connection list. +@[inline] +fn is_token_sep(c u8) bool { + return c == `,` || c == ` ` || c == `\t` +} + +// has_close_option reports whether the Connection header lists the `close` +// option: a case-insensitive token in a comma-separated list (RFC 9110 §7.6.1), +// matched in place without allocating (this binary may run -gc none). +@[direct_array_access] +fn has_close_option(req request_parser.HttpRequest) bool { + c := req.get_header_value_slice('Connection') or { return false } + end := c.start + c.len + mut i := c.start + for i + 5 <= end { + if (req.buffer[i] | 0x20) == `c` && (req.buffer[i + 1] | 0x20) == `l` + && (req.buffer[i + 2] | 0x20) == `o` && (req.buffer[i + 3] | 0x20) == `s` + && (req.buffer[i + 4] | 0x20) == `e` { + before := i == c.start || is_token_sep(req.buffer[i - 1]) + after := i + 5 == end || is_token_sep(req.buffer[i + 5]) + if before && after { + return true + } + } + i++ + } + return false +} + fn accepts_gzip(req request_parser.HttpRequest) bool { ae := req.get_header_value_slice('Accept-Encoding') or { return false } return unsafe { tos(&req.buffer[ae.start], ae.len) }.contains('gzip') @@ -1297,6 +1610,20 @@ fn parse_db_url(u string) pg_async.ConnConfig { } } +// TlsWorker is the per-worker state of the TLS listener: the reused dechunk +// buffer /echo needs for a chunked body (a per-request buffer would leak +// under -gc none). +struct TlsWorker { +mut: + dechunk_buf []u8 +} + +fn new_tls_worker() voidptr { + return &TlsWorker{ + dechunk_buf: []u8{cap: 16384} + } +} + // load_tls_config builds the json-tls server's TLS config. It reads the cert/key // the HttpArena harness bind-mounts at /certs (overridable via TLS_CERT/TLS_KEY). // If NO cert is mounted (local dev), it falls back to a fresh self-signed cert — @@ -1304,6 +1631,24 @@ fn parse_db_url(u string) pg_async.ConnConfig { // cert IS present but the key is missing/unreadable, it FAILS LOUDLY rather than // silently self-signing, so a real misconfiguration can't slip through as "works // but with the wrong identity". TLS 1.3 + ALPN http/1.1 are fixed by the tls shim. +// connect_pool brings up a worker's pool, retrying for up to 30 s while +// Postgres refuses connections. The postgres image answers pg_isready and psql +// over its unix socket while the init-time server is still up, then restarts +// to listen on TCP, so a server started right after "ready" can meet a refused +// connect for a moment. +fn connect_pool(cfg pg_async.ConnConfig, size int) &pg_async.PgPool { + mut last := '' + for _ in 0 .. 150 { + if pool := pg_async.new_pool(cfg, size) { + return pool + } else { + last = err.msg() + } + time.sleep(200 * time.millisecond) + } + panic('vanilla-io_uring: pg pool bring-up failed: ${last}') +} + fn load_tls_config() &tls.Config { cert_path := os.getenv_opt('TLS_CERT') or { '/certs/server.crt' } key_path := os.getenv_opt('TLS_KEY') or { '/certs/server.key' } @@ -1338,7 +1683,10 @@ fn main() { if total < 1 { total = 64 } - workers := runtime.nr_cpus() + // Same count the server starts with (VANILLA_WORKERS, which the image sets from + // the container's cpuset; nr_cpus otherwise), so the budget splits across the + // workers that actually run rather than the host's CPU count. + workers := core.max_thread_pool_size mut per_worker := total / workers if per_worker < 1 { per_worker = 1 @@ -1346,30 +1694,39 @@ fn main() { dataset_path := os.getenv_opt('DATASET_PATH') or { '/data/dataset.json' } dataset_raw := os.read_file(dataset_path) or { '[]' } - dataset := json.decode([]DatasetItem, dataset_raw) or { []DatasetItem{} } + dataset := json.decode[[]DatasetItem](dataset_raw) or { []DatasetItem{} } mut prefixes := []string{cap: dataset.len} for it in dataset { - enc := json.encode(it) + // escape_unicode: the byte-exact output of the removed `json` module's encode + // (non-ASCII as \uXXXX), so the /json bodies don't change with the toolchain. + enc := json.encode(it, escape_unicode: true) prefixes << enc#[..-1] + ',"total":' } static_dir := os.getenv_opt('STATIC_DIR') or { '/data/static' } - // Canonical static server: loads every asset PLUS its .br/.gz siblings once, mounts - // them at /static/, and negotiates Accept-Encoding per request, emitting via - // core.queue_buf (borrowed send of the preloaded bytes). - // - // Do NOT set sendfile_min_bytes here (unlike the epoll twin, which uses 16 KiB): the - // io_uring backend has NO sendfile path (no core.enable_sendfile / queue_file drain), - // so static_assets.respond_into would fall back to READING a "large" asset's body - // from disk on every request — a blocking read that stalls the ring. Keeping the - // default (256 KiB) preloads every arena .br/.gz sibling (all < 256 KiB) and serves - // them as a zero-copy borrowed send. (Measured: 16 KiB here collapsed static ~-86% to - // -99% — the large .br siblings hit the read-per-request fallback.) + // Canonical static server, mounted at /static/ on both listeners: negotiates the + // precompressed .br/.gz sibling per Accept-Encoding (the arena sends + // `br;q=1, gzip;q=0.8`), with ETag/Vary/Cache-Control. spa_fallback is off: the + // arena fixture set has no SPA entrypoint. + // follow_disk: the cache follows the disk (engine rule: replace a file and the + // next response carries the new bytes). Each representation is an immutable + // snapshot re-checked with one stat(2) per REVALIDATE window and rebuilt when + // the file's (dev, ino, size, mtime, ctime) changed. + // sendfile_min_bytes: representations >= 16 KiB keep an fd and go out with + // sendfile(2) where the worker can hand them off: the plain epoll worker and + // kTLS connections on :8081 (the kernel encrypts the pages). + // memory_fallback: those representations keep their bytes in RAM too, so a + // worker that cannot sendfile them (io_uring's borrowed send, a userspace-TLS + // connection) sends from memory instead of reading the file per request. asv := static_assets.new(static_assets.Config{ - root: static_dir - url_prefix: '/static/' - spa_fallback: '' + root: static_dir + url_prefix: '/static/' + spa_fallback: '' + sendfile_min_bytes: 16 * 1024 + memory_fallback: true + follow_disk: true + revalidate_ms: static_revalidate_ms }) or { panic('vanilla-io_uring: static_assets init failed: ${err}') } ro := &SharedRO{ @@ -1378,30 +1735,46 @@ fn main() { asv: asv crud: []CrudSlot{len: crud_cache_slots} crud_mu: sync.new_rwmutex() + users: []CrudSlot{len: user_cache_slots} + users_mu: sync.new_rwmutex() gz: map[u64][]u8{} gz_mu: sync.new_rwmutex() } // ── json-tls profile: /json over HTTPS on :8081 via the epoll + kTLS backend ── // The lib's io_uring backend has no TLS, so the json-tls listener runs on the - // epoll backend (a SECOND server anyway, because tls_config is server-wide). It serves ONLY /json - // (404 for everything else) so the TLS port exposes the minimal surface the - // profile needs — no /static, /echo, /crud or DB routes. The handler is a - // STATELESS request_handler (no make_state, sidestepping the TLS worker's - // stateful path) capturing the read-only `ro`; it reuses write_json_into - // verbatim, so the bytes are identical to the plaintext /json. Mbed TLS 1.3, - // ALPN http/1.1 (set by the tls shim) → curl --http1.1 negotiates 1.1. - tls_handler := fn [ro] (req_buffer []u8, fd int, mut out []u8) ! { + // epoll backend (a SECOND server anyway, because tls_config is server-wide). It serves ONLY /json, + // /echo and /static (404 for everything else) so the TLS port exposes the minimal + // surface the json-tls, 8gbit and static-tls profiles need — no /crud or DB + // routes. On a kTLS connection a /static body of 16 KiB or more goes out with + // sendfile(2), headers coalesced into its first record; on a userspace-TLS + // connection it is sent from memory (memory_fallback). The + // handler captures the read-only `ro` and gets its TlsWorker (the /echo dechunk + // buffer) as worker_state from make_state. It must stay synchronous (.done): the + // TLS worker has no watch reactor, so a .suspend would drop the connection. It + // reuses write_json_into verbatim, so the bytes are identical to the plaintext + // /json. Mbed TLS 1.3, ALPN http/1.1 (set by the tls shim) → curl --http1.1 + // negotiates 1.1. + tls_handler := fn [ro] (req_buffer []u8, mut out []u8, client_fd int, worker_state voidptr, mut event_loop core.EventLoop) core.Step { + mut tw := unsafe { &TlsWorker(worker_state) } mut req := request_parser.HttpRequest{ buffer: req_buffer } if !request_parser.decode_into(mut req) { wb(mut out, bad_request) - return + return .done } target := unsafe { tos(&req.buffer[req.path.start], req.path.len) } qpos := target.index_u8(`?`) route := if qpos < 0 { target } else { unsafe { tos(target.str, qpos) } } + if route.starts_with('/static/') { + ro.asv.respond_req_into(&req, mut out) + return .done + } + if route == '/echo' { + echo_into(mut out, req, mut tw.dechunk_buf) + return .done + } if route.starts_with('/json/') { count := clamp_count(parse_u_at(route, 6), ro.dataset.len) mut m := qint(req, qk_m) @@ -1409,9 +1782,10 @@ fn main() { m = 1 } write_json_into(ro, mut out, count, m) - return + return .done } wb(mut out, not_found) + return .done } // Port is fixed to 8081 by the HttpArena harness; TLS_PORT lets local runs pick // a free port (the harness injects nothing, so the default is the contract). @@ -1419,19 +1793,21 @@ fn main() { if tls_port <= 0 { tls_port = 8081 } - tls_server := http_server.new_server(http_server.ServerConfig{ + tls_server := server.new_server(server.ServerConfig{ port: tls_port io_multiplexing: .epoll - limits: http_server.Limits{ - // json-tls requests are tiny GETs; a small ceiling bounds per-conn - // memory and shrinks the DoS surface (the TLS port takes no bodies). - max_request_bytes: 64 * 1024 + limits: server.Limits{ + // json-tls sends tiny GETs; 8gbit POSTs 10 KB to /echo and validation + // goes up to 100 KB, chunked included. 256 KiB covers that with room + // for chunk framing and still bounds a connection's read buffer. + max_request_bytes: 256 * 1024 } - request_handler: tls_handler + handler: tls_handler + make_state: new_tls_worker tls_config: load_tls_config() })! // run() blocks in the accept loop, so the TLS server runs on its own thread - // while the plaintext server.run() below blocks main. run() has a value-mut + // while the plaintext srv.run() below blocks main. run() has a value-mut // receiver, so spawn it via a closure with a local mut copy (each Server is // independent — own socket, workers and counters). spawn fn [tls_server] () { @@ -1439,17 +1815,15 @@ fn main() { s.run() }() - mut server := http_server.new_server(http_server.ServerConfig{ + mut srv := server.new_server(server.ServerConfig{ port: 8080 io_multiplexing: .io_uring - limits: http_server.Limits{ + limits: server.Limits{ max_request_bytes: 32 * 1024 * 1024 } - async_handler: handle + handler: handle make_state: fn [ro, cfg, per_worker] () voidptr { - pool := pg_async.new_pool(cfg, per_worker) or { - panic('vanilla-io_uring: pg pool bring-up failed: ${err}') - } + pool := connect_pool(cfg, per_worker) w := &WorkerCtx{ ro: ro pool: pool @@ -1459,9 +1833,10 @@ fn main() { stash_pool: []&Stash{cap: 64} // Stash free-list fortunes_buf: []Fortune{cap: 256} // reused /fortunes rows dechunk_buf: []u8{cap: 4096} // reused chunked-body scratch + timer_fds: []int{cap: 64} // recycled /delay timerfds } return voidptr(w) } })! - server.run() + srv.run() } diff --git a/frameworks/vanilla-io_uring/mbedtls-rsa-sign-cache.patch b/frameworks/vanilla-io_uring/mbedtls-rsa-sign-cache.patch new file mode 100644 index 000000000..016cc06b8 --- /dev/null +++ b/frameworks/vanilla-io_uring/mbedtls-rsa-sign-cache.patch @@ -0,0 +1,101 @@ +--- a/tf-psa-crypto/drivers/builtin/src/psa_crypto_rsa.c ++++ b/tf-psa-crypto/drivers/builtin/src/psa_crypto_rsa.c +@@ -306,6 +306,68 @@ + return PSA_SUCCESS; + } + ++/* vanilla (HttpArena) patch: per-thread cache of the signing key's parsed RSA ++ * context. ++ * ++ * Unpatched, every psa_sign_hash() re-parses the key into a fresh ++ * mbedtls_rsa_context, so mbedtls_rsa_private() finds no blinding values and ++ * regenerates them from scratch (a random value, its modular inverse and an ++ * exponentiation) before signing. For a TLS 1.3 server with an RSA ++ * certificate that is most of every handshake's CertificateVerify. A ++ * long-lived context, as the legacy RSA API always had, updates its blinding ++ * values by squaring instead. ++ * ++ * The cache is thread-local, so there is no locking and no thread ever sees ++ * another's (mutable) blinding state. It holds one key, compared byte for ++ * byte, so a different or re-imported key simply reloads. The entry lives as ++ * long as the thread. */ ++static __thread mbedtls_rsa_context *vanilla_sign_rsa = NULL; ++static __thread uint8_t *vanilla_sign_key = NULL; ++static __thread size_t vanilla_sign_key_len = 0; ++ ++static psa_status_t vanilla_rsa_sign_context(psa_key_type_t type, ++ const uint8_t *key_buffer, ++ size_t key_buffer_size, ++ mbedtls_rsa_context **p_rsa, ++ int *cached) ++{ ++ psa_status_t status; ++ mbedtls_rsa_context *rsa = NULL; ++ uint8_t *copy; ++ ++ if (vanilla_sign_rsa != NULL && vanilla_sign_key_len == key_buffer_size && ++ memcmp(vanilla_sign_key, key_buffer, key_buffer_size) == 0) { ++ *p_rsa = vanilla_sign_rsa; ++ *cached = 1; ++ return PSA_SUCCESS; ++ } ++ status = mbedtls_psa_rsa_load_representation(type, key_buffer, ++ key_buffer_size, &rsa); ++ *p_rsa = rsa; ++ *cached = 0; ++ if (status != PSA_SUCCESS) { ++ return status; ++ } ++ copy = mbedtls_calloc(1, key_buffer_size); ++ if (copy == NULL) { ++ return PSA_SUCCESS; /* sign uncached; the caller frees rsa */ ++ } ++ memcpy(copy, key_buffer, key_buffer_size); ++ if (vanilla_sign_rsa != NULL) { ++ mbedtls_rsa_free(vanilla_sign_rsa); ++ mbedtls_free(vanilla_sign_rsa); ++ } ++ if (vanilla_sign_key != NULL) { ++ mbedtls_platform_zeroize(vanilla_sign_key, vanilla_sign_key_len); ++ mbedtls_free(vanilla_sign_key); ++ } ++ vanilla_sign_rsa = rsa; ++ vanilla_sign_key = copy; ++ vanilla_sign_key_len = key_buffer_size; ++ *cached = 1; ++ return PSA_SUCCESS; ++} ++ + psa_status_t mbedtls_psa_rsa_sign_hash( + const psa_key_attributes_t *attributes, + const uint8_t *key_buffer, size_t key_buffer_size, +@@ -316,11 +378,12 @@ + mbedtls_rsa_context *rsa = NULL; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_md_type_t md_alg; ++ int cached = 0; + +- status = mbedtls_psa_rsa_load_representation(attributes->type, +- key_buffer, +- key_buffer_size, +- &rsa); ++ status = vanilla_rsa_sign_context(attributes->type, ++ key_buffer, ++ key_buffer_size, ++ &rsa, &cached); + if (status != PSA_SUCCESS) { + goto exit; + } +@@ -377,8 +440,10 @@ + status = mbedtls_to_psa_error(ret); + + exit: +- mbedtls_rsa_free(rsa); +- mbedtls_free(rsa); ++ if (!cached) { ++ mbedtls_rsa_free(rsa); ++ mbedtls_free(rsa); ++ } + + return status; + } diff --git a/frameworks/vanilla-io_uring/meta.json b/frameworks/vanilla-io_uring/meta.json index ee05dfa55..663cabc21 100644 --- a/frameworks/vanilla-io_uring/meta.json +++ b/frameworks/vanilla-io_uring/meta.json @@ -3,15 +3,17 @@ "language": "V", "type": "engine", "engine": "io_uring", - "description": "vanilla is a minimalist, high-performance HTTP server written in V: multi-threaded, non-blocking io_uring I/O, lock-free, copy-free, SO_REUSEPORT. This entry is the vanilla-epoll entry's async handler verbatim, running on the io_uring async runtime (enghitalo/vanilla#99): DB queries park on the PG socket via a oneshot IORING_OP_POLL_ADD and resume on the ring — never blocking the worker. JSON is built in a single allocation with precomputed prefixes (no per-request reflection); json-comp gzips on Accept-Encoding; json-tls serves /json over HTTP/1.1 + TLS 1.3 on :8081 via the lib's epoll backend (the io_uring backend has no TLS) with kTLS record offload where present; static assets are preloaded into memory; fortunes renders the DB rows + a runtime row with HTML escaping; async-db/crud/fortunes use the native async pg_async driver with per-worker pipelined pools. Built with the default GC on pinned V master (built from source). crud uses an in-memory cache-aside (X-Cache MISS/HIT, invalidated on update) — no Redis required.", + "description": "vanilla is a minimalist, high-performance HTTP server written in V: multi-threaded, non-blocking io_uring I/O, lock-free, copy-free, SO_REUSEPORT. This entry is the vanilla-epoll entry's async handler verbatim, running on the io_uring async runtime (enghitalo/vanilla#99): DB queries park on the PG socket via a oneshot IORING_OP_POLL_ADD and resume on the ring — never blocking the worker. JSON is built in a single allocation with precomputed prefixes (no per-request reflection); json-comp gzips on Accept-Encoding; json-tls serves /json over HTTP/1.1 + TLS 1.3 on :8081 via the lib's epoll backend (the io_uring backend has no TLS) with kTLS record offload where present; static-tls serves the 20 /static files on :8081 through vanilla's static_assets (br/gzip negotiation; snapshots re-checked against the disk, so a replaced file is served at once), sending bodies of 16 KiB or more with sendfile(2) over kTLS; fortunes renders the DB rows + a runtime row with HTML escaping; async-db/crud/fortunes use the native async pg_async driver with per-worker pipelined pools. Built with the default GC on pinned V master (built from source). async parks each /delay/{ms} on a one-shot timerfd from a per-worker free-list and answers only once it reports an expiration; 8gbit echoes the POST body on the :8081 TLS listener (Content-Length or chunked, per-worker dechunk buffer); production-stack's /api cache-aside (X-Cache MISS/HIT, 1 s items / 30 s users TTL, invalidated on write) runs in-process — no Redis required. One worker per CPU of the container's cpuset.", "repo": "https://github.com/enghitalo/vanilla", - "enabled": false, + "enabled": true, "tests": [ - "baseline", "latency-1m", "latency-10k", + "baseline", "async", "latency-1m", "latency-10k", "latency-500k-8cpu", "pipelined", "limited-conn", "json-comp", "json-tls", + "static-tls", + "8gbit", "async-db", "fortunes" ], diff --git a/frameworks/vanilla-production/compose.production-stack.yml b/frameworks/vanilla-production/compose.production-stack.yml new file mode 100644 index 000000000..39448c0ac --- /dev/null +++ b/frameworks/vanilla-production/compose.production-stack.yml @@ -0,0 +1,103 @@ +# production-stack - nginx edge + Redis + the shared authsvc + the vanilla-epoll +# image, on the reference entry's 64-CPU split (the spec's tuning note: the best +# split has edge, authsvc and server near their ceilings at once): +# +# edge nginx 30 logical TLS + h2, static from disk, auth_request +# cache redis 2 logical the stack's cache service +# authsvc shared 8 logical HMAC-SHA256 JWT check on every /api/* call +# server vanilla 24 logical /public/*, /api/* with in-process cache-aside +# +# Override with EDGE_CPUSET / CACHE_CPUSET / AUTH_CPUSET / SERVER_CPUSET. +services: + edge: + build: ./proxy-production + network_mode: host + cpuset: "${EDGE_CPUSET:-0-14,64-78}" + ulimits: + memlock: -1 + nofile: + soft: 1048576 + hard: 1048576 + security_opt: + - seccomp:unconfined + volumes: + - ${CERTS_DIR}:/certs:ro + - ${DATA_DIR}/static:/data/static:ro + depends_on: + authsvc: + condition: service_healthy + server: + condition: service_started + + cache: + image: redis:7-alpine + network_mode: host + cpuset: "${CACHE_CPUSET:-15,79}" + ulimits: + memlock: -1 + nofile: + soft: 1048576 + hard: 1048576 + security_opt: + - seccomp:unconfined + volumes: + - ${DATA_DIR}/redis-seed.txt:/seed.txt:ro + - ${DATA_DIR}/redis-entrypoint.sh:/entrypoint.sh:ro + entrypoint: ["sh", "/entrypoint.sh"] + healthcheck: + test: ["CMD", "redis-cli", "-p", "6379", "ping"] + interval: 30s + timeout: 2s + retries: 3 + start_period: 30s + start_interval: 1s + + authsvc: + build: ../_shared/authsvc + network_mode: host + cpuset: "${AUTH_CPUSET:-16-19,80-83}" + ulimits: + memlock: -1 + nofile: + soft: 1048576 + hard: 1048576 + security_opt: + - seccomp:unconfined + environment: + - JWT_SECRET=httparena-bench-secret-do-not-use-in-production + - AUTHSVC_LISTEN=0.0.0.0:9090 + # the sidecar's own /_health, probed with the image's busybox wget + healthcheck: + test: ["CMD", "wget", "-qO-", "http://127.0.0.1:9090/_health"] + interval: 30s + timeout: 2s + retries: 3 + start_period: 30s + start_interval: 1s + + server: + build: + context: ../vanilla-epoll + dockerfile: Dockerfile + network_mode: host + cpuset: "${SERVER_CPUSET:-20-31,84-95}" + ulimits: + memlock: -1 + nofile: + soft: 1048576 + hard: 1048576 + security_opt: + - seccomp:unconfined + environment: + - DATABASE_URL=${DATABASE_URL} + # Postgres allows 256; split evenly across the server's workers + - DATABASE_MAX_CONN=256 + - REDIS_URL=redis://127.0.0.1:6379 + - DATASET_PATH=/data/dataset.json + volumes: + - ${DATA_DIR}/dataset.json:/data/dataset.json:ro + # the image mounts its static handler at boot; the edge serves /static here + - ${DATA_DIR}/static:/data/static:ro + depends_on: + cache: + condition: service_healthy diff --git a/frameworks/vanilla-production/meta.json b/frameworks/vanilla-production/meta.json new file mode 100644 index 000000000..cec7680eb --- /dev/null +++ b/frameworks/vanilla-production/meta.json @@ -0,0 +1,15 @@ +{ + "display_name": "vanilla-epoll", + "language": "V", + "type": "engine", + "engine": "epoll", + "description": "vanilla-epoll in the four-service production stack: nginx terminates TLS + h2 and verifies every /api/* request's JWT through the shared authsvc (auth_request), serves /static/* from disk and forwards to the vanilla-epoll image over loopback HTTP/1.1 keepalive. The server is the vanilla-epoll entry unchanged: cache-aside on /api/items/{id} (1 s TTL) and /api/me (30 s TTL) in an in-process, id-indexed slab shared by its workers (X-Cache HIT/MISS), POST /api/items/{id} parsed in place, UPDATE through the async pg_async pools, then invalidate and 204. Redis runs as the stack's cache service; the server keeps its cache in-process, which the profile allows.", + "repo": "https://github.com/enghitalo/vanilla", + "enabled": true, + "tests": [ + "production-stack" + ], + "maintainers": [ + "enghitalo" + ] +} diff --git a/frameworks/vanilla-production/proxy-production/Dockerfile b/frameworks/vanilla-production/proxy-production/Dockerfile new file mode 100644 index 000000000..2077c8bb5 --- /dev/null +++ b/frameworks/vanilla-production/proxy-production/Dockerfile @@ -0,0 +1,8 @@ +# Stock nginx: TLS + h2 edge with auth_request for the production-stack profile. +FROM nginx:1.27-alpine + +COPY nginx.conf /etc/nginx/nginx.conf + +EXPOSE 8443/tcp + +CMD ["nginx", "-g", "daemon off;"] diff --git a/frameworks/vanilla-production/proxy-production/nginx.conf b/frameworks/vanilla-production/proxy-production/nginx.conf new file mode 100644 index 000000000..d30c892a6 --- /dev/null +++ b/frameworks/vanilla-production/proxy-production/nginx.conf @@ -0,0 +1,98 @@ +# vanilla production-stack edge, nginx. +# +# TLS + h2 on 8443. /static/* from disk. /public/* straight to the server. +# /api/* goes through auth_request to the shared authsvc on EVERY call (no auth +# caching, per the profile); on 200 the verified user id is forwarded to the +# server as X-User-Id, on anything else the client gets 401. Both upstreams are +# loopback HTTP/1.1 keepalive pools. + +worker_processes auto; +worker_rlimit_nofile 1048576; + +events { + worker_connections 65535; + multi_accept on; +} + +http { + include /etc/nginx/mime.types; + default_type application/octet-stream; + + sendfile on; + tcp_nopush on; + tcp_nodelay on; + + gzip_static on; + gzip_vary on; + + keepalive_timeout 65; + keepalive_requests 1000000; + + access_log off; + error_log /dev/stderr warn; + + upstream backend { + server 127.0.0.1:8080; + keepalive 2048; + keepalive_requests 1000000; + keepalive_timeout 300s; + } + + upstream authsvc { + server 127.0.0.1:9090; + keepalive 256; + keepalive_requests 1000000; + keepalive_timeout 300s; + } + + server { + listen 8443 ssl; + http2 on; + + ssl_certificate /certs/server.crt; + ssl_certificate_key /certs/server.key; + ssl_protocols TLSv1.2 TLSv1.3; + ssl_prefer_server_ciphers off; + + auth_request_set $auth_user_id $upstream_http_x_user_id; + + location = /_auth { + internal; + proxy_pass http://authsvc/_auth; + proxy_http_version 1.1; + proxy_set_header Connection ""; + proxy_set_header Host $host; + proxy_set_header Authorization $http_authorization; + proxy_pass_request_body off; + proxy_set_header Content-Length ""; + } + + location /static/ { + alias /data/static/; + expires off; + add_header Cache-Control "no-cache"; + } + + location /public/ { + proxy_pass http://backend; + proxy_http_version 1.1; + proxy_set_header Connection ""; + proxy_set_header Host $host; + } + + location /api/ { + auth_request /_auth; + error_page 401 = @auth_failed; + proxy_pass http://backend; + proxy_http_version 1.1; + proxy_set_header Connection ""; + proxy_set_header Host $host; + proxy_set_header X-User-Id $auth_user_id; + } + + location @auth_failed { + add_header Content-Type "application/json" always; + return 401 '{"error":"unauthorized"}'; + } + } +} diff --git a/frameworks/vanilla-ws/Dockerfile b/frameworks/vanilla-ws/Dockerfile index d6d9d5376..198c77732 100644 --- a/frameworks/vanilla-ws/Dockerfile +++ b/frameworks/vanilla-ws/Dockerfile @@ -5,27 +5,48 @@ RUN apt-get -qq update && \ ca-certificates build-essential git liburing-dev && \ rm -rf /var/lib/apt/lists/* -# Pinned, reproducible V at master commit 5fb31f25 (built from source), the -# commit this entry was validated against. `make` bootstraps via the matching -# vc; if a much later rebuild ever fails to bootstrap, pin vlang/vc to the -# commit cut for this V. -RUN git clone https://github.com/vlang/v /opt/v && \ - cd /opt/v && git checkout 5fb31f25bd9b056cc63cedc51b669073658b41a8 && \ - make && ln -s /opt/v/v /usr/local/bin/v +# Pinned, reproducible V at master commit b99970bd (0.5.2, built from source), +# the commit this entry was validated against. +# +# The bootstrap is pinned too. A bare `make` clones vlang/vc and vlang/tccbin at +# their CURRENT heads, so a fixed V source gets built by whatever compiler vc +# holds that day: that is what broke every V entry in #1288 ("C function C.open +# was already declared with a different signature"), and vc head has since +# failed in other ways. vc 2cbaf6bc is vc's newest snapshot (generated from V +# 0c41fadb, 40 commits earlier; vc has none for b99970bd yet), so it is what +# `make` bootstraps this V with today; tccbin d6e7ac1b is the head of tccbin's +# thirdparty-linux-amd64 branch, and `local=1` makes `make` build with both +# instead of pulling. +# +# Each repo is fetched at its one pinned commit (depth 1) rather than cloned: +# a full clone of v, vc and tccbin is hundreds of MB and a slow or flaky link +# stalls it past the validator's timeout; this is ~30 MB. +RUN git init -q /opt/v && cd /opt/v && \ + git fetch -q --depth 1 https://github.com/vlang/v b99970bd438a7bdcdfbe38f74d9364db801d5439 && \ + git checkout -q FETCH_HEAD && \ + git init -q vc && \ + git -C vc fetch -q --depth 1 https://github.com/vlang/vc 2cbaf6bc2367937cd5f0b4ef923d1ef9aad613b3 && \ + git -C vc checkout -q FETCH_HEAD && \ + git init -q thirdparty/tcc && \ + git -C thirdparty/tcc fetch -q --depth 1 https://github.com/vlang/tccbin d6e7ac1b1bcc98aed734a6ecbfa8509f24606c74 && \ + git -C thirdparty/tcc checkout -q FETCH_HEAD && \ + make local=1 && ln -s /opt/v/v /usr/local/bin/v # Install vanilla as the `vanilla` module (import vanilla.server), pinned to a # specific commit: reproducible, with NO per-build network call to detect # changes. To pick up upstream library fixes, bump this commit. # -# Pinned to vanilla main @ab0791b — carries the conn-mode seam +# Pinned to vanilla main @091c014, which carries the conn-mode seam # (enghitalo/vanilla#136): a protocol-neutral connection-takeover contract in # core (queue_takeover + ConnHandler) that lets an HTTP handler flip the # connection out of the HTTP/1.1 state machine after the 101, plus the # websocket module — a pure RFC 6455 codec (accept-key, frame-head parsing # with the full malformed matrix, in-place unmasking, unmasked server-frame -# writers). This entry composes the two; see main.v. -RUN git clone https://github.com/enghitalo/vanilla /root/.vmodules/vanilla && \ - git -C /root/.vmodules/vanilla checkout ab0791b54717db843be3ed820c97ad93398930ff +# writers). This entry composes the two; see main.v. Fetched at that one commit. +RUN git init -q /root/.vmodules/vanilla && \ + git -C /root/.vmodules/vanilla fetch -q --depth 1 https://github.com/enghitalo/vanilla \ + 091c014a0191afd7e740b84f5599b9b1fc1fd914 && \ + git -C /root/.vmodules/vanilla checkout -q FETCH_HEAD WORKDIR /app COPY . . @@ -40,4 +61,8 @@ RUN apt-get -qq update && \ COPY --from=build /app/server /server EXPOSE 8080 -CMD ["/server"] +# One worker per CPU the container may run on. vanilla defaults to nr_cpus, +# which reads the host's online CPUs (128 on the bench box) and ignores the +# cpuset, so a 64-CPU profile started 128 workers and latency-500k-8cpu would +# start 128 on 8. nproc honours the cpuset; an explicit VANILLA_WORKERS wins. +CMD ["/bin/sh", "-c", "VANILLA_WORKERS=${VANILLA_WORKERS:-$(nproc)} exec /server"] diff --git a/frameworks/vanilla-ws/meta.json b/frameworks/vanilla-ws/meta.json index 8cc1f83d1..44039b36b 100644 --- a/frameworks/vanilla-ws/meta.json +++ b/frameworks/vanilla-ws/meta.json @@ -5,10 +5,11 @@ "engine": "epoll", "description": "WebSocket echo on vanilla's conn-mode seam: one epoll engine, two protocols on the same connection. The HTTP handler validates the RFC 6455 upgrade as a pure function, appends the 101 and hands the connection over (core.queue_takeover); from then on every readable burst is fed to a ConnHandler instead of the HTTP/1.1 state machine. The websocket module is a pure RFC 6455 codec (accept-key, frame-head parsing, in-place unmasking, unmasked server-frame writers). Read buffering/compaction, batched flushes and EPOLLOUT backpressure are the engine's own, so a pipelined burst of frames is drained in one handler call and coalesced into one write. Multi-threaded, SO_REUSEPORT, lock-free, -gc none.", "repo": "https://github.com/enghitalo/vanilla", - "enabled": false, + "enabled": true, "tests": [ "echo-ws", - "echo-ws-pipeline" + "echo-ws-pipeline", + "echo-ws-limited" ], "maintainers": [ "enghitalo" diff --git a/site/data/frameworks.json b/site/data/frameworks.json index 89431f068..dc196143f 100644 --- a/site/data/frameworks.json +++ b/site/data/frameworks.json @@ -2090,21 +2090,37 @@ }, "vanilla-epoll": { "dir": "vanilla-epoll", - "description": "vanilla is a minimalist, high-performance HTTP server written in V: multi-threaded, non-blocking epoll I/O, lock-free, copy-free, SO_REUSEPORT. Handlers are pure (request)->[]u8 returning raw response bytes. JSON is built in a single allocation with precomputed prefixes (no per-request reflection); json-comp gzips on Accept-Encoding; json-tls terminates TLS 1.3 (Mbed TLS 4) on :8081 with ALPN http/1.1, reusing the same allocation-free /json serializer; static assets are preloaded into memory; fortunes renders the DB rows + a runtime row with HTML escaping; async-db uses the stdlib db.pg ConnectionPool. Pinned V 0.5.1 (prebuilt release). crud uses an in-memory cache-aside (X-Cache MISS/HIT, invalidated on update) \u2014 no Redis required.", + "description": "vanilla is a minimalist, high-performance HTTP server written in V: multi-threaded, non-blocking epoll I/O, lock-free, copy-free, SO_REUSEPORT. Handlers are pure (request)->[]u8 returning raw response bytes. JSON is built in a single allocation with precomputed prefixes (no per-request reflection); json-comp gzips on Accept-Encoding; json-tls terminates TLS 1.3 (Mbed TLS 4) on :8081 with ALPN http/1.1, reusing the same allocation-free /json serializer; static-tls serves the 20 /static files on :8081 through vanilla's static_assets (br/gzip negotiation; snapshots re-checked against the disk, so a replaced file is served at once), sending bodies of 16 KiB or more with sendfile(2) over kTLS; fortunes renders the DB rows + a runtime row with HTML escaping; async-db/crud/fortunes use the native async pg_async driver with per-worker pipelined pools. Pinned V master (built from source, bootstrap pinned). async parks each /delay/{ms} on a one-shot timerfd from a per-worker free-list and answers only once it reports an expiration; 8gbit echoes the POST body on the :8081 TLS listener (Content-Length or chunked, per-worker dechunk buffer); production-stack's /api cache-aside (X-Cache MISS/HIT, 1 s items / 30 s users TTL, invalidated on write) runs in-process \u2014 no Redis required. One worker per CPU of the container's cpuset.", "repo": "https://github.com/enghitalo/vanilla", "type": "engine", - "engine": "epoll" + "engine": "epoll", + "variants": [ + { + "dir": "vanilla-gateway", + "description": "vanilla-epoll behind a stock edge for the gateway profiles: nginx terminates TLS + h2 (gateway-64) and Caddy terminates QUIC + h3 (gateway-h3); both serve /static/* from disk and forward /baseline2, /json and /async-db to the vanilla-epoll image over loopback HTTP/1.1 with a 2048-connection keepalive pool. The server is the vanilla-epoll entry unchanged (same Dockerfile), one worker per CPU of its cpuset, async pg_async pools, and /json served gzip from its lazy per-(count, m) cache when the edge forwards Accept-Encoding.", + "repo": "https://github.com/enghitalo/vanilla", + "type": "engine", + "engine": "epoll" + }, + { + "dir": "vanilla-production", + "description": "vanilla-epoll in the four-service production stack: nginx terminates TLS + h2 and verifies every /api/* request's JWT through the shared authsvc (auth_request), serves /static/* from disk and forwards to the vanilla-epoll image over loopback HTTP/1.1 keepalive. The server is the vanilla-epoll entry unchanged: cache-aside on /api/items/{id} (1 s TTL) and /api/me (30 s TTL) in an in-process, id-indexed slab shared by its workers (X-Cache HIT/MISS), POST /api/items/{id} parsed in place, UPDATE through the async pg_async pools, then invalidate and 204. Redis runs as the stack's cache service; the server keeps its cache in-process, which the profile allows.", + "repo": "https://github.com/enghitalo/vanilla", + "type": "engine", + "engine": "epoll" + } + ] }, "vanilla-h2c": { "dir": "vanilla-h2c", - "description": "HTTP/2 cleartext (h2c, prior-knowledge) on vanilla's conn-mode seam: one epoll engine drives the RFC 9113 state machine behind a ConnHandler. The client's PRI * HTTP/2.0 preface parses as an ordinary request; the HTTP handler flips the connection over (core.queue_takeover), appends the server SETTINGS preface, and every later burst is fed to the http2 machine instead of the HTTP/1.1 parser. The http2 module is a self-contained RFC 9113/7541 codec: HPACK (static + dynamic table, canonical Huffman decode, decoded-block ceiling), frame codec, and a stream state machine with send-side flow control, hardened against a live h2spec CI gate. Requests surface only when COMPLETE (END_STREAM); responses are HPACK-encoded HEADERS + DATA. The :8082 listener is h2c-only \u2014 a plain HTTP/1.1 request is refused 505, never a 200, so the benchmark cannot silently measure h1 throughput. /json reuses the vanilla /json shape (same dataset, precomputed per-item prefixes, total = price*quantity*m). Multi-threaded, SO_REUSEPORT, lock-free, -gc none. Pinned V 0.5.2 (prebuilt from source).", + "description": "HTTP/2 cleartext (h2c, prior-knowledge) on vanilla's conn-mode seam: one epoll engine drives the RFC 9113 state machine behind a ConnHandler. The client's PRI * HTTP/2.0 preface parses as an ordinary request; the HTTP handler flips the connection over (core.queue_takeover), appends the server SETTINGS preface, and every later burst is fed to the http2 machine instead of the HTTP/1.1 parser. The http2 module is a self-contained RFC 9113/7541 codec: HPACK (static + dynamic table, canonical Huffman decode, decoded-block ceiling), frame codec, and a stream state machine with send-side flow control, hardened against a live h2spec CI gate. Requests surface only when COMPLETE (END_STREAM); responses are HPACK-encoded HEADERS + DATA. The :8082 listener is h2c-only \u2014 a plain HTTP/1.1 request is refused 505, never a 200, so the benchmark cannot silently measure h1 throughput. /json reuses the vanilla /json shape (same dataset, precomputed per-item prefixes, total = price*quantity*m). unary-grpc runs on the same machine on :8080: GetSum decodes the length-prefixed SumRequest (a protobuf varint loop that skips unknown fields), answers HEADERS + the SumReply as DATA without END_STREAM, then grpc-status 0 as trailers, which wait behind any DATA parked on flow control (enghitalo/vanilla#174). Each connection reuses its request list and buffers; the gRPC header blocks are encoded once. Multi-threaded, SO_REUSEPORT, lock-free, -gc none. Pinned V 0.5.2 (prebuilt from source).", "repo": "https://github.com/enghitalo/vanilla", "type": "engine", "engine": "epoll" }, "vanilla-io_uring": { "dir": "vanilla-io_uring", - "description": "vanilla is a minimalist, high-performance HTTP server written in V: multi-threaded, non-blocking io_uring I/O, lock-free, copy-free, SO_REUSEPORT. This entry is the vanilla-epoll entry's async handler verbatim, running on the io_uring async runtime (enghitalo/vanilla#99): DB queries park on the PG socket via a oneshot IORING_OP_POLL_ADD and resume on the ring \u2014 never blocking the worker. JSON is built in a single allocation with precomputed prefixes (no per-request reflection); json-comp gzips on Accept-Encoding; json-tls serves /json over HTTP/1.1 + TLS 1.3 on :8081 via the lib's epoll backend (the io_uring backend has no TLS) with kTLS record offload where present; static assets are preloaded into memory; fortunes renders the DB rows + a runtime row with HTML escaping; async-db/crud/fortunes use the native async pg_async driver with per-worker pipelined pools. Built with the default GC on pinned V master (built from source). crud uses an in-memory cache-aside (X-Cache MISS/HIT, invalidated on update) \u2014 no Redis required.", + "description": "vanilla is a minimalist, high-performance HTTP server written in V: multi-threaded, non-blocking io_uring I/O, lock-free, copy-free, SO_REUSEPORT. This entry is the vanilla-epoll entry's async handler verbatim, running on the io_uring async runtime (enghitalo/vanilla#99): DB queries park on the PG socket via a oneshot IORING_OP_POLL_ADD and resume on the ring \u2014 never blocking the worker. JSON is built in a single allocation with precomputed prefixes (no per-request reflection); json-comp gzips on Accept-Encoding; json-tls serves /json over HTTP/1.1 + TLS 1.3 on :8081 via the lib's epoll backend (the io_uring backend has no TLS) with kTLS record offload where present; static-tls serves the 20 /static files on :8081 through vanilla's static_assets (br/gzip negotiation; snapshots re-checked against the disk, so a replaced file is served at once), sending bodies of 16 KiB or more with sendfile(2) over kTLS; fortunes renders the DB rows + a runtime row with HTML escaping; async-db/crud/fortunes use the native async pg_async driver with per-worker pipelined pools. Built with the default GC on pinned V master (built from source). async parks each /delay/{ms} on a one-shot timerfd from a per-worker free-list and answers only once it reports an expiration; 8gbit echoes the POST body on the :8081 TLS listener (Content-Length or chunked, per-worker dechunk buffer); production-stack's /api cache-aside (X-Cache MISS/HIT, 1 s items / 30 s users TTL, invalidated on write) runs in-process \u2014 no Redis required. One worker per CPU of the container's cpuset.", "repo": "https://github.com/enghitalo/vanilla", "type": "engine", "engine": "io_uring" diff --git a/site/data/results/vanilla-epoll.json b/site/data/results/vanilla-epoll.json new file mode 100644 index 000000000..8aa4fa076 --- /dev/null +++ b/site/data/results/vanilla-epoll.json @@ -0,0 +1,442 @@ +{ + "framework": "vanilla-epoll", + "results": { + "8gbit-512": { + "framework": "vanilla-epoll", + "language": "V", + "rps": 49158, + "avg_latency": "287.9us", + "p99_latency": "238.0us", + "cpu": "512.6%", + "memory": "86MiB", + "connections": 512, + "threads": 64, + "duration": "5s", + "pipeline": 1, + "bandwidth": "509.42MB/s", + "input_bw": "480.06MB/s", + "reconnects": 0, + "status_2xx": 245899, + "status_3xx": 0, + "status_4xx": 0, + "status_5xx": 0, + "cpu_usec": 23118772, + "cpu_per_req_us": 94.0173, + "target_rate": 50000, + "rate_ratio": 0.9832, + "p99_9_latency": "42224.0us" + }, + "async-32000": { + "framework": "vanilla-epoll", + "language": "V", + "rps": 2597329, + "avg_latency": "12.22ms", + "p99_latency": "12.70ms", + "cpu": "6180.4%", + "memory": "1.3GiB", + "connections": 32000, + "threads": 64, + "duration": "5s", + "pipeline": 1, + "bandwidth": "264.99MB/s", + "input_bw": "118.90MB/s", + "reconnects": 0, + "status_2xx": 25973296, + "status_3xx": 0, + "status_4xx": 0, + "status_5xx": 0 + }, + "async-db-1024": { + "framework": "vanilla-epoll", + "language": "V", + "rps": 345636, + "avg_latency": "1.38ms", + "p99_latency": "8.87ms", + "cpu": "2972.1%", + "memory": "120MiB", + "connections": 1024, + "threads": 64, + "duration": "5s", + "pipeline": 1, + "bandwidth": "1.30GB/s", + "input_bw": "23.07MB/s", + "reconnects": 138258, + "status_2xx": 3456361, + "status_3xx": 0, + "status_4xx": 0, + "status_5xx": 0 + }, + "baseline-4096": { + "framework": "vanilla-epoll", + "language": "V", + "rps": 4117078, + "avg_latency": "994us", + "p99_latency": "1.08ms", + "cpu": "6222.4%", + "memory": "128MiB", + "connections": 4096, + "threads": 64, + "duration": "5s", + "pipeline": 1, + "bandwidth": "419.96MB/s", + "input_bw": "318.03MB/s", + "reconnects": 0, + "status_2xx": 20585394, + "status_3xx": 0, + "status_4xx": 0, + "status_5xx": 0 + }, + "fortunes-1024": { + "framework": "vanilla-epoll", + "language": "V", + "rps": 185540, + "avg_latency": "4.05ms", + "p99_latency": "7.93ms", + "cpu": "6269.5%", + "memory": "233MiB", + "connections": 1024, + "threads": 64, + "duration": "5s", + "pipeline": 1, + "bandwidth": "4.30GB/s", + "reconnects": 0, + "status_2xx": 927704, + "status_3xx": 0, + "status_4xx": 0, + "status_5xx": 0 + }, + "gateway-64-1024": { + "framework": "vanilla-epoll", + "language": "V", + "rps": 383090, + "avg_latency": "86.71ms", + "p99_latency": "564.50ms", + "cpu": "5258.6%", + "memory": "2.3GiB", + "connections": 1024, + "threads": 64, + "duration": "5s", + "pipeline": 1, + "bandwidth": "4.72GB/s", + "reconnects": 0, + "status_2xx": 1942270, + "status_3xx": 0, + "status_4xx": 0, + "status_5xx": 0, + "tpl_static": 582681, + "tpl_baseline": 388454, + "tpl_json": 679794, + "tpl_async_db": 291340, + "cpu_breakdown": "proxy: 4188% 1.6GiB | server: 1070% 668MiB" + }, + "gateway-64-512": { + "framework": "vanilla-epoll", + "language": "V", + "rps": 380490, + "avg_latency": "49.37ms", + "p99_latency": "264.91ms", + "cpu": "5079.6%", + "memory": "1.7GiB", + "connections": 512, + "threads": 64, + "duration": "5s", + "pipeline": 1, + "bandwidth": "4.64GB/s", + "reconnects": 0, + "status_2xx": 1921479, + "status_3xx": 0, + "status_4xx": 0, + "status_5xx": 0, + "tpl_static": 576443, + "tpl_baseline": 384295, + "tpl_json": 672517, + "tpl_async_db": 288221, + "cpu_breakdown": "proxy: 4075% 1.4GiB | server: 1005% 397MiB" + }, + "gateway-h3-256": { + "framework": "vanilla-epoll", + "language": "V", + "rps": 62102, + "avg_latency": "128.11ms", + "p99_latency": "759.12ms", + "cpu": "2123.9%", + "memory": "1.5GiB", + "connections": 256, + "threads": 64, + "duration": "5s", + "pipeline": 1, + "bandwidth": "662.06MB/s", + "reconnects": 0, + "status_2xx": 312997, + "status_3xx": 0, + "status_4xx": 0, + "status_5xx": 0, + "tpl_static": 93899, + "tpl_baseline": 62599, + "tpl_json": 109548, + "tpl_async_db": 46949, + "cpu_breakdown": "server: 140% 86MiB | proxy: 1984% 1.4GiB" + }, + "gateway-h3-64": { + "framework": "vanilla-epoll", + "language": "V", + "rps": 92115, + "avg_latency": "22.11ms", + "p99_latency": "81.94ms", + "cpu": "2748.1%", + "memory": "532MiB", + "connections": 64, + "threads": 64, + "duration": "5s", + "pipeline": 1, + "bandwidth": "1002.35MB/s", + "reconnects": 0, + "status_2xx": 461500, + "status_3xx": 0, + "status_4xx": 0, + "status_5xx": 0, + "tpl_static": 138450, + "tpl_baseline": 92300, + "tpl_json": 161525, + "tpl_async_db": 69225, + "cpu_breakdown": "server: 228% 59MiB | proxy: 2520% 473MiB" + }, + "json-comp-16384": { + "framework": "vanilla-epoll", + "language": "V", + "rps": 2503125, + "avg_latency": "6.19ms", + "p99_latency": "159.70ms", + "cpu": "5697.4%", + "memory": "218MiB", + "connections": 16384, + "threads": 64, + "duration": "5s", + "pipeline": 1, + "bandwidth": "4.00GB/s", + "input_bw": "186.20MB/s", + "reconnects": 499933, + "status_2xx": 12515627, + "status_3xx": 0, + "status_4xx": 0, + "status_5xx": 0 + }, + "json-comp-4096": { + "framework": "vanilla-epoll", + "language": "V", + "rps": 2530892, + "avg_latency": "1.38ms", + "p99_latency": "33.00ms", + "cpu": "5721.8%", + "memory": "150MiB", + "connections": 4096, + "threads": 64, + "duration": "5s", + "pipeline": 1, + "bandwidth": "4.04GB/s", + "input_bw": "188.26MB/s", + "reconnects": 505339, + "status_2xx": 12654460, + "status_3xx": 0, + "status_4xx": 0, + "status_5xx": 0 + }, + "json-tls-4096": { + "framework": "vanilla-epoll", + "language": "V", + "rps": 1609881, + "avg_latency": "13.83ms", + "p99_latency": "759.35ms", + "cpu": "5607.2%", + "memory": "307MiB", + "connections": 4096, + "threads": 64, + "duration": "5s", + "pipeline": 1, + "bandwidth": "5.45GB", + "reconnects": 0, + "status_2xx": 8205409, + "status_3xx": 0, + "status_4xx": 0, + "status_5xx": 0 + }, + "latency-10k-1024": { + "framework": "vanilla-epoll", + "language": "V", + "rps": 9981, + "avg_latency": "70.7us", + "p99_latency": "96.0us", + "cpu": "21.2%", + "memory": "58MiB", + "connections": 1024, + "threads": 64, + "duration": "20s", + "pipeline": 1, + "bandwidth": "1.06MB/s", + "reconnects": 0, + "status_2xx": 199647, + "status_3xx": 0, + "status_4xx": 0, + "status_5xx": 0, + "cpu_usec": 4448538, + "cpu_per_req_us": 22.282, + "target_rate": 10000, + "rate_ratio": 0.9981, + "p99_9_latency": "146.0us" + }, + "latency-1m-1024": { + "framework": "vanilla-epoll", + "language": "V", + "rps": 997951, + "avg_latency": "93.3us", + "p99_latency": "162.0us", + "cpu": "2133.2%", + "memory": "62MiB", + "connections": 1024, + "threads": 64, + "duration": "20s", + "pipeline": 1, + "bandwidth": "105.78MB/s", + "reconnects": 0, + "status_2xx": 19962814, + "status_3xx": 0, + "status_4xx": 0, + "status_5xx": 0, + "cpu_usec": 388582250, + "cpu_per_req_us": 19.4653, + "target_rate": 1000000, + "rate_ratio": 0.998, + "p99_9_latency": "3253.0us" + }, + "latency-500k-8cpu-1024": { + "framework": "vanilla-epoll", + "language": "V", + "rps": 498816, + "avg_latency": "806.9us", + "p99_latency": "8364.0us", + "cpu": "757.2%", + "memory": "39MiB", + "connections": 1024, + "threads": 64, + "duration": "20s", + "pipeline": 1, + "bandwidth": "52.87MB/s", + "reconnects": 0, + "status_2xx": 9978134, + "status_3xx": 0, + "status_4xx": 0, + "status_5xx": 0, + "cpu_usec": 144312521, + "cpu_per_req_us": 14.4629, + "target_rate": 500000, + "rate_ratio": 0.9976, + "p99_9_latency": "14476.0us" + }, + "limited-conn-4096": { + "framework": "vanilla-epoll", + "language": "V", + "rps": 1045265, + "avg_latency": "3.89ms", + "p99_latency": "40.30ms", + "cpu": "2938.2%", + "memory": "83MiB", + "connections": 4096, + "threads": 64, + "duration": "5s", + "pipeline": 1, + "bandwidth": "106.63MB/s", + "input_bw": "80.74MB/s", + "reconnects": 522729, + "status_2xx": 5226329, + "status_3xx": 0, + "status_4xx": 0, + "status_5xx": 0 + }, + "pipelined-4096": { + "framework": "vanilla-epoll", + "language": "V", + "rps": 40088672, + "avg_latency": "1.63ms", + "p99_latency": "1.84ms", + "cpu": "6369.8%", + "memory": "134MiB", + "connections": 4096, + "threads": 64, + "duration": "5s", + "pipeline": 16, + "bandwidth": "3.99GB/s", + "reconnects": 0, + "status_2xx": 200443360, + "status_3xx": 0, + "status_4xx": 0, + "status_5xx": 0 + }, + "production-stack-1024": { + "framework": "vanilla-epoll", + "language": "V", + "rps": 198023, + "avg_latency": "83.11ms", + "p99_latency": "475.44ms", + "cpu": "3420.9%", + "memory": "2.1GiB", + "connections": 1024, + "threads": 64, + "duration": "5s", + "pipeline": 1, + "bandwidth": "2.16GB/s", + "reconnects": 0, + "status_2xx": 1001997, + "status_3xx": 0, + "status_4xx": 0, + "status_5xx": 0, + "tpl_static": 300599, + "tpl_baseline": 100199, + "tpl_items": 500998, + "tpl_me": 100199, + "cpu_breakdown": "cache: 0% 5MiB | authsvc: 739% 590MiB | edge: 2358% 1.3GiB | server: 323% 172MiB" + }, + "production-stack-256": { + "framework": "vanilla-epoll", + "language": "V", + "rps": 241873, + "avg_latency": "20.25ms", + "p99_latency": "115.42ms", + "cpu": "3838.9%", + "memory": "1.2GiB", + "connections": 256, + "threads": 64, + "duration": "5s", + "pipeline": 1, + "bandwidth": "2.44GB/s", + "reconnects": 0, + "status_2xx": 1216624, + "status_3xx": 0, + "status_4xx": 0, + "status_5xx": 0, + "tpl_static": 364987, + "tpl_baseline": 121662, + "tpl_items": 608312, + "tpl_me": 121662, + "cpu_breakdown": "cache: 0% 14MiB | authsvc: 731% 146MiB | edge: 2624% 993MiB | server: 484% 95MiB" + }, + "static-tls-1024": { + "framework": "vanilla-epoll", + "language": "V", + "rps": 1104765, + "avg_latency": "1.52ms", + "p99_latency": "182.98ms", + "cpu": "6230.5%", + "memory": "112MiB", + "connections": 1024, + "threads": 64, + "duration": "5s", + "pipeline": 1, + "bandwidth": "16.97GB", + "reconnects": 0, + "status_2xx": 5633644, + "status_3xx": 0, + "status_4xx": 0, + "status_5xx": 0 + } + } +} diff --git a/site/data/results/vanilla-h2c.json b/site/data/results/vanilla-h2c.json new file mode 100644 index 000000000..21c4045ec --- /dev/null +++ b/site/data/results/vanilla-h2c.json @@ -0,0 +1,138 @@ +{ + "framework": "vanilla-h2c", + "results": { + "baseline-h2c-1024": { + "framework": "vanilla-h2c", + "language": "V", + "rps": 15460256, + "avg_latency": "4.05ms", + "p99_latency": "111.80ms", + "cpu": "2476.8%", + "memory": "206MiB", + "connections": 1024, + "threads": 64, + "duration": "5s", + "pipeline": 1, + "bandwidth": "671.45MB/s", + "reconnects": 0, + "status_2xx": 78228900, + "status_3xx": 0, + "status_4xx": 0, + "status_5xx": 0 + }, + "baseline-h2c-256": { + "framework": "vanilla-h2c", + "language": "V", + "rps": 15749463, + "avg_latency": "840us", + "p99_latency": "20.51ms", + "cpu": "2121.9%", + "memory": "118MiB", + "connections": 256, + "threads": 64, + "duration": "5s", + "pipeline": 1, + "bandwidth": "679.95MB/s", + "reconnects": 0, + "status_2xx": 79219800, + "status_3xx": 0, + "status_4xx": 0, + "status_5xx": 0 + }, + "baseline-h2c-4096": { + "framework": "vanilla-h2c", + "language": "V", + "rps": 12653654, + "avg_latency": "32.35ms", + "p99_latency": "533.31ms", + "cpu": "2422.0%", + "memory": "1.3GiB", + "connections": 4096, + "threads": 64, + "duration": "5s", + "pipeline": 1, + "bandwidth": "552.83MB/s", + "reconnects": 0, + "status_2xx": 64407100, + "status_3xx": 0, + "status_4xx": 0, + "status_5xx": 0 + }, + "json-h2c-1024": { + "framework": "vanilla-h2c", + "language": "V", + "rps": 4670555, + "avg_latency": "5.33ms", + "p99_latency": "61.19ms", + "cpu": "6294.9%", + "memory": "541MiB", + "connections": 1024, + "threads": 64, + "duration": "5s", + "pipeline": 1, + "bandwidth": "15.74GB/s", + "reconnects": 0, + "status_2xx": 23679716, + "status_3xx": 0, + "status_4xx": 0, + "status_5xx": 0 + }, + "json-h2c-4096": { + "framework": "vanilla-h2c", + "language": "V", + "rps": 3807159, + "avg_latency": "35.12ms", + "p99_latency": "314.59ms", + "cpu": "6030.8%", + "memory": "1.9GiB", + "connections": 4096, + "threads": 64, + "duration": "5s", + "pipeline": 1, + "bandwidth": "13.06GB/s", + "reconnects": 0, + "status_2xx": 19644944, + "status_3xx": 0, + "status_4xx": 0, + "status_5xx": 0 + }, + "unary-grpc-1024": { + "framework": "vanilla-h2c", + "language": "V", + "rps": 7092189, + "avg_latency": "8.55ms", + "p99_latency": "121.70ms", + "cpu": "1436.3%", + "memory": "224MiB", + "connections": 1024, + "threads": 64, + "duration": "5s", + "pipeline": 1, + "bandwidth": "644.69MB/s", + "reconnects": 0, + "status_2xx": 35957400, + "status_3xx": 0, + "status_4xx": 0, + "status_5xx": 0 + }, + "unary-grpc-256": { + "framework": "vanilla-h2c", + "language": "V", + "rps": 7323273, + "avg_latency": "2.08ms", + "p99_latency": "21.85ms", + "cpu": "1380.6%", + "memory": "165MiB", + "connections": 256, + "threads": 64, + "duration": "5s", + "pipeline": 1, + "bandwidth": "661.75MB/s", + "reconnects": 0, + "status_2xx": 36909300, + "status_3xx": 0, + "status_4xx": 0, + "status_5xx": 0 + } + } +} diff --git a/site/data/results/vanilla-io_uring.json b/site/data/results/vanilla-io_uring.json new file mode 100644 index 000000000..dc2a3ebfb --- /dev/null +++ b/site/data/results/vanilla-io_uring.json @@ -0,0 +1,298 @@ +{ + "framework": "vanilla-io_uring", + "results": { + "8gbit-512": { + "framework": "vanilla-io_uring", + "language": "V", + "rps": 49118, + "avg_latency": "326.4us", + "p99_latency": "235.0us", + "cpu": "415.7%", + "memory": "673MiB", + "connections": 512, + "threads": 64, + "duration": "5s", + "pipeline": 1, + "bandwidth": "509.01MB/s", + "input_bw": "479.67MB/s", + "reconnects": 0, + "status_2xx": 245709, + "status_3xx": 0, + "status_4xx": 0, + "status_5xx": 0, + "cpu_usec": 23635093, + "cpu_per_req_us": 96.1914, + "target_rate": 50000, + "rate_ratio": 0.9824, + "p99_9_latency": "48560.0us" + }, + "async-32000": { + "framework": "vanilla-io_uring", + "language": "V", + "rps": 2734750, + "avg_latency": "11.60ms", + "p99_latency": "14.00ms", + "cpu": "5628.4%", + "memory": "2.0GiB", + "connections": 32000, + "threads": 64, + "duration": "5s", + "pipeline": 1, + "bandwidth": "279.01MB/s", + "input_bw": "125.19MB/s", + "reconnects": 0, + "status_2xx": 27347504, + "status_3xx": 0, + "status_4xx": 0, + "status_5xx": 0 + }, + "async-db-1024": { + "framework": "vanilla-io_uring", + "language": "V", + "rps": 317554, + "avg_latency": "1.21ms", + "p99_latency": "8.59ms", + "cpu": "3102.2%", + "memory": "693MiB", + "connections": 1024, + "threads": 64, + "duration": "5s", + "pipeline": 1, + "bandwidth": "1.20GB/s", + "input_bw": "21.20MB/s", + "reconnects": 127176, + "status_2xx": 3175548, + "status_3xx": 0, + "status_4xx": 0, + "status_5xx": 0 + }, + "baseline-4096": { + "framework": "vanilla-io_uring", + "language": "V", + "rps": 4307987, + "avg_latency": "950us", + "p99_latency": "1.25ms", + "cpu": "6128.8%", + "memory": "641MiB", + "connections": 4096, + "threads": 64, + "duration": "5s", + "pipeline": 1, + "bandwidth": "439.27MB/s", + "input_bw": "332.78MB/s", + "reconnects": 0, + "status_2xx": 21539938, + "status_3xx": 0, + "status_4xx": 0, + "status_5xx": 0 + }, + "fortunes-1024": { + "framework": "vanilla-io_uring", + "language": "V", + "rps": 176058, + "avg_latency": "4.33ms", + "p99_latency": "10.00ms", + "cpu": "6017.9%", + "memory": "782MiB", + "connections": 1024, + "threads": 64, + "duration": "5s", + "pipeline": 1, + "bandwidth": "4.08GB/s", + "reconnects": 0, + "status_2xx": 880293, + "status_3xx": 0, + "status_4xx": 0, + "status_5xx": 0 + }, + "json-comp-16384": { + "framework": "vanilla-io_uring", + "language": "V", + "rps": 2676274, + "avg_latency": "5.27ms", + "p99_latency": "13.00ms", + "cpu": "5488.5%", + "memory": "990MiB", + "connections": 16384, + "threads": 64, + "duration": "5s", + "pipeline": 1, + "bandwidth": "4.27GB/s", + "input_bw": "199.08MB/s", + "reconnects": 527381, + "status_2xx": 13381373, + "status_3xx": 0, + "status_4xx": 0, + "status_5xx": 0 + }, + "json-comp-4096": { + "framework": "vanilla-io_uring", + "language": "V", + "rps": 2862233, + "avg_latency": "906us", + "p99_latency": "2.87ms", + "cpu": "5909.5%", + "memory": "741MiB", + "connections": 4096, + "threads": 64, + "duration": "5s", + "pipeline": 1, + "bandwidth": "4.57GB/s", + "input_bw": "212.91MB/s", + "reconnects": 570590, + "status_2xx": 14311169, + "status_3xx": 0, + "status_4xx": 0, + "status_5xx": 0 + }, + "json-tls-4096": { + "framework": "vanilla-io_uring", + "language": "V", + "rps": 1533275, + "avg_latency": "14.84ms", + "p99_latency": "680.54ms", + "cpu": "5249.2%", + "memory": "969MiB", + "connections": 4096, + "threads": 64, + "duration": "5s", + "pipeline": 1, + "bandwidth": "5.19GB", + "reconnects": 0, + "status_2xx": 7815548, + "status_3xx": 0, + "status_4xx": 0, + "status_5xx": 0 + }, + "latency-10k-1024": { + "framework": "vanilla-io_uring", + "language": "V", + "rps": 9979, + "avg_latency": "70.6us", + "p99_latency": "101.0us", + "cpu": "20.9%", + "memory": "570MiB", + "connections": 1024, + "threads": 64, + "duration": "20s", + "pipeline": 1, + "bandwidth": "1.06MB/s", + "reconnects": 0, + "status_2xx": 199609, + "status_3xx": 0, + "status_4xx": 0, + "status_5xx": 0, + "cpu_usec": 4382329, + "cpu_per_req_us": 21.9546, + "target_rate": 10000, + "rate_ratio": 0.9979, + "p99_9_latency": "219.0us" + }, + "latency-1m-1024": { + "framework": "vanilla-io_uring", + "language": "V", + "rps": 997694, + "avg_latency": "90.5us", + "p99_latency": "164.0us", + "cpu": "2145.0%", + "memory": "571MiB", + "connections": 1024, + "threads": 64, + "duration": "20s", + "pipeline": 1, + "bandwidth": "105.76MB/s", + "reconnects": 0, + "status_2xx": 19957073, + "status_3xx": 0, + "status_4xx": 0, + "status_5xx": 0, + "cpu_usec": 390283741, + "cpu_per_req_us": 19.5562, + "target_rate": 1000000, + "rate_ratio": 0.9977, + "p99_9_latency": "314.0us" + }, + "latency-500k-8cpu-1024": { + "framework": "vanilla-io_uring", + "language": "V", + "rps": 498915, + "avg_latency": "546.2us", + "p99_latency": "3935.0us", + "cpu": "806.5%", + "memory": "109MiB", + "connections": 1024, + "threads": 64, + "duration": "20s", + "pipeline": 1, + "bandwidth": "52.88MB/s", + "reconnects": 0, + "status_2xx": 9980173, + "status_3xx": 0, + "status_4xx": 0, + "status_5xx": 0, + "cpu_usec": 152964033, + "cpu_per_req_us": 15.3268, + "target_rate": 500000, + "rate_ratio": 0.9978, + "p99_9_latency": "12636.0us" + }, + "limited-conn-4096": { + "framework": "vanilla-io_uring", + "language": "V", + "rps": 2685418, + "avg_latency": "1.39ms", + "p99_latency": "2.14ms", + "cpu": "5518.8%", + "memory": "763MiB", + "connections": 4096, + "threads": 64, + "duration": "5s", + "pipeline": 1, + "bandwidth": "273.94MB/s", + "input_bw": "207.44MB/s", + "reconnects": 1342825, + "status_2xx": 13427094, + "status_3xx": 0, + "status_4xx": 0, + "status_5xx": 0 + }, + "pipelined-4096": { + "framework": "vanilla-io_uring", + "language": "V", + "rps": 43693484, + "avg_latency": "1.50ms", + "p99_latency": "1.97ms", + "cpu": "6409.2%", + "memory": "638MiB", + "connections": 4096, + "threads": 64, + "duration": "5s", + "pipeline": 16, + "bandwidth": "4.35GB/s", + "reconnects": 0, + "status_2xx": 218467424, + "status_3xx": 0, + "status_4xx": 0, + "status_5xx": 0 + }, + "static-tls-1024": { + "framework": "vanilla-io_uring", + "language": "V", + "rps": 1112233, + "avg_latency": "1.50ms", + "p99_latency": "176.58ms", + "cpu": "6305.1%", + "memory": "694MiB", + "connections": 1024, + "threads": 64, + "duration": "5s", + "pipeline": 1, + "bandwidth": "17.08GB", + "reconnects": 0, + "status_2xx": 5672613, + "status_3xx": 0, + "status_4xx": 0, + "status_5xx": 0 + } + } +} diff --git a/site/data/results/vanilla-ws.json b/site/data/results/vanilla-ws.json new file mode 100644 index 000000000..fb0ff8745 --- /dev/null +++ b/site/data/results/vanilla-ws.json @@ -0,0 +1,157 @@ +{ + "framework": "vanilla-ws", + "results": { + "echo-ws-16384": { + "framework": "vanilla-ws", + "language": "V", + "rps": 4066664, + "avg_latency": "3.90ms", + "p99_latency": "4.18ms", + "cpu": "6409.7%", + "memory": "373MiB", + "connections": 16384, + "threads": 64, + "duration": "5s", + "pipeline": 1, + "bandwidth": "27.54MB/s", + "reconnects": 0, + "status_2xx": 20333321, + "status_3xx": 0, + "status_4xx": 0, + "status_5xx": 0 + }, + "echo-ws-4096": { + "framework": "vanilla-ws", + "language": "V", + "rps": 4287978, + "avg_latency": "945us", + "p99_latency": "1.02ms", + "cpu": "6098.0%", + "memory": "102MiB", + "connections": 4096, + "threads": 64, + "duration": "5s", + "pipeline": 1, + "bandwidth": "28.70MB/s", + "reconnects": 0, + "status_2xx": 21439893, + "status_3xx": 0, + "status_4xx": 0, + "status_5xx": 0 + }, + "echo-ws-512": { + "framework": "vanilla-ws", + "language": "V", + "rps": 4329153, + "avg_latency": "117us", + "p99_latency": "149us", + "cpu": "6423.5%", + "memory": "43MiB", + "connections": 512, + "threads": 64, + "duration": "5s", + "pipeline": 1, + "bandwidth": "28.89MB/s", + "reconnects": 0, + "status_2xx": 21645768, + "status_3xx": 0, + "status_4xx": 0, + "status_5xx": 0 + }, + "echo-ws-limited-4096": { + "framework": "vanilla-ws", + "language": "V", + "rps": 1012444, + "avg_latency": "49us", + "p99_latency": "125us", + "cpu": "3453.3%", + "memory": "746MiB", + "connections": 4096, + "threads": 64, + "duration": "5s", + "pipeline": 1, + "bandwidth": "19.21MB/s", + "reconnects": 506223, + "status_2xx": 5062221, + "status_3xx": 0, + "status_4xx": 0, + "status_5xx": 0 + }, + "echo-ws-limited-512": { + "framework": "vanilla-ws", + "language": "V", + "rps": 1013549, + "avg_latency": "48us", + "p99_latency": "111us", + "cpu": "3477.0%", + "memory": "1.2GiB", + "connections": 512, + "threads": 64, + "duration": "5s", + "pipeline": 1, + "bandwidth": "19.23MB/s", + "reconnects": 506772, + "status_2xx": 5067746, + "status_3xx": 0, + "status_4xx": 0, + "status_5xx": 0 + }, + "echo-ws-pipeline-16384": { + "framework": "vanilla-ws", + "language": "V", + "rps": 60761495, + "avg_latency": "4.23ms", + "p99_latency": "7.52ms", + "cpu": "6290.3%", + "memory": "373MiB", + "connections": 16384, + "threads": 64, + "duration": "5s", + "pipeline": 16, + "bandwidth": "405.86MB/s", + "reconnects": 0, + "status_2xx": 303807476, + "status_3xx": 0, + "status_4xx": 0, + "status_5xx": 0 + }, + "echo-ws-pipeline-4096": { + "framework": "vanilla-ws", + "language": "V", + "rps": 64150975, + "avg_latency": "1.02ms", + "p99_latency": "1.14ms", + "cpu": "6159.6%", + "memory": "121MiB", + "connections": 4096, + "threads": 64, + "duration": "5s", + "pipeline": 16, + "bandwidth": "428.18MB/s", + "reconnects": 0, + "status_2xx": 320754879, + "status_3xx": 0, + "status_4xx": 0, + "status_5xx": 0 + }, + "echo-ws-pipeline-512": { + "framework": "vanilla-ws", + "language": "V", + "rps": 65963734, + "avg_latency": "123us", + "p99_latency": "157us", + "cpu": "6470.8%", + "memory": "41MiB", + "connections": 512, + "threads": 64, + "duration": "5s", + "pipeline": 16, + "bandwidth": "440.29MB/s", + "reconnects": 0, + "status_2xx": 329818672, + "status_3xx": 0, + "status_4xx": 0, + "status_5xx": 0 + } + } +} diff --git a/site/data/tls/vanilla-epoll.json b/site/data/tls/vanilla-epoll.json new file mode 100644 index 000000000..8b84b4d67 --- /dev/null +++ b/site/data/tls/vanilla-epoll.json @@ -0,0 +1,5 @@ +{ + "framework": "vanilla-epoll", + "tls": "pass", + "check": "none" +} diff --git a/site/data/tls/vanilla-io_uring.json b/site/data/tls/vanilla-io_uring.json new file mode 100644 index 000000000..7216c2ca4 --- /dev/null +++ b/site/data/tls/vanilla-io_uring.json @@ -0,0 +1,5 @@ +{ + "framework": "vanilla-io_uring", + "tls": "pass", + "check": "none" +} diff --git a/site/static/logs/8gbit/512/vanilla-epoll.log b/site/static/logs/8gbit/512/vanilla-epoll.log new file mode 100644 index 000000000..7c2b25c7a --- /dev/null +++ b/site/static/logs/8gbit/512/vanilla-epoll.log @@ -0,0 +1,7 @@ +[socket] SO_REUSEPORT enabled for load balancing +[socket] SO_REUSEPORT enabled for load balancing +[socket] Binding to 0.0.0.0:8081 +[socket] Binding to 0.0.0.0:8080 +listening on http://localhost:8080/ +listening on http://localhost:8081/ +[ktls] engaged: kernel TLS TX+RX (TLS 1.3, AES-128-GCM) diff --git a/site/static/logs/8gbit/512/vanilla-io_uring.log b/site/static/logs/8gbit/512/vanilla-io_uring.log new file mode 100644 index 000000000..a71290593 --- /dev/null +++ b/site/static/logs/8gbit/512/vanilla-io_uring.log @@ -0,0 +1,133 @@ +[socket] Binding to 0.0.0.0:8081 +[socket] SO_REUSEPORT enabled for load balancing +[socket] SO_REUSEPORT enabled for load balancing +[socket] SO_REUSEPORT enabled for load balancing +[socket] SO_REUSEPORT enabled for load balancing +[socket] SO_REUSEPORT enabled for load balancing +[socket] SO_REUSEPORT enabled for load balancing +[socket] SO_REUSEPORT enabled for load balancing +[socket] SO_REUSEPORT enabled for load balancing +[socket] Binding to 0.0.0.0:8080 +[socket] Binding to 0.0.0.0:8080 +[socket] Binding to 0.0.0.0:8080 +[socket] Binding to 0.0.0.0:8080 +[socket] Binding to 0.0.0.0:8080 +[socket] Binding to 0.0.0.0:8080 +[socket] Binding to 0.0.0.0:8080 +[socket] SO_REUSEPORT enabled for load balancing +[socket] SO_REUSEPORT enabled for load balancing +[socket] Binding to 0.0.0.0:8080 +[socket] Binding to 0.0.0.0:8080 +[socket] SO_REUSEPORT enabled for load balancing +[socket] Binding to 0.0.0.0:8080 +[socket] Binding to 0.0.0.0:8080 +[socket] SO_REUSEPORT enabled for load balancing +[socket] Binding to 0.0.0.0:8080 +[socket] SO_REUSEPORT enabled for load balancing +[socket] Binding to 0.0.0.0:8080 +[socket] Binding to 0.0.0.0:8080 +[socket] Binding to 0.0.0.0:8080 +[socket] Binding to 0.0.0.0:8080 +[socket] SO_REUSEPORT enabled for load balancing +[socket] SO_REUSEPORT enabled for load balancing +[socket] SO_REUSEPORT enabled for load balancing +[socket] SO_REUSEPORT enabled for load balancing +[socket] SO_REUSEPORT enabled for load balancing +[socket] Binding to 0.0.0.0:8080 +[socket] SO_REUSEPORT enabled for load balancing +[socket] SO_REUSEPORT enabled for load balancing +[socket] SO_REUSEPORT enabled for load balancing +[socket] Binding to 0.0.0.0:8080 +[socket] Binding to 0.0.0.0:8080 +[socket] Binding to 0.0.0.0:8080 +[socket] Binding to 0.0.0.0:8080 +[socket] SO_REUSEPORT enabled for load balancing +[socket] SO_REUSEPORT enabled for load balancing +[socket] Binding to 0.0.0.0:8080 +[socket] Binding to 0.0.0.0:8080 +[socket] SO_REUSEPORT enabled for load balancing +[socket] Binding to 0.0.0.0:8080 +[socket] SO_REUSEPORT enabled for load balancing +[socket] SO_REUSEPORT enabled for load balancing +[socket] SO_REUSEPORT enabled for load balancing +[socket] SO_REUSEPORT enabled for load balancing +[socket] SO_REUSEPORT enabled for load balancing +[socket] Binding to 0.0.0.0:8080 +[socket] Binding to 0.0.0.0:8080 +[socket] Binding to 0.0.0.0:8080 +[socket] Binding to 0.0.0.0:8080 +[socket] SO_REUSEPORT enabled for load balancing +[socket] Binding to 0.0.0.0:8080 +[socket] SO_REUSEPORT enabled for load balancing +[socket] Binding to 0.0.0.0:8080 +[socket] SO_REUSEPORT enabled for load balancing +[socket] Binding to 0.0.0.0:8080 +[socket] SO_REUSEPORT enabled for load balancing +[socket] Binding to 0.0.0.0:8080 +[socket] SO_REUSEPORT enabled for load balancing +[socket] Binding to 0.0.0.0:8080 +[socket] SO_REUSEPORT enabled for load balancing +[socket] Binding to 0.0.0.0:8080 +[socket] Binding to 0.0.0.0:8080 +[socket] Binding to 0.0.0.0:8080 +[socket] Binding to 0.0.0.0:8080 +[socket] SO_REUSEPORT enabled for load balancing +[socket] SO_REUSEPORT enabled for load balancing +[socket] SO_REUSEPORT enabled for load balancing +[socket] SO_REUSEPORT enabled for load balancing +[socket] Binding to 0.0.0.0:8080 +[socket] SO_REUSEPORT enabled for load balancing +[socket] Binding to 0.0.0.0:8080 +[socket] SO_REUSEPORT enabled for load balancing +[socket] Binding to 0.0.0.0:8080 +[socket] SO_REUSEPORT enabled for load balancing +[socket] Binding to 0.0.0.0:8080 +[socket] SO_REUSEPORT enabled for load balancing +[socket] Binding to 0.0.0.0:8080 +[socket] SO_REUSEPORT enabled for load balancing +[socket] Binding to 0.0.0.0:8080 +[socket] Binding to 0.0.0.0:8080 +[socket] Binding to 0.0.0.0:8080 +[socket] Binding to 0.0.0.0:8080 +[socket] SO_REUSEPORT enabled for load balancing +[socket] SO_REUSEPORT enabled for load balancing +[socket] Binding to 0.0.0.0:8080 +[socket] SO_REUSEPORT enabled for load balancing +[socket] SO_REUSEPORT enabled for load balancing +[socket] SO_REUSEPORT enabled for load balancing +[socket] SO_REUSEPORT enabled for load balancing +[socket] Binding to 0.0.0.0:8080 +[socket] Binding to 0.0.0.0:8080 +[socket] SO_REUSEPORT enabled for load balancing +[socket] Binding to 0.0.0.0:8080 +[socket] SO_REUSEPORT enabled for load balancing +[socket] Binding to 0.0.0.0:8080 +[socket] Binding to 0.0.0.0:8080 +[socket] SO_REUSEPORT enabled for load balancing +[socket] SO_REUSEPORT enabled for load balancing +[socket] SO_REUSEPORT enabled for load balancing +[socket] SO_REUSEPORT enabled for load balancing +[socket] Binding to 0.0.0.0:8080 +[socket] Binding to 0.0.0.0:8080 +[socket] Binding to 0.0.0.0:8080 +[socket] SO_REUSEPORT enabled for load balancing +[socket] Binding to 0.0.0.0:8080 +[socket] SO_REUSEPORT enabled for load balancing +[socket] Binding to 0.0.0.0:8080 +[socket] Binding to 0.0.0.0:8080 +[socket] SO_REUSEPORT enabled for load balancing +[socket] Binding to 0.0.0.0:8080 +[socket] SO_REUSEPORT enabled for load balancing +[socket] SO_REUSEPORT enabled for load balancing +[socket] Binding to 0.0.0.0:8080 +[socket] SO_REUSEPORT enabled for load balancing +[socket] Binding to 0.0.0.0:8080 +[socket] SO_REUSEPORT enabled for load balancing +[socket] Binding to 0.0.0.0:8080 +[socket] SO_REUSEPORT enabled for load balancing +[socket] Binding to 0.0.0.0:8080 +[socket] SO_REUSEPORT enabled for load balancing +[socket] Binding to 0.0.0.0:8080 +listening on http://localhost:8081/ +[ktls] engaged: kernel TLS TX+RX (TLS 1.3, AES-128-GCM) +listening on http://localhost:8080/ (io_uring) diff --git a/site/static/logs/async-db/1024/vanilla-epoll.log b/site/static/logs/async-db/1024/vanilla-epoll.log index 9de548a21..dee8f8a58 100644 --- a/site/static/logs/async-db/1024/vanilla-epoll.log +++ b/site/static/logs/async-db/1024/vanilla-epoll.log @@ -2,5 +2,5 @@ [socket] SO_REUSEPORT enabled for load balancing [socket] Binding to 0.0.0.0:8080 [socket] SO_REUSEPORT enabled for load balancing -listening on http://localhost:8081/ listening on http://localhost:8080/ +listening on http://localhost:8081/ diff --git a/site/static/logs/async-db/1024/vanilla-io_uring.log b/site/static/logs/async-db/1024/vanilla-io_uring.log index cf1482402..05df8e4ea 100644 --- a/site/static/logs/async-db/1024/vanilla-io_uring.log +++ b/site/static/logs/async-db/1024/vanilla-io_uring.log @@ -1,32 +1,17 @@ +[socket] SO_REUSEPORT enabled for load balancing [socket] Binding to 0.0.0.0:8081 [socket] SO_REUSEPORT enabled for load balancing -[socket] Binding to 0.0.0.0:8080 [socket] SO_REUSEPORT enabled for load balancing -[socket] Binding to 0.0.0.0:8080 -[socket] SO_REUSEPORT enabled for load balancing -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 [socket] SO_REUSEPORT enabled for load balancing [socket] SO_REUSEPORT enabled for load balancing [socket] SO_REUSEPORT enabled for load balancing [socket] SO_REUSEPORT enabled for load balancing [socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] Binding to 0.0.0.0:8080 [socket] Binding to 0.0.0.0:8080 [socket] Binding to 0.0.0.0:8080 [socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing [socket] SO_REUSEPORT enabled for load balancing [socket] Binding to 0.0.0.0:8080 -[socket] SO_REUSEPORT enabled for load balancing [socket] Binding to 0.0.0.0:8080 [socket] SO_REUSEPORT enabled for load balancing [socket] Binding to 0.0.0.0:8080 @@ -35,29 +20,8 @@ [socket] Binding to 0.0.0.0:8080 [socket] Binding to 0.0.0.0:8080 [socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing [socket] SO_REUSEPORT enabled for load balancing [socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 -[socket] SO_REUSEPORT enabled for load balancing [socket] Binding to 0.0.0.0:8080 [socket] Binding to 0.0.0.0:8080 [socket] Binding to 0.0.0.0:8080 @@ -66,47 +30,19 @@ [socket] SO_REUSEPORT enabled for load balancing [socket] SO_REUSEPORT enabled for load balancing [socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 [socket] Binding to 0.0.0.0:8080 [socket] SO_REUSEPORT enabled for load balancing +[socket] Binding to 0.0.0.0:8080 [socket] SO_REUSEPORT enabled for load balancing [socket] SO_REUSEPORT enabled for load balancing [socket] SO_REUSEPORT enabled for load balancing [socket] SO_REUSEPORT enabled for load balancing -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 [socket] SO_REUSEPORT enabled for load balancing [socket] SO_REUSEPORT enabled for load balancing [socket] SO_REUSEPORT enabled for load balancing [socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 [socket] SO_REUSEPORT enabled for load balancing +[socket] Binding to 0.0.0.0:8080 [socket] SO_REUSEPORT enabled for load balancing [socket] Binding to 0.0.0.0:8080 [socket] Binding to 0.0.0.0:8080 @@ -116,39 +52,14 @@ [socket] Binding to 0.0.0.0:8080 [socket] Binding to 0.0.0.0:8080 [socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] Binding to 0.0.0.0:8080 [socket] Binding to 0.0.0.0:8080 [socket] SO_REUSEPORT enabled for load balancing [socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 [socket] SO_REUSEPORT enabled for load balancing [socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 [socket] SO_REUSEPORT enabled for load balancing [socket] Binding to 0.0.0.0:8080 [socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 [socket] Binding to 0.0.0.0:8080 [socket] SO_REUSEPORT enabled for load balancing [socket] SO_REUSEPORT enabled for load balancing @@ -160,22 +71,12 @@ [socket] Binding to 0.0.0.0:8080 [socket] SO_REUSEPORT enabled for load balancing [socket] SO_REUSEPORT enabled for load balancing -[socket] Binding to 0.0.0.0:8080 -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] Binding to 0.0.0.0:8080 [socket] SO_REUSEPORT enabled for load balancing -[socket] Binding to 0.0.0.0:8080 [socket] SO_REUSEPORT enabled for load balancing [socket] Binding to 0.0.0.0:8080 [socket] Binding to 0.0.0.0:8080 [socket] Binding to 0.0.0.0:8080 [socket] Binding to 0.0.0.0:8080 -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing [socket] Binding to 0.0.0.0:8080 [socket] Binding to 0.0.0.0:8080 [socket] Binding to 0.0.0.0:8080 @@ -185,13 +86,6 @@ [socket] SO_REUSEPORT enabled for load balancing [socket] SO_REUSEPORT enabled for load balancing [socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] Binding to 0.0.0.0:8080 -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 [socket] Binding to 0.0.0.0:8080 [socket] Binding to 0.0.0.0:8080 [socket] Binding to 0.0.0.0:8080 @@ -201,47 +95,27 @@ [socket] Binding to 0.0.0.0:8080 [socket] Binding to 0.0.0.0:8080 [socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 -[socket] SO_REUSEPORT enabled for load balancing [socket] SO_REUSEPORT enabled for load balancing [socket] SO_REUSEPORT enabled for load balancing -[socket] Binding to 0.0.0.0:8080 -[socket] SO_REUSEPORT enabled for load balancing [socket] SO_REUSEPORT enabled for load balancing [socket] SO_REUSEPORT enabled for load balancing -[socket] Binding to 0.0.0.0:8080 [socket] SO_REUSEPORT enabled for load balancing [socket] Binding to 0.0.0.0:8080 [socket] Binding to 0.0.0.0:8080 -[socket] SO_REUSEPORT enabled for load balancing [socket] Binding to 0.0.0.0:8080 -[socket] SO_REUSEPORT enabled for load balancing [socket] Binding to 0.0.0.0:8080 [socket] Binding to 0.0.0.0:8080 -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing [socket] Binding to 0.0.0.0:8080 -[socket] SO_REUSEPORT enabled for load balancing [socket] Binding to 0.0.0.0:8080 -[socket] SO_REUSEPORT enabled for load balancing [socket] Binding to 0.0.0.0:8080 [socket] SO_REUSEPORT enabled for load balancing [socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing [socket] Binding to 0.0.0.0:8080 [socket] SO_REUSEPORT enabled for load balancing [socket] Binding to 0.0.0.0:8080 [socket] SO_REUSEPORT enabled for load balancing [socket] Binding to 0.0.0.0:8080 [socket] SO_REUSEPORT enabled for load balancing -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 -[socket] SO_REUSEPORT enabled for load balancing [socket] SO_REUSEPORT enabled for load balancing [socket] SO_REUSEPORT enabled for load balancing [socket] Binding to 0.0.0.0:8080 @@ -250,9 +124,7 @@ [socket] SO_REUSEPORT enabled for load balancing [socket] SO_REUSEPORT enabled for load balancing [socket] SO_REUSEPORT enabled for load balancing -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 +[socket] SO_REUSEPORT enabled for load balancing [socket] SO_REUSEPORT enabled for load balancing [socket] Binding to 0.0.0.0:8080 [socket] Binding to 0.0.0.0:8080 diff --git a/site/static/logs/async/32000/vanilla-epoll.log b/site/static/logs/async/32000/vanilla-epoll.log new file mode 100644 index 000000000..9de548a21 --- /dev/null +++ b/site/static/logs/async/32000/vanilla-epoll.log @@ -0,0 +1,6 @@ +[socket] Binding to 0.0.0.0:8081 +[socket] SO_REUSEPORT enabled for load balancing +[socket] Binding to 0.0.0.0:8080 +[socket] SO_REUSEPORT enabled for load balancing +listening on http://localhost:8081/ +listening on http://localhost:8080/ diff --git a/site/static/logs/async/32000/vanilla-io_uring.log b/site/static/logs/async/32000/vanilla-io_uring.log new file mode 100644 index 000000000..6ecf926ba --- /dev/null +++ b/site/static/logs/async/32000/vanilla-io_uring.log @@ -0,0 +1,132 @@ +[socket] Binding to 0.0.0.0:8081 +[socket] SO_REUSEPORT enabled for load balancing +[socket] Binding to 0.0.0.0:8080 +[socket] Binding to 0.0.0.0:8080 +[socket] Binding to 0.0.0.0:8080 +[socket] Binding to 0.0.0.0:8080 +[socket] SO_REUSEPORT enabled for load balancing +[socket] SO_REUSEPORT enabled for load balancing +[socket] SO_REUSEPORT enabled for load balancing +[socket] SO_REUSEPORT enabled for load balancing +[socket] SO_REUSEPORT enabled for load balancing +[socket] Binding to 0.0.0.0:8080 +[socket] SO_REUSEPORT enabled for load balancing +[socket] SO_REUSEPORT enabled for load balancing +[socket] Binding to 0.0.0.0:8080 +[socket] Binding to 0.0.0.0:8080 +[socket] SO_REUSEPORT enabled for load balancing +[socket] SO_REUSEPORT enabled for load balancing +[socket] SO_REUSEPORT enabled for load balancing +[socket] Binding to 0.0.0.0:8080 +[socket] Binding to 0.0.0.0:8080 +[socket] Binding to 0.0.0.0:8080 +[socket] Binding to 0.0.0.0:8080 +[socket] Binding to 0.0.0.0:8080 +[socket] Binding to 0.0.0.0:8080 +[socket] SO_REUSEPORT enabled for load balancing +[socket] Binding to 0.0.0.0:8080 +[socket] SO_REUSEPORT enabled for load balancing +[socket] SO_REUSEPORT enabled for load balancing +[socket] SO_REUSEPORT enabled for load balancing +[socket] Binding to 0.0.0.0:8080 +[socket] SO_REUSEPORT enabled for load balancing +[socket] Binding to 0.0.0.0:8080 +[socket] SO_REUSEPORT enabled for load balancing +[socket] Binding to 0.0.0.0:8080 +[socket] SO_REUSEPORT enabled for load balancing +[socket] Binding to 0.0.0.0:8080 +[socket] Binding to 0.0.0.0:8080 +[socket] SO_REUSEPORT enabled for load balancing +[socket] SO_REUSEPORT enabled for load balancing +[socket] SO_REUSEPORT enabled for load balancing +[socket] SO_REUSEPORT enabled for load balancing +[socket] SO_REUSEPORT enabled for load balancing +[socket] Binding to 0.0.0.0:8080 +[socket] SO_REUSEPORT enabled for load balancing +[socket] Binding to 0.0.0.0:8080 +[socket] SO_REUSEPORT enabled for load balancing +[socket] Binding to 0.0.0.0:8080 +[socket] Binding to 0.0.0.0:8080 +[socket] Binding to 0.0.0.0:8080 +[socket] Binding to 0.0.0.0:8080 +[socket] Binding to 0.0.0.0:8080 +[socket] Binding to 0.0.0.0:8080 +[socket] Binding to 0.0.0.0:8080 +[socket] Binding to 0.0.0.0:8080 +[socket] Binding to 0.0.0.0:8080 +[socket] SO_REUSEPORT enabled for load balancing +[socket] SO_REUSEPORT enabled for load balancing +[socket] SO_REUSEPORT enabled for load balancing +[socket] SO_REUSEPORT enabled for load balancing +[socket] SO_REUSEPORT enabled for load balancing +[socket] SO_REUSEPORT enabled for load balancing +[socket] SO_REUSEPORT enabled for load balancing +[socket] SO_REUSEPORT enabled for load balancing +[socket] SO_REUSEPORT enabled for load balancing +[socket] SO_REUSEPORT enabled for load balancing +[socket] Binding to 0.0.0.0:8080 +[socket] Binding to 0.0.0.0:8080 +[socket] Binding to 0.0.0.0:8080 +[socket] Binding to 0.0.0.0:8080 +[socket] SO_REUSEPORT enabled for load balancing +[socket] SO_REUSEPORT enabled for load balancing +[socket] SO_REUSEPORT enabled for load balancing +[socket] Binding to 0.0.0.0:8080 +[socket] Binding to 0.0.0.0:8080 +[socket] SO_REUSEPORT enabled for load balancing +[socket] SO_REUSEPORT enabled for load balancing +[socket] SO_REUSEPORT enabled for load balancing +[socket] SO_REUSEPORT enabled for load balancing +[socket] SO_REUSEPORT enabled for load balancing +[socket] SO_REUSEPORT enabled for load balancing +[socket] SO_REUSEPORT enabled for load balancing +[socket] SO_REUSEPORT enabled for load balancing +[socket] SO_REUSEPORT enabled for load balancing +[socket] SO_REUSEPORT enabled for load balancing +[socket] SO_REUSEPORT enabled for load balancing +[socket] SO_REUSEPORT enabled for load balancing +[socket] SO_REUSEPORT enabled for load balancing +[socket] SO_REUSEPORT enabled for load balancing +[socket] SO_REUSEPORT enabled for load balancing +[socket] SO_REUSEPORT enabled for load balancing +[socket] Binding to 0.0.0.0:8080 +[socket] Binding to 0.0.0.0:8080 +[socket] Binding to 0.0.0.0:8080 +[socket] Binding to 0.0.0.0:8080 +[socket] Binding to 0.0.0.0:8080 +[socket] Binding to 0.0.0.0:8080 +[socket] Binding to 0.0.0.0:8080 +[socket] SO_REUSEPORT enabled for load balancing +[socket] SO_REUSEPORT enabled for load balancing +[socket] SO_REUSEPORT enabled for load balancing +[socket] Binding to 0.0.0.0:8080 +[socket] Binding to 0.0.0.0:8080 +[socket] Binding to 0.0.0.0:8080 +[socket] Binding to 0.0.0.0:8080 +[socket] Binding to 0.0.0.0:8080 +[socket] Binding to 0.0.0.0:8080 +[socket] Binding to 0.0.0.0:8080 +[socket] Binding to 0.0.0.0:8080 +[socket] SO_REUSEPORT enabled for load balancing +[socket] Binding to 0.0.0.0:8080 +[socket] Binding to 0.0.0.0:8080 +[socket] Binding to 0.0.0.0:8080 +[socket] Binding to 0.0.0.0:8080 +[socket] Binding to 0.0.0.0:8080 +[socket] Binding to 0.0.0.0:8080 +[socket] Binding to 0.0.0.0:8080 +[socket] Binding to 0.0.0.0:8080 +[socket] Binding to 0.0.0.0:8080 +[socket] Binding to 0.0.0.0:8080 +[socket] Binding to 0.0.0.0:8080 +[socket] SO_REUSEPORT enabled for load balancing +[socket] SO_REUSEPORT enabled for load balancing +[socket] SO_REUSEPORT enabled for load balancing +[socket] SO_REUSEPORT enabled for load balancing +[socket] SO_REUSEPORT enabled for load balancing +[socket] SO_REUSEPORT enabled for load balancing +[socket] Binding to 0.0.0.0:8080 +[socket] Binding to 0.0.0.0:8080 +[socket] SO_REUSEPORT enabled for load balancing +listening on http://localhost:8081/ +listening on http://localhost:8080/ (io_uring) diff --git a/site/static/logs/baseline-h2c/1024/vanilla-h2c.log b/site/static/logs/baseline-h2c/1024/vanilla-h2c.log index 7ea9bff07..526c3b4ff 100644 --- a/site/static/logs/baseline-h2c/1024/vanilla-h2c.log +++ b/site/static/logs/baseline-h2c/1024/vanilla-h2c.log @@ -1,3 +1,6 @@ -[socket] Binding to 0.0.0.0:8082 [socket] SO_REUSEPORT enabled for load balancing +[socket] SO_REUSEPORT enabled for load balancing +[socket] Binding to 0.0.0.0:8080 +[socket] Binding to 0.0.0.0:8082 +listening on http://localhost:8080/ listening on http://localhost:8082/ diff --git a/site/static/logs/baseline-h2c/256/vanilla-h2c.log b/site/static/logs/baseline-h2c/256/vanilla-h2c.log index 7ea9bff07..a33b1d5ca 100644 --- a/site/static/logs/baseline-h2c/256/vanilla-h2c.log +++ b/site/static/logs/baseline-h2c/256/vanilla-h2c.log @@ -1,3 +1,6 @@ +[socket] Binding to 0.0.0.0:8080 +[socket] SO_REUSEPORT enabled for load balancing [socket] Binding to 0.0.0.0:8082 [socket] SO_REUSEPORT enabled for load balancing listening on http://localhost:8082/ +listening on http://localhost:8080/ diff --git a/site/static/logs/baseline-h2c/4096/vanilla-h2c.log b/site/static/logs/baseline-h2c/4096/vanilla-h2c.log index 7ea9bff07..77ce6b371 100644 --- a/site/static/logs/baseline-h2c/4096/vanilla-h2c.log +++ b/site/static/logs/baseline-h2c/4096/vanilla-h2c.log @@ -1,3 +1,6 @@ -[socket] Binding to 0.0.0.0:8082 +[socket] Binding to 0.0.0.0:8080 +[socket] SO_REUSEPORT enabled for load balancing [socket] SO_REUSEPORT enabled for load balancing +[socket] Binding to 0.0.0.0:8082 +listening on http://localhost:8080/ listening on http://localhost:8082/ diff --git a/site/static/logs/baseline/4096/vanilla-epoll.log b/site/static/logs/baseline/4096/vanilla-epoll.log index 7e0c123c0..8c4e788f2 100644 --- a/site/static/logs/baseline/4096/vanilla-epoll.log +++ b/site/static/logs/baseline/4096/vanilla-epoll.log @@ -2,5 +2,5 @@ [socket] SO_REUSEPORT enabled for load balancing [socket] SO_REUSEPORT enabled for load balancing [socket] Binding to 0.0.0.0:8080 -listening on http://localhost:8081/ listening on http://localhost:8080/ +listening on http://localhost:8081/ diff --git a/site/static/logs/baseline/4096/vanilla-io_uring.log b/site/static/logs/baseline/4096/vanilla-io_uring.log index 84a725161..5c1b8a0fc 100644 --- a/site/static/logs/baseline/4096/vanilla-io_uring.log +++ b/site/static/logs/baseline/4096/vanilla-io_uring.log @@ -2,85 +2,28 @@ [socket] SO_REUSEPORT enabled for load balancing [socket] SO_REUSEPORT enabled for load balancing [socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing [socket] Binding to 0.0.0.0:8080 [socket] Binding to 0.0.0.0:8080 -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing [socket] Binding to 0.0.0.0:8080 -[socket] SO_REUSEPORT enabled for load balancing [socket] Binding to 0.0.0.0:8080 [socket] SO_REUSEPORT enabled for load balancing [socket] Binding to 0.0.0.0:8080 [socket] SO_REUSEPORT enabled for load balancing -[socket] Binding to 0.0.0.0:8080 [socket] SO_REUSEPORT enabled for load balancing -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 -[socket] SO_REUSEPORT enabled for load balancing -[socket] Binding to 0.0.0.0:8080 [socket] SO_REUSEPORT enabled for load balancing [socket] Binding to 0.0.0.0:8080 [socket] Binding to 0.0.0.0:8080 -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing [socket] Binding to 0.0.0.0:8080 [socket] Binding to 0.0.0.0:8080 [socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 [socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing [socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] Binding to 0.0.0.0:8080 [socket] Binding to 0.0.0.0:8080 [socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing [socket] SO_REUSEPORT enabled for load balancing [socket] Binding to 0.0.0.0:8080 [socket] SO_REUSEPORT enabled for load balancing -[socket] Binding to 0.0.0.0:8080 [socket] SO_REUSEPORT enabled for load balancing -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 -[socket] SO_REUSEPORT enabled for load balancing -[socket] Binding to 0.0.0.0:8080 -[socket] SO_REUSEPORT enabled for load balancing -[socket] Binding to 0.0.0.0:8080 -[socket] SO_REUSEPORT enabled for load balancing -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] Binding to 0.0.0.0:8080 -[socket] SO_REUSEPORT enabled for load balancing -[socket] Binding to 0.0.0.0:8080 -[socket] SO_REUSEPORT enabled for load balancing -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 -[socket] SO_REUSEPORT enabled for load balancing -[socket] Binding to 0.0.0.0:8080 -[socket] SO_REUSEPORT enabled for load balancing -[socket] Binding to 0.0.0.0:8080 -[socket] SO_REUSEPORT enabled for load balancing -[socket] Binding to 0.0.0.0:8080 -[socket] SO_REUSEPORT enabled for load balancing -[socket] Binding to 0.0.0.0:8080 [socket] SO_REUSEPORT enabled for load balancing [socket] SO_REUSEPORT enabled for load balancing [socket] SO_REUSEPORT enabled for load balancing @@ -89,27 +32,14 @@ [socket] SO_REUSEPORT enabled for load balancing [socket] SO_REUSEPORT enabled for load balancing [socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 [socket] Binding to 0.0.0.0:8080 [socket] Binding to 0.0.0.0:8080 [socket] Binding to 0.0.0.0:8080 [socket] Binding to 0.0.0.0:8080 -[socket] SO_REUSEPORT enabled for load balancing [socket] Binding to 0.0.0.0:8080 [socket] Binding to 0.0.0.0:8080 [socket] Binding to 0.0.0.0:8080 [socket] Binding to 0.0.0.0:8080 -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing [socket] Binding to 0.0.0.0:8080 [socket] Binding to 0.0.0.0:8080 [socket] Binding to 0.0.0.0:8080 @@ -120,9 +50,7 @@ [socket] SO_REUSEPORT enabled for load balancing [socket] SO_REUSEPORT enabled for load balancing [socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing +[socket] Binding to 0.0.0.0:8080 [socket] Binding to 0.0.0.0:8080 [socket] Binding to 0.0.0.0:8080 [socket] Binding to 0.0.0.0:8080 @@ -132,59 +60,31 @@ [socket] SO_REUSEPORT enabled for load balancing [socket] SO_REUSEPORT enabled for load balancing [socket] SO_REUSEPORT enabled for load balancing -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 -[socket] SO_REUSEPORT enabled for load balancing [socket] SO_REUSEPORT enabled for load balancing [socket] SO_REUSEPORT enabled for load balancing [socket] Binding to 0.0.0.0:8080 [socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 [socket] SO_REUSEPORT enabled for load balancing [socket] SO_REUSEPORT enabled for load balancing [socket] SO_REUSEPORT enabled for load balancing [socket] Binding to 0.0.0.0:8080 [socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 [socket] Binding to 0.0.0.0:8080 [socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing [socket] SO_REUSEPORT enabled for load balancing [socket] SO_REUSEPORT enabled for load balancing [socket] SO_REUSEPORT enabled for load balancing [socket] Binding to 0.0.0.0:8080 -[socket] SO_REUSEPORT enabled for load balancing [socket] Binding to 0.0.0.0:8080 -[socket] SO_REUSEPORT enabled for load balancing [socket] Binding to 0.0.0.0:8080 [socket] SO_REUSEPORT enabled for load balancing -[socket] Binding to 0.0.0.0:8080 [socket] SO_REUSEPORT enabled for load balancing -[socket] Binding to 0.0.0.0:8080 [socket] SO_REUSEPORT enabled for load balancing -[socket] Binding to 0.0.0.0:8080 [socket] SO_REUSEPORT enabled for load balancing [socket] Binding to 0.0.0.0:8080 -[socket] SO_REUSEPORT enabled for load balancing [socket] Binding to 0.0.0.0:8080 [socket] SO_REUSEPORT enabled for load balancing [socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 [socket] Binding to 0.0.0.0:8080 [socket] Binding to 0.0.0.0:8080 [socket] Binding to 0.0.0.0:8080 @@ -198,9 +98,6 @@ [socket] Binding to 0.0.0.0:8080 [socket] SO_REUSEPORT enabled for load balancing [socket] Binding to 0.0.0.0:8080 -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] Binding to 0.0.0.0:8080 [socket] Binding to 0.0.0.0:8080 [socket] Binding to 0.0.0.0:8080 [socket] SO_REUSEPORT enabled for load balancing @@ -211,50 +108,25 @@ [socket] Binding to 0.0.0.0:8080 [socket] SO_REUSEPORT enabled for load balancing [socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] Binding to 0.0.0.0:8080 [socket] Binding to 0.0.0.0:8080 [socket] Binding to 0.0.0.0:8080 [socket] Binding to 0.0.0.0:8080 -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing [socket] Binding to 0.0.0.0:8080 [socket] Binding to 0.0.0.0:8080 -[socket] SO_REUSEPORT enabled for load balancing [socket] Binding to 0.0.0.0:8080 [socket] SO_REUSEPORT enabled for load balancing -[socket] Binding to 0.0.0.0:8080 [socket] SO_REUSEPORT enabled for load balancing -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 [socket] SO_REUSEPORT enabled for load balancing [socket] SO_REUSEPORT enabled for load balancing [socket] SO_REUSEPORT enabled for load balancing [socket] SO_REUSEPORT enabled for load balancing -[socket] Binding to 0.0.0.0:8080 [socket] SO_REUSEPORT enabled for load balancing -[socket] Binding to 0.0.0.0:8080 [socket] SO_REUSEPORT enabled for load balancing [socket] SO_REUSEPORT enabled for load balancing [socket] Binding to 0.0.0.0:8080 [socket] Binding to 0.0.0.0:8080 [socket] Binding to 0.0.0.0:8080 -[socket] SO_REUSEPORT enabled for load balancing -[socket] Binding to 0.0.0.0:8080 -[socket] SO_REUSEPORT enabled for load balancing [socket] Binding to 0.0.0.0:8080 -[socket] SO_REUSEPORT enabled for load balancing [socket] Binding to 0.0.0.0:8080 listening on http://localhost:8081/ listening on http://localhost:8080/ (io_uring) diff --git a/site/static/logs/echo-ws-limited/4096/vanilla-ws.log b/site/static/logs/echo-ws-limited/4096/vanilla-ws.log new file mode 100644 index 000000000..806e2188d --- /dev/null +++ b/site/static/logs/echo-ws-limited/4096/vanilla-ws.log @@ -0,0 +1,3 @@ +[socket] SO_REUSEPORT enabled for load balancing +[socket] Binding to 0.0.0.0:8080 +listening on http://localhost:8080/ diff --git a/site/static/logs/echo-ws-limited/512/vanilla-ws.log b/site/static/logs/echo-ws-limited/512/vanilla-ws.log new file mode 100644 index 000000000..806e2188d --- /dev/null +++ b/site/static/logs/echo-ws-limited/512/vanilla-ws.log @@ -0,0 +1,3 @@ +[socket] SO_REUSEPORT enabled for load balancing +[socket] Binding to 0.0.0.0:8080 +listening on http://localhost:8080/ diff --git a/site/static/logs/echo-ws-pipeline/16384/vanilla-ws.log b/site/static/logs/echo-ws-pipeline/16384/vanilla-ws.log index e05644d2b..806e2188d 100644 --- a/site/static/logs/echo-ws-pipeline/16384/vanilla-ws.log +++ b/site/static/logs/echo-ws-pipeline/16384/vanilla-ws.log @@ -1,3 +1,3 @@ -[socket] Binding to 0.0.0.0:8080 [socket] SO_REUSEPORT enabled for load balancing +[socket] Binding to 0.0.0.0:8080 listening on http://localhost:8080/ diff --git a/site/static/logs/echo-ws-pipeline/4096/vanilla-ws.log b/site/static/logs/echo-ws-pipeline/4096/vanilla-ws.log index 806e2188d..e05644d2b 100644 --- a/site/static/logs/echo-ws-pipeline/4096/vanilla-ws.log +++ b/site/static/logs/echo-ws-pipeline/4096/vanilla-ws.log @@ -1,3 +1,3 @@ -[socket] SO_REUSEPORT enabled for load balancing [socket] Binding to 0.0.0.0:8080 +[socket] SO_REUSEPORT enabled for load balancing listening on http://localhost:8080/ diff --git a/site/static/logs/echo-ws/4096/vanilla-ws.log b/site/static/logs/echo-ws/4096/vanilla-ws.log index e05644d2b..806e2188d 100644 --- a/site/static/logs/echo-ws/4096/vanilla-ws.log +++ b/site/static/logs/echo-ws/4096/vanilla-ws.log @@ -1,3 +1,3 @@ -[socket] Binding to 0.0.0.0:8080 [socket] SO_REUSEPORT enabled for load balancing +[socket] Binding to 0.0.0.0:8080 listening on http://localhost:8080/ diff --git a/site/static/logs/echo-ws/512/vanilla-ws.log b/site/static/logs/echo-ws/512/vanilla-ws.log index 806e2188d..e05644d2b 100644 --- a/site/static/logs/echo-ws/512/vanilla-ws.log +++ b/site/static/logs/echo-ws/512/vanilla-ws.log @@ -1,3 +1,3 @@ -[socket] SO_REUSEPORT enabled for load balancing [socket] Binding to 0.0.0.0:8080 +[socket] SO_REUSEPORT enabled for load balancing listening on http://localhost:8080/ diff --git a/site/static/logs/fortunes/1024/vanilla-epoll.log b/site/static/logs/fortunes/1024/vanilla-epoll.log index 7e0c123c0..761cac6b1 100644 --- a/site/static/logs/fortunes/1024/vanilla-epoll.log +++ b/site/static/logs/fortunes/1024/vanilla-epoll.log @@ -1,6 +1,6 @@ [socket] Binding to 0.0.0.0:8081 +[socket] Binding to 0.0.0.0:8080 [socket] SO_REUSEPORT enabled for load balancing [socket] SO_REUSEPORT enabled for load balancing -[socket] Binding to 0.0.0.0:8080 -listening on http://localhost:8081/ listening on http://localhost:8080/ +listening on http://localhost:8081/ diff --git a/site/static/logs/fortunes/1024/vanilla-io_uring.log b/site/static/logs/fortunes/1024/vanilla-io_uring.log index bf1d506ac..331e2a12f 100644 --- a/site/static/logs/fortunes/1024/vanilla-io_uring.log +++ b/site/static/logs/fortunes/1024/vanilla-io_uring.log @@ -1,207 +1,94 @@ -[socket] SO_REUSEPORT enabled for load balancing [socket] Binding to 0.0.0.0:8081 -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 [socket] SO_REUSEPORT enabled for load balancing [socket] SO_REUSEPORT enabled for load balancing [socket] SO_REUSEPORT enabled for load balancing [socket] Binding to 0.0.0.0:8080 [socket] Binding to 0.0.0.0:8080 [socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing [socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 [socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing [socket] SO_REUSEPORT enabled for load balancing +[socket] Binding to 0.0.0.0:8080 [socket] SO_REUSEPORT enabled for load balancing [socket] SO_REUSEPORT enabled for load balancing +[socket] Binding to 0.0.0.0:8080 [socket] SO_REUSEPORT enabled for load balancing [socket] SO_REUSEPORT enabled for load balancing [socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 [socket] SO_REUSEPORT enabled for load balancing -[socket] Binding to 0.0.0.0:8080 [socket] SO_REUSEPORT enabled for load balancing [socket] Binding to 0.0.0.0:8080 [socket] Binding to 0.0.0.0:8080 [socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 [socket] SO_REUSEPORT enabled for load balancing -[socket] Binding to 0.0.0.0:8080 [socket] SO_REUSEPORT enabled for load balancing [socket] Binding to 0.0.0.0:8080 -[socket] SO_REUSEPORT enabled for load balancing [socket] Binding to 0.0.0.0:8080 [socket] SO_REUSEPORT enabled for load balancing [socket] Binding to 0.0.0.0:8080 [socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing [socket] Binding to 0.0.0.0:8080 [socket] SO_REUSEPORT enabled for load balancing -[socket] Binding to 0.0.0.0:8080 [socket] SO_REUSEPORT enabled for load balancing [socket] Binding to 0.0.0.0:8080 [socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing [socket] SO_REUSEPORT enabled for load balancing [socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] Binding to 0.0.0.0:8080 [socket] Binding to 0.0.0.0:8080 [socket] Binding to 0.0.0.0:8080 [socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing [socket] Binding to 0.0.0.0:8080 [socket] Binding to 0.0.0.0:8080 [socket] SO_REUSEPORT enabled for load balancing [socket] Binding to 0.0.0.0:8080 [socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing [socket] Binding to 0.0.0.0:8080 [socket] Binding to 0.0.0.0:8080 [socket] SO_REUSEPORT enabled for load balancing -[socket] Binding to 0.0.0.0:8080 [socket] SO_REUSEPORT enabled for load balancing -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 [socket] SO_REUSEPORT enabled for load balancing -[socket] Binding to 0.0.0.0:8080 [socket] SO_REUSEPORT enabled for load balancing [socket] Binding to 0.0.0.0:8080 [socket] Binding to 0.0.0.0:8080 [socket] Binding to 0.0.0.0:8080 [socket] Binding to 0.0.0.0:8080 [socket] SO_REUSEPORT enabled for load balancing -[socket] Binding to 0.0.0.0:8080 [socket] SO_REUSEPORT enabled for load balancing [socket] Binding to 0.0.0.0:8080 [socket] SO_REUSEPORT enabled for load balancing [socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 [socket] SO_REUSEPORT enabled for load balancing -[socket] Binding to 0.0.0.0:8080 -[socket] SO_REUSEPORT enabled for load balancing -[socket] Binding to 0.0.0.0:8080 [socket] SO_REUSEPORT enabled for load balancing [socket] SO_REUSEPORT enabled for load balancing [socket] Binding to 0.0.0.0:8080 [socket] Binding to 0.0.0.0:8080 [socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 [socket] Binding to 0.0.0.0:8080 [socket] SO_REUSEPORT enabled for load balancing [socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 -[socket] SO_REUSEPORT enabled for load balancing [socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 [socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing [socket] SO_REUSEPORT enabled for load balancing [socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 [socket] SO_REUSEPORT enabled for load balancing [socket] Binding to 0.0.0.0:8080 [socket] Binding to 0.0.0.0:8080 [socket] Binding to 0.0.0.0:8080 [socket] SO_REUSEPORT enabled for load balancing [socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] Binding to 0.0.0.0:8080 -[socket] SO_REUSEPORT enabled for load balancing [socket] Binding to 0.0.0.0:8080 [socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] Binding to 0.0.0.0:8080 [socket] Binding to 0.0.0.0:8080 [socket] SO_REUSEPORT enabled for load balancing [socket] SO_REUSEPORT enabled for load balancing [socket] SO_REUSEPORT enabled for load balancing [socket] Binding to 0.0.0.0:8080 -[socket] SO_REUSEPORT enabled for load balancing [socket] Binding to 0.0.0.0:8080 [socket] SO_REUSEPORT enabled for load balancing [socket] Binding to 0.0.0.0:8080 [socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 [socket] SO_REUSEPORT enabled for load balancing -[socket] Binding to 0.0.0.0:8080 +[socket] SO_REUSEPORT enabled for load balancing [socket] SO_REUSEPORT enabled for load balancing [socket] Binding to 0.0.0.0:8080 [socket] Binding to 0.0.0.0:8080 @@ -211,19 +98,16 @@ [socket] SO_REUSEPORT enabled for load balancing [socket] SO_REUSEPORT enabled for load balancing [socket] SO_REUSEPORT enabled for load balancing -[socket] Binding to 0.0.0.0:8080 [socket] SO_REUSEPORT enabled for load balancing [socket] Binding to 0.0.0.0:8080 [socket] SO_REUSEPORT enabled for load balancing [socket] Binding to 0.0.0.0:8080 [socket] SO_REUSEPORT enabled for load balancing -[socket] Binding to 0.0.0.0:8080 [socket] SO_REUSEPORT enabled for load balancing [socket] SO_REUSEPORT enabled for load balancing -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 +[socket] SO_REUSEPORT enabled for load balancing +[socket] SO_REUSEPORT enabled for load balancing +[socket] SO_REUSEPORT enabled for load balancing [socket] SO_REUSEPORT enabled for load balancing [socket] SO_REUSEPORT enabled for load balancing [socket] SO_REUSEPORT enabled for load balancing @@ -239,22 +123,10 @@ [socket] Binding to 0.0.0.0:8080 [socket] Binding to 0.0.0.0:8080 [socket] Binding to 0.0.0.0:8080 -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing [socket] Binding to 0.0.0.0:8080 [socket] Binding to 0.0.0.0:8080 [socket] Binding to 0.0.0.0:8080 [socket] Binding to 0.0.0.0:8080 -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] Binding to 0.0.0.0:8080 -[socket] SO_REUSEPORT enabled for load balancing [socket] Binding to 0.0.0.0:8080 listening on http://localhost:8081/ listening on http://localhost:8080/ (io_uring) diff --git a/site/static/logs/gateway-64/1024/vanilla-gateway.log b/site/static/logs/gateway-64/1024/vanilla-gateway.log new file mode 100644 index 000000000..9f076e226 --- /dev/null +++ b/site/static/logs/gateway-64/1024/vanilla-gateway.log @@ -0,0 +1 @@ +Error response from daemon: No such container: httparena-bench-vanilla-gateway diff --git a/site/static/logs/gateway-64/512/vanilla-gateway.log b/site/static/logs/gateway-64/512/vanilla-gateway.log new file mode 100644 index 000000000..9f076e226 --- /dev/null +++ b/site/static/logs/gateway-64/512/vanilla-gateway.log @@ -0,0 +1 @@ +Error response from daemon: No such container: httparena-bench-vanilla-gateway diff --git a/site/static/logs/gateway-h3/256/vanilla-gateway.log b/site/static/logs/gateway-h3/256/vanilla-gateway.log new file mode 100644 index 000000000..9f076e226 --- /dev/null +++ b/site/static/logs/gateway-h3/256/vanilla-gateway.log @@ -0,0 +1 @@ +Error response from daemon: No such container: httparena-bench-vanilla-gateway diff --git a/site/static/logs/gateway-h3/64/vanilla-gateway.log b/site/static/logs/gateway-h3/64/vanilla-gateway.log new file mode 100644 index 000000000..9f076e226 --- /dev/null +++ b/site/static/logs/gateway-h3/64/vanilla-gateway.log @@ -0,0 +1 @@ +Error response from daemon: No such container: httparena-bench-vanilla-gateway diff --git a/site/static/logs/json-comp/16384/vanilla-epoll.log b/site/static/logs/json-comp/16384/vanilla-epoll.log index 761cac6b1..9de548a21 100644 --- a/site/static/logs/json-comp/16384/vanilla-epoll.log +++ b/site/static/logs/json-comp/16384/vanilla-epoll.log @@ -1,6 +1,6 @@ [socket] Binding to 0.0.0.0:8081 -[socket] Binding to 0.0.0.0:8080 [socket] SO_REUSEPORT enabled for load balancing +[socket] Binding to 0.0.0.0:8080 [socket] SO_REUSEPORT enabled for load balancing -listening on http://localhost:8080/ listening on http://localhost:8081/ +listening on http://localhost:8080/ diff --git a/site/static/logs/json-comp/16384/vanilla-io_uring.log b/site/static/logs/json-comp/16384/vanilla-io_uring.log index b2034cdfa..471260d5a 100644 --- a/site/static/logs/json-comp/16384/vanilla-io_uring.log +++ b/site/static/logs/json-comp/16384/vanilla-io_uring.log @@ -1,46 +1,17 @@ -[socket] SO_REUSEPORT enabled for load balancing [socket] Binding to 0.0.0.0:8081 -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 [socket] SO_REUSEPORT enabled for load balancing [socket] Binding to 0.0.0.0:8080 [socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing [socket] Binding to 0.0.0.0:8080 [socket] SO_REUSEPORT enabled for load balancing [socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing [socket] Binding to 0.0.0.0:8080 [socket] Binding to 0.0.0.0:8080 -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing [socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 -[socket] SO_REUSEPORT enabled for load balancing [socket] SO_REUSEPORT enabled for load balancing [socket] SO_REUSEPORT enabled for load balancing [socket] Binding to 0.0.0.0:8080 -[socket] SO_REUSEPORT enabled for load balancing -[socket] Binding to 0.0.0.0:8080 [socket] Binding to 0.0.0.0:8080 -[socket] SO_REUSEPORT enabled for load balancing -[socket] Binding to 0.0.0.0:8080 -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing [socket] Binding to 0.0.0.0:8080 [socket] Binding to 0.0.0.0:8080 [socket] SO_REUSEPORT enabled for load balancing @@ -51,47 +22,22 @@ [socket] Binding to 0.0.0.0:8080 [socket] Binding to 0.0.0.0:8080 [socket] Binding to 0.0.0.0:8080 -[socket] SO_REUSEPORT enabled for load balancing -[socket] Binding to 0.0.0.0:8080 -[socket] SO_REUSEPORT enabled for load balancing -[socket] Binding to 0.0.0.0:8080 -[socket] SO_REUSEPORT enabled for load balancing -[socket] Binding to 0.0.0.0:8080 [socket] Binding to 0.0.0.0:8080 -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing [socket] Binding to 0.0.0.0:8080 [socket] Binding to 0.0.0.0:8080 [socket] Binding to 0.0.0.0:8080 [socket] SO_REUSEPORT enabled for load balancing [socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing [socket] Binding to 0.0.0.0:8080 [socket] SO_REUSEPORT enabled for load balancing [socket] Binding to 0.0.0.0:8080 [socket] SO_REUSEPORT enabled for load balancing [socket] SO_REUSEPORT enabled for load balancing [socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 [socket] SO_REUSEPORT enabled for load balancing [socket] SO_REUSEPORT enabled for load balancing [socket] SO_REUSEPORT enabled for load balancing -[socket] Binding to 0.0.0.0:8080 [socket] SO_REUSEPORT enabled for load balancing -[socket] Binding to 0.0.0.0:8080 -[socket] SO_REUSEPORT enabled for load balancing -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 -[socket] SO_REUSEPORT enabled for load balancing -[socket] Binding to 0.0.0.0:8080 -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] Binding to 0.0.0.0:8080 [socket] SO_REUSEPORT enabled for load balancing [socket] SO_REUSEPORT enabled for load balancing [socket] SO_REUSEPORT enabled for load balancing @@ -103,10 +49,6 @@ [socket] Binding to 0.0.0.0:8080 [socket] SO_REUSEPORT enabled for load balancing [socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] Binding to 0.0.0.0:8080 [socket] Binding to 0.0.0.0:8080 [socket] Binding to 0.0.0.0:8080 [socket] Binding to 0.0.0.0:8080 @@ -114,85 +56,41 @@ [socket] Binding to 0.0.0.0:8080 [socket] Binding to 0.0.0.0:8080 [socket] Binding to 0.0.0.0:8080 -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing [socket] Binding to 0.0.0.0:8080 [socket] Binding to 0.0.0.0:8080 [socket] SO_REUSEPORT enabled for load balancing -[socket] Binding to 0.0.0.0:8080 [socket] SO_REUSEPORT enabled for load balancing [socket] SO_REUSEPORT enabled for load balancing [socket] SO_REUSEPORT enabled for load balancing [socket] SO_REUSEPORT enabled for load balancing [socket] Binding to 0.0.0.0:8080 [socket] SO_REUSEPORT enabled for load balancing -[socket] Binding to 0.0.0.0:8080 [socket] SO_REUSEPORT enabled for load balancing [socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 [socket] SO_REUSEPORT enabled for load balancing [socket] SO_REUSEPORT enabled for load balancing -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 -[socket] SO_REUSEPORT enabled for load balancing [socket] SO_REUSEPORT enabled for load balancing [socket] SO_REUSEPORT enabled for load balancing -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 [socket] SO_REUSEPORT enabled for load balancing -[socket] Binding to 0.0.0.0:8080 [socket] SO_REUSEPORT enabled for load balancing [socket] SO_REUSEPORT enabled for load balancing [socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 [socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] Binding to 0.0.0.0:8080 [socket] Binding to 0.0.0.0:8080 [socket] Binding to 0.0.0.0:8080 [socket] Binding to 0.0.0.0:8080 [socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] Binding to 0.0.0.0:8080 -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing [socket] Binding to 0.0.0.0:8080 [socket] SO_REUSEPORT enabled for load balancing [socket] Binding to 0.0.0.0:8080 [socket] Binding to 0.0.0.0:8080 [socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 -[socket] SO_REUSEPORT enabled for load balancing [socket] SO_REUSEPORT enabled for load balancing [socket] Binding to 0.0.0.0:8080 [socket] SO_REUSEPORT enabled for load balancing [socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] Binding to 0.0.0.0:8080 -[socket] SO_REUSEPORT enabled for load balancing -[socket] Binding to 0.0.0.0:8080 -[socket] SO_REUSEPORT enabled for load balancing -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] Binding to 0.0.0.0:8080 [socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 -[socket] SO_REUSEPORT enabled for load balancing [socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 [socket] Binding to 0.0.0.0:8080 [socket] SO_REUSEPORT enabled for load balancing [socket] SO_REUSEPORT enabled for load balancing @@ -202,31 +100,17 @@ [socket] Binding to 0.0.0.0:8080 [socket] SO_REUSEPORT enabled for load balancing [socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 -[socket] SO_REUSEPORT enabled for load balancing [socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] Binding to 0.0.0.0:8080 [socket] Binding to 0.0.0.0:8080 [socket] Binding to 0.0.0.0:8080 [socket] Binding to 0.0.0.0:8080 -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing [socket] Binding to 0.0.0.0:8080 [socket] Binding to 0.0.0.0:8080 [socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] Binding to 0.0.0.0:8080 [socket] SO_REUSEPORT enabled for load balancing [socket] SO_REUSEPORT enabled for load balancing [socket] SO_REUSEPORT enabled for load balancing [socket] SO_REUSEPORT enabled for load balancing -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing [socket] SO_REUSEPORT enabled for load balancing [socket] SO_REUSEPORT enabled for load balancing [socket] SO_REUSEPORT enabled for load balancing @@ -237,24 +121,12 @@ [socket] Binding to 0.0.0.0:8080 [socket] Binding to 0.0.0.0:8080 [socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 -[socket] SO_REUSEPORT enabled for load balancing -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing [socket] SO_REUSEPORT enabled for load balancing [socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 [socket] Binding to 0.0.0.0:8080 +[socket] SO_REUSEPORT enabled for load balancing [socket] Binding to 0.0.0.0:8080 [socket] SO_REUSEPORT enabled for load balancing +[socket] SO_REUSEPORT enabled for load balancing listening on http://localhost:8081/ listening on http://localhost:8080/ (io_uring) diff --git a/site/static/logs/json-comp/4096/vanilla-epoll.log b/site/static/logs/json-comp/4096/vanilla-epoll.log index 029eef843..dee8f8a58 100644 --- a/site/static/logs/json-comp/4096/vanilla-epoll.log +++ b/site/static/logs/json-comp/4096/vanilla-epoll.log @@ -1,5 +1,5 @@ -[socket] SO_REUSEPORT enabled for load balancing [socket] Binding to 0.0.0.0:8081 +[socket] SO_REUSEPORT enabled for load balancing [socket] Binding to 0.0.0.0:8080 [socket] SO_REUSEPORT enabled for load balancing listening on http://localhost:8080/ diff --git a/site/static/logs/json-comp/4096/vanilla-io_uring.log b/site/static/logs/json-comp/4096/vanilla-io_uring.log index 536572d86..4d35c646c 100644 --- a/site/static/logs/json-comp/4096/vanilla-io_uring.log +++ b/site/static/logs/json-comp/4096/vanilla-io_uring.log @@ -1,50 +1,31 @@ [socket] Binding to 0.0.0.0:8081 [socket] SO_REUSEPORT enabled for load balancing -[socket] Binding to 0.0.0.0:8080 [socket] SO_REUSEPORT enabled for load balancing [socket] SO_REUSEPORT enabled for load balancing [socket] SO_REUSEPORT enabled for load balancing -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 [socket] SO_REUSEPORT enabled for load balancing [socket] SO_REUSEPORT enabled for load balancing [socket] Binding to 0.0.0.0:8080 -[socket] SO_REUSEPORT enabled for load balancing [socket] Binding to 0.0.0.0:8080 -[socket] SO_REUSEPORT enabled for load balancing [socket] Binding to 0.0.0.0:8080 [socket] SO_REUSEPORT enabled for load balancing [socket] Binding to 0.0.0.0:8080 [socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 [socket] Binding to 0.0.0.0:8080 [socket] SO_REUSEPORT enabled for load balancing [socket] SO_REUSEPORT enabled for load balancing [socket] Binding to 0.0.0.0:8080 [socket] SO_REUSEPORT enabled for load balancing [socket] Binding to 0.0.0.0:8080 +[socket] SO_REUSEPORT enabled for load balancing [socket] Binding to 0.0.0.0:8080 +[socket] SO_REUSEPORT enabled for load balancing [socket] Binding to 0.0.0.0:8080 [socket] Binding to 0.0.0.0:8080 [socket] Binding to 0.0.0.0:8080 [socket] Binding to 0.0.0.0:8080 [socket] SO_REUSEPORT enabled for load balancing [socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing [socket] Binding to 0.0.0.0:8080 [socket] Binding to 0.0.0.0:8080 [socket] Binding to 0.0.0.0:8080 @@ -59,90 +40,25 @@ [socket] Binding to 0.0.0.0:8080 [socket] SO_REUSEPORT enabled for load balancing [socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 [socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 [socket] Binding to 0.0.0.0:8080 [socket] SO_REUSEPORT enabled for load balancing [socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing [socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] Binding to 0.0.0.0:8080 [socket] Binding to 0.0.0.0:8080 [socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing [socket] Binding to 0.0.0.0:8080 [socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] Binding to 0.0.0.0:8080 [socket] Binding to 0.0.0.0:8080 [socket] SO_REUSEPORT enabled for load balancing [socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 [socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] Binding to 0.0.0.0:8080 [socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing [socket] SO_REUSEPORT enabled for load balancing [socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 [socket] SO_REUSEPORT enabled for load balancing [socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 [socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 [socket] Binding to 0.0.0.0:8080 [socket] SO_REUSEPORT enabled for load balancing [socket] Binding to 0.0.0.0:8080 @@ -150,23 +66,14 @@ [socket] Binding to 0.0.0.0:8080 [socket] SO_REUSEPORT enabled for load balancing [socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing [socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 -[socket] SO_REUSEPORT enabled for load balancing [socket] SO_REUSEPORT enabled for load balancing [socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 [socket] SO_REUSEPORT enabled for load balancing [socket] SO_REUSEPORT enabled for load balancing [socket] Binding to 0.0.0.0:8080 [socket] Binding to 0.0.0.0:8080 [socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 -[socket] SO_REUSEPORT enabled for load balancing [socket] SO_REUSEPORT enabled for load balancing [socket] Binding to 0.0.0.0:8080 [socket] SO_REUSEPORT enabled for load balancing @@ -190,61 +97,29 @@ [socket] SO_REUSEPORT enabled for load balancing [socket] SO_REUSEPORT enabled for load balancing [socket] Binding to 0.0.0.0:8080 -[socket] SO_REUSEPORT enabled for load balancing -[socket] Binding to 0.0.0.0:8080 -[socket] SO_REUSEPORT enabled for load balancing -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 -[socket] SO_REUSEPORT enabled for load balancing -[socket] Binding to 0.0.0.0:8080 -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 [socket] Binding to 0.0.0.0:8080 [socket] SO_REUSEPORT enabled for load balancing [socket] Binding to 0.0.0.0:8080 [socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing [socket] Binding to 0.0.0.0:8080 [socket] SO_REUSEPORT enabled for load balancing -[socket] Binding to 0.0.0.0:8080 [socket] SO_REUSEPORT enabled for load balancing [socket] Binding to 0.0.0.0:8080 [socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing [socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 -[socket] SO_REUSEPORT enabled for load balancing [socket] SO_REUSEPORT enabled for load balancing [socket] Binding to 0.0.0.0:8080 [socket] Binding to 0.0.0.0:8080 -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing [socket] Binding to 0.0.0.0:8080 -[socket] SO_REUSEPORT enabled for load balancing [socket] Binding to 0.0.0.0:8080 [socket] SO_REUSEPORT enabled for load balancing [socket] SO_REUSEPORT enabled for load balancing [socket] Binding to 0.0.0.0:8080 [socket] SO_REUSEPORT enabled for load balancing -[socket] Binding to 0.0.0.0:8080 -[socket] SO_REUSEPORT enabled for load balancing -[socket] Binding to 0.0.0.0:8080 [socket] SO_REUSEPORT enabled for load balancing -[socket] Binding to 0.0.0.0:8080 [socket] SO_REUSEPORT enabled for load balancing [socket] Binding to 0.0.0.0:8080 -[socket] SO_REUSEPORT enabled for load balancing [socket] Binding to 0.0.0.0:8080 -[socket] SO_REUSEPORT enabled for load balancing [socket] Binding to 0.0.0.0:8080 [socket] SO_REUSEPORT enabled for load balancing [socket] Binding to 0.0.0.0:8080 @@ -252,9 +127,6 @@ [socket] Binding to 0.0.0.0:8080 [socket] Binding to 0.0.0.0:8080 [socket] SO_REUSEPORT enabled for load balancing -[socket] Binding to 0.0.0.0:8080 -[socket] SO_REUSEPORT enabled for load balancing [socket] SO_REUSEPORT enabled for load balancing -[socket] Binding to 0.0.0.0:8080 listening on http://localhost:8081/ listening on http://localhost:8080/ (io_uring) diff --git a/site/static/logs/json-h2c/1024/vanilla-h2c.log b/site/static/logs/json-h2c/1024/vanilla-h2c.log index 7ea9bff07..b838ed571 100644 --- a/site/static/logs/json-h2c/1024/vanilla-h2c.log +++ b/site/static/logs/json-h2c/1024/vanilla-h2c.log @@ -1,3 +1,6 @@ -[socket] Binding to 0.0.0.0:8082 [socket] SO_REUSEPORT enabled for load balancing +[socket] SO_REUSEPORT enabled for load balancing +[socket] Binding to 0.0.0.0:8080 +[socket] Binding to 0.0.0.0:8082 listening on http://localhost:8082/ +listening on http://localhost:8080/ diff --git a/site/static/logs/json-h2c/4096/vanilla-h2c.log b/site/static/logs/json-h2c/4096/vanilla-h2c.log index 7ea9bff07..fdd66dfff 100644 --- a/site/static/logs/json-h2c/4096/vanilla-h2c.log +++ b/site/static/logs/json-h2c/4096/vanilla-h2c.log @@ -1,3 +1,6 @@ +[socket] Binding to 0.0.0.0:8080 [socket] Binding to 0.0.0.0:8082 [socket] SO_REUSEPORT enabled for load balancing +[socket] SO_REUSEPORT enabled for load balancing +listening on http://localhost:8080/ listening on http://localhost:8082/ diff --git a/site/static/logs/json-tls/4096/vanilla-epoll.log b/site/static/logs/json-tls/4096/vanilla-epoll.log index 7040d20ce..ceaa19716 100644 --- a/site/static/logs/json-tls/4096/vanilla-epoll.log +++ b/site/static/logs/json-tls/4096/vanilla-epoll.log @@ -1,7 +1,7 @@ [socket] Binding to 0.0.0.0:8081 +[socket] Binding to 0.0.0.0:8080 [socket] SO_REUSEPORT enabled for load balancing [socket] SO_REUSEPORT enabled for load balancing -[socket] Binding to 0.0.0.0:8080 -listening on http://localhost:8081/ listening on http://localhost:8080/ +listening on http://localhost:8081/ [ktls] engaged: kernel TLS TX+RX (TLS 1.3, AES-128-GCM) diff --git a/site/static/logs/json-tls/4096/vanilla-io_uring.log b/site/static/logs/json-tls/4096/vanilla-io_uring.log index 7cc4b882d..4c30356ce 100644 --- a/site/static/logs/json-tls/4096/vanilla-io_uring.log +++ b/site/static/logs/json-tls/4096/vanilla-io_uring.log @@ -1,6 +1,4 @@ [socket] Binding to 0.0.0.0:8081 -[socket] SO_REUSEPORT enabled for load balancing -[socket] Binding to 0.0.0.0:8080 [socket] Binding to 0.0.0.0:8080 [socket] Binding to 0.0.0.0:8080 [socket] Binding to 0.0.0.0:8080 @@ -12,130 +10,51 @@ [socket] SO_REUSEPORT enabled for load balancing [socket] SO_REUSEPORT enabled for load balancing [socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] Binding to 0.0.0.0:8080 -[socket] SO_REUSEPORT enabled for load balancing -[socket] Binding to 0.0.0.0:8080 -[socket] SO_REUSEPORT enabled for load balancing -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 [socket] Binding to 0.0.0.0:8080 [socket] Binding to 0.0.0.0:8080 [socket] Binding to 0.0.0.0:8080 [socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 [socket] Binding to 0.0.0.0:8080 [socket] Binding to 0.0.0.0:8080 [socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 -[socket] SO_REUSEPORT enabled for load balancing [socket] SO_REUSEPORT enabled for load balancing [socket] SO_REUSEPORT enabled for load balancing [socket] SO_REUSEPORT enabled for load balancing [socket] SO_REUSEPORT enabled for load balancing [socket] SO_REUSEPORT enabled for load balancing [socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] Binding to 0.0.0.0:8080 -[socket] SO_REUSEPORT enabled for load balancing -[socket] Binding to 0.0.0.0:8080 -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 [socket] Binding to 0.0.0.0:8080 [socket] SO_REUSEPORT enabled for load balancing [socket] SO_REUSEPORT enabled for load balancing [socket] SO_REUSEPORT enabled for load balancing -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 [socket] SO_REUSEPORT enabled for load balancing [socket] Binding to 0.0.0.0:8080 -[socket] SO_REUSEPORT enabled for load balancing [socket] Binding to 0.0.0.0:8080 -[socket] SO_REUSEPORT enabled for load balancing [socket] Binding to 0.0.0.0:8080 -[socket] SO_REUSEPORT enabled for load balancing [socket] Binding to 0.0.0.0:8080 [socket] Binding to 0.0.0.0:8080 [socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing [socket] Binding to 0.0.0.0:8080 [socket] Binding to 0.0.0.0:8080 [socket] Binding to 0.0.0.0:8080 -[socket] SO_REUSEPORT enabled for load balancing -[socket] Binding to 0.0.0.0:8080 -[socket] SO_REUSEPORT enabled for load balancing -[socket] Binding to 0.0.0.0:8080 -[socket] SO_REUSEPORT enabled for load balancing [socket] Binding to 0.0.0.0:8080 [socket] Binding to 0.0.0.0:8080 [socket] Binding to 0.0.0.0:8080 [socket] Binding to 0.0.0.0:8080 [socket] SO_REUSEPORT enabled for load balancing [socket] SO_REUSEPORT enabled for load balancing -[socket] Binding to 0.0.0.0:8080 [socket] SO_REUSEPORT enabled for load balancing [socket] SO_REUSEPORT enabled for load balancing -[socket] Binding to 0.0.0.0:8080 [socket] SO_REUSEPORT enabled for load balancing -[socket] Binding to 0.0.0.0:8080 [socket] SO_REUSEPORT enabled for load balancing -[socket] Binding to 0.0.0.0:8080 [socket] SO_REUSEPORT enabled for load balancing -[socket] Binding to 0.0.0.0:8080 [socket] SO_REUSEPORT enabled for load balancing [socket] Binding to 0.0.0.0:8080 -[socket] SO_REUSEPORT enabled for load balancing [socket] Binding to 0.0.0.0:8080 -[socket] SO_REUSEPORT enabled for load balancing [socket] Binding to 0.0.0.0:8080 -[socket] SO_REUSEPORT enabled for load balancing [socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing [socket] SO_REUSEPORT enabled for load balancing -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 [socket] SO_REUSEPORT enabled for load balancing -[socket] Binding to 0.0.0.0:8080 [socket] SO_REUSEPORT enabled for load balancing [socket] Binding to 0.0.0.0:8080 [socket] Binding to 0.0.0.0:8080 @@ -146,39 +65,25 @@ [socket] Binding to 0.0.0.0:8080 [socket] SO_REUSEPORT enabled for load balancing [socket] SO_REUSEPORT enabled for load balancing -[socket] Binding to 0.0.0.0:8080 [socket] SO_REUSEPORT enabled for load balancing [socket] SO_REUSEPORT enabled for load balancing [socket] Binding to 0.0.0.0:8080 -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing [socket] Binding to 0.0.0.0:8080 [socket] Binding to 0.0.0.0:8080 [socket] Binding to 0.0.0.0:8080 [socket] SO_REUSEPORT enabled for load balancing [socket] SO_REUSEPORT enabled for load balancing -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 -[socket] SO_REUSEPORT enabled for load balancing [socket] SO_REUSEPORT enabled for load balancing -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 [socket] SO_REUSEPORT enabled for load balancing [socket] SO_REUSEPORT enabled for load balancing -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 [socket] SO_REUSEPORT enabled for load balancing [socket] SO_REUSEPORT enabled for load balancing [socket] Binding to 0.0.0.0:8080 -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing [socket] Binding to 0.0.0.0:8080 [socket] Binding to 0.0.0.0:8080 [socket] Binding to 0.0.0.0:8080 [socket] Binding to 0.0.0.0:8080 [socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing [socket] Binding to 0.0.0.0:8080 [socket] SO_REUSEPORT enabled for load balancing [socket] Binding to 0.0.0.0:8080 @@ -186,38 +91,16 @@ [socket] Binding to 0.0.0.0:8080 [socket] SO_REUSEPORT enabled for load balancing [socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] Binding to 0.0.0.0:8080 [socket] Binding to 0.0.0.0:8080 [socket] SO_REUSEPORT enabled for load balancing [socket] Binding to 0.0.0.0:8080 [socket] SO_REUSEPORT enabled for load balancing [socket] SO_REUSEPORT enabled for load balancing -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 -[socket] SO_REUSEPORT enabled for load balancing -[socket] Binding to 0.0.0.0:8080 -[socket] SO_REUSEPORT enabled for load balancing -[socket] Binding to 0.0.0.0:8080 -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] Binding to 0.0.0.0:8080 [socket] SO_REUSEPORT enabled for load balancing [socket] SO_REUSEPORT enabled for load balancing [socket] Binding to 0.0.0.0:8080 [socket] Binding to 0.0.0.0:8080 [socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 -[socket] SO_REUSEPORT enabled for load balancing -[socket] Binding to 0.0.0.0:8080 [socket] SO_REUSEPORT enabled for load balancing [socket] Binding to 0.0.0.0:8080 [socket] SO_REUSEPORT enabled for load balancing @@ -225,36 +108,25 @@ [socket] SO_REUSEPORT enabled for load balancing [socket] SO_REUSEPORT enabled for load balancing [socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 -[socket] SO_REUSEPORT enabled for load balancing [socket] Binding to 0.0.0.0:8080 [socket] Binding to 0.0.0.0:8080 -[socket] SO_REUSEPORT enabled for load balancing [socket] Binding to 0.0.0.0:8080 [socket] SO_REUSEPORT enabled for load balancing [socket] SO_REUSEPORT enabled for load balancing [socket] SO_REUSEPORT enabled for load balancing [socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing [socket] Binding to 0.0.0.0:8080 [socket] SO_REUSEPORT enabled for load balancing [socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 -[socket] SO_REUSEPORT enabled for load balancing [socket] SO_REUSEPORT enabled for load balancing [socket] Binding to 0.0.0.0:8080 -[socket] SO_REUSEPORT enabled for load balancing [socket] Binding to 0.0.0.0:8080 [socket] SO_REUSEPORT enabled for load balancing [socket] Binding to 0.0.0.0:8080 +[socket] Binding to 0.0.0.0:8080 [socket] SO_REUSEPORT enabled for load balancing [socket] Binding to 0.0.0.0:8080 [socket] Binding to 0.0.0.0:8080 -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing [socket] Binding to 0.0.0.0:8080 listening on http://localhost:8081/ [ktls] engaged: kernel TLS TX+RX (TLS 1.3, AES-128-GCM) diff --git a/site/static/logs/latency-10k/1024/vanilla-epoll.log b/site/static/logs/latency-10k/1024/vanilla-epoll.log new file mode 100644 index 000000000..255dbf08b --- /dev/null +++ b/site/static/logs/latency-10k/1024/vanilla-epoll.log @@ -0,0 +1,6 @@ +[socket] Binding to 0.0.0.0:8081 +[socket] Binding to 0.0.0.0:8080 +[socket] SO_REUSEPORT enabled for load balancing +[socket] SO_REUSEPORT enabled for load balancing +listening on http://localhost:8081/ +listening on http://localhost:8080/ diff --git a/site/static/logs/latency-10k/1024/vanilla-io_uring.log b/site/static/logs/latency-10k/1024/vanilla-io_uring.log new file mode 100644 index 000000000..1d8d10b8a --- /dev/null +++ b/site/static/logs/latency-10k/1024/vanilla-io_uring.log @@ -0,0 +1,132 @@ +[socket] SO_REUSEPORT enabled for load balancing +[socket] Binding to 0.0.0.0:8081 +[socket] SO_REUSEPORT enabled for load balancing +[socket] SO_REUSEPORT enabled for load balancing +[socket] Binding to 0.0.0.0:8080 +[socket] Binding to 0.0.0.0:8080 +[socket] Binding to 0.0.0.0:8080 +[socket] Binding to 0.0.0.0:8080 +[socket] Binding to 0.0.0.0:8080 +[socket] SO_REUSEPORT enabled for load balancing +[socket] SO_REUSEPORT enabled for load balancing +[socket] SO_REUSEPORT enabled for load balancing +[socket] SO_REUSEPORT enabled for load balancing +[socket] SO_REUSEPORT enabled for load balancing +[socket] SO_REUSEPORT enabled for load balancing +[socket] Binding to 0.0.0.0:8080 +[socket] Binding to 0.0.0.0:8080 +[socket] Binding to 0.0.0.0:8080 +[socket] SO_REUSEPORT enabled for load balancing +[socket] SO_REUSEPORT enabled for load balancing +[socket] SO_REUSEPORT enabled for load balancing +[socket] SO_REUSEPORT enabled for load balancing +[socket] Binding to 0.0.0.0:8080 +[socket] Binding to 0.0.0.0:8080 +[socket] Binding to 0.0.0.0:8080 +[socket] Binding to 0.0.0.0:8080 +[socket] SO_REUSEPORT enabled for load balancing +[socket] Binding to 0.0.0.0:8080 +[socket] Binding to 0.0.0.0:8080 +[socket] SO_REUSEPORT enabled for load balancing +[socket] Binding to 0.0.0.0:8080 +[socket] SO_REUSEPORT enabled for load balancing +[socket] Binding to 0.0.0.0:8080 +[socket] SO_REUSEPORT enabled for load balancing +[socket] Binding to 0.0.0.0:8080 +[socket] Binding to 0.0.0.0:8080 +[socket] SO_REUSEPORT enabled for load balancing +[socket] Binding to 0.0.0.0:8080 +[socket] Binding to 0.0.0.0:8080 +[socket] SO_REUSEPORT enabled for load balancing +[socket] SO_REUSEPORT enabled for load balancing +[socket] SO_REUSEPORT enabled for load balancing +[socket] SO_REUSEPORT enabled for load balancing +[socket] Binding to 0.0.0.0:8080 +[socket] Binding to 0.0.0.0:8080 +[socket] SO_REUSEPORT enabled for load balancing +[socket] Binding to 0.0.0.0:8080 +[socket] SO_REUSEPORT enabled for load balancing +[socket] Binding to 0.0.0.0:8080 +[socket] Binding to 0.0.0.0:8080 +[socket] SO_REUSEPORT enabled for load balancing +[socket] SO_REUSEPORT enabled for load balancing +[socket] SO_REUSEPORT enabled for load balancing +[socket] SO_REUSEPORT enabled for load balancing +[socket] SO_REUSEPORT enabled for load balancing +[socket] SO_REUSEPORT enabled for load balancing +[socket] SO_REUSEPORT enabled for load balancing +[socket] SO_REUSEPORT enabled for load balancing +[socket] SO_REUSEPORT enabled for load balancing +[socket] Binding to 0.0.0.0:8080 +[socket] Binding to 0.0.0.0:8080 +[socket] Binding to 0.0.0.0:8080 +[socket] Binding to 0.0.0.0:8080 +[socket] Binding to 0.0.0.0:8080 +[socket] Binding to 0.0.0.0:8080 +[socket] Binding to 0.0.0.0:8080 +[socket] SO_REUSEPORT enabled for load balancing +[socket] SO_REUSEPORT enabled for load balancing +[socket] SO_REUSEPORT enabled for load balancing +[socket] Binding to 0.0.0.0:8080 +[socket] Binding to 0.0.0.0:8080 +[socket] Binding to 0.0.0.0:8080 +[socket] SO_REUSEPORT enabled for load balancing +[socket] Binding to 0.0.0.0:8080 +[socket] Binding to 0.0.0.0:8080 +[socket] Binding to 0.0.0.0:8080 +[socket] Binding to 0.0.0.0:8080 +[socket] Binding to 0.0.0.0:8080 +[socket] Binding to 0.0.0.0:8080 +[socket] Binding to 0.0.0.0:8080 +[socket] Binding to 0.0.0.0:8080 +[socket] Binding to 0.0.0.0:8080 +[socket] Binding to 0.0.0.0:8080 +[socket] Binding to 0.0.0.0:8080 +[socket] SO_REUSEPORT enabled for load balancing +[socket] SO_REUSEPORT enabled for load balancing +[socket] SO_REUSEPORT enabled for load balancing +[socket] SO_REUSEPORT enabled for load balancing +[socket] SO_REUSEPORT enabled for load balancing +[socket] SO_REUSEPORT enabled for load balancing +[socket] SO_REUSEPORT enabled for load balancing +[socket] Binding to 0.0.0.0:8080 +[socket] Binding to 0.0.0.0:8080 +[socket] Binding to 0.0.0.0:8080 +[socket] Binding to 0.0.0.0:8080 +[socket] SO_REUSEPORT enabled for load balancing +[socket] SO_REUSEPORT enabled for load balancing +[socket] SO_REUSEPORT enabled for load balancing +[socket] SO_REUSEPORT enabled for load balancing +[socket] Binding to 0.0.0.0:8080 +[socket] SO_REUSEPORT enabled for load balancing +[socket] SO_REUSEPORT enabled for load balancing +[socket] SO_REUSEPORT enabled for load balancing +[socket] Binding to 0.0.0.0:8080 +[socket] SO_REUSEPORT enabled for load balancing +[socket] SO_REUSEPORT enabled for load balancing +[socket] Binding to 0.0.0.0:8080 +[socket] SO_REUSEPORT enabled for load balancing +[socket] Binding to 0.0.0.0:8080 +[socket] SO_REUSEPORT enabled for load balancing +[socket] SO_REUSEPORT enabled for load balancing +[socket] SO_REUSEPORT enabled for load balancing +[socket] Binding to 0.0.0.0:8080 +[socket] SO_REUSEPORT enabled for load balancing +[socket] SO_REUSEPORT enabled for load balancing +[socket] Binding to 0.0.0.0:8080 +[socket] Binding to 0.0.0.0:8080 +[socket] Binding to 0.0.0.0:8080 +[socket] Binding to 0.0.0.0:8080 +[socket] Binding to 0.0.0.0:8080 +[socket] Binding to 0.0.0.0:8080 +[socket] SO_REUSEPORT enabled for load balancing +[socket] SO_REUSEPORT enabled for load balancing +[socket] SO_REUSEPORT enabled for load balancing +[socket] SO_REUSEPORT enabled for load balancing +[socket] SO_REUSEPORT enabled for load balancing +[socket] Binding to 0.0.0.0:8080 +[socket] SO_REUSEPORT enabled for load balancing +[socket] Binding to 0.0.0.0:8080 +[socket] Binding to 0.0.0.0:8080 +listening on http://localhost:8081/ +listening on http://localhost:8080/ (io_uring) diff --git a/site/static/logs/latency-1m/1024/vanilla-epoll.log b/site/static/logs/latency-1m/1024/vanilla-epoll.log new file mode 100644 index 000000000..029eef843 --- /dev/null +++ b/site/static/logs/latency-1m/1024/vanilla-epoll.log @@ -0,0 +1,6 @@ +[socket] SO_REUSEPORT enabled for load balancing +[socket] Binding to 0.0.0.0:8081 +[socket] Binding to 0.0.0.0:8080 +[socket] SO_REUSEPORT enabled for load balancing +listening on http://localhost:8080/ +listening on http://localhost:8081/ diff --git a/site/static/logs/latency-1m/1024/vanilla-io_uring.log b/site/static/logs/latency-1m/1024/vanilla-io_uring.log new file mode 100644 index 000000000..e8afb0a64 --- /dev/null +++ b/site/static/logs/latency-1m/1024/vanilla-io_uring.log @@ -0,0 +1,132 @@ +[socket] SO_REUSEPORT enabled for load balancing +[socket] Binding to 0.0.0.0:8081 +[socket] SO_REUSEPORT enabled for load balancing +[socket] SO_REUSEPORT enabled for load balancing +[socket] Binding to 0.0.0.0:8080 +[socket] Binding to 0.0.0.0:8080 +[socket] SO_REUSEPORT enabled for load balancing +[socket] Binding to 0.0.0.0:8080 +[socket] Binding to 0.0.0.0:8080 +[socket] Binding to 0.0.0.0:8080 +[socket] SO_REUSEPORT enabled for load balancing +[socket] SO_REUSEPORT enabled for load balancing +[socket] Binding to 0.0.0.0:8080 +[socket] SO_REUSEPORT enabled for load balancing +[socket] Binding to 0.0.0.0:8080 +[socket] SO_REUSEPORT enabled for load balancing +[socket] SO_REUSEPORT enabled for load balancing +[socket] Binding to 0.0.0.0:8080 +[socket] Binding to 0.0.0.0:8080 +[socket] Binding to 0.0.0.0:8080 +[socket] Binding to 0.0.0.0:8080 +[socket] Binding to 0.0.0.0:8080 +[socket] Binding to 0.0.0.0:8080 +[socket] SO_REUSEPORT enabled for load balancing +[socket] SO_REUSEPORT enabled for load balancing +[socket] SO_REUSEPORT enabled for load balancing +[socket] SO_REUSEPORT enabled for load balancing +[socket] SO_REUSEPORT enabled for load balancing +[socket] SO_REUSEPORT enabled for load balancing +[socket] Binding to 0.0.0.0:8080 +[socket] Binding to 0.0.0.0:8080 +[socket] Binding to 0.0.0.0:8080 +[socket] SO_REUSEPORT enabled for load balancing +[socket] Binding to 0.0.0.0:8080 +[socket] SO_REUSEPORT enabled for load balancing +[socket] SO_REUSEPORT enabled for load balancing +[socket] SO_REUSEPORT enabled for load balancing +[socket] SO_REUSEPORT enabled for load balancing +[socket] SO_REUSEPORT enabled for load balancing +[socket] Binding to 0.0.0.0:8080 +[socket] Binding to 0.0.0.0:8080 +[socket] Binding to 0.0.0.0:8080 +[socket] SO_REUSEPORT enabled for load balancing +[socket] Binding to 0.0.0.0:8080 +[socket] SO_REUSEPORT enabled for load balancing +[socket] Binding to 0.0.0.0:8080 +[socket] SO_REUSEPORT enabled for load balancing +[socket] Binding to 0.0.0.0:8080 +[socket] Binding to 0.0.0.0:8080 +[socket] SO_REUSEPORT enabled for load balancing +[socket] Binding to 0.0.0.0:8080 +[socket] Binding to 0.0.0.0:8080 +[socket] Binding to 0.0.0.0:8080 +[socket] SO_REUSEPORT enabled for load balancing +[socket] SO_REUSEPORT enabled for load balancing +[socket] SO_REUSEPORT enabled for load balancing +[socket] SO_REUSEPORT enabled for load balancing +[socket] Binding to 0.0.0.0:8080 +[socket] SO_REUSEPORT enabled for load balancing +[socket] Binding to 0.0.0.0:8080 +[socket] Binding to 0.0.0.0:8080 +[socket] Binding to 0.0.0.0:8080 +[socket] SO_REUSEPORT enabled for load balancing +[socket] SO_REUSEPORT enabled for load balancing +[socket] Binding to 0.0.0.0:8080 +[socket] Binding to 0.0.0.0:8080 +[socket] SO_REUSEPORT enabled for load balancing +[socket] SO_REUSEPORT enabled for load balancing +[socket] SO_REUSEPORT enabled for load balancing +[socket] SO_REUSEPORT enabled for load balancing +[socket] Binding to 0.0.0.0:8080 +[socket] Binding to 0.0.0.0:8080 +[socket] SO_REUSEPORT enabled for load balancing +[socket] Binding to 0.0.0.0:8080 +[socket] Binding to 0.0.0.0:8080 +[socket] SO_REUSEPORT enabled for load balancing +[socket] Binding to 0.0.0.0:8080 +[socket] SO_REUSEPORT enabled for load balancing +[socket] Binding to 0.0.0.0:8080 +[socket] Binding to 0.0.0.0:8080 +[socket] Binding to 0.0.0.0:8080 +[socket] Binding to 0.0.0.0:8080 +[socket] Binding to 0.0.0.0:8080 +[socket] Binding to 0.0.0.0:8080 +[socket] SO_REUSEPORT enabled for load balancing +[socket] SO_REUSEPORT enabled for load balancing +[socket] Binding to 0.0.0.0:8080 +[socket] SO_REUSEPORT enabled for load balancing +[socket] SO_REUSEPORT enabled for load balancing +[socket] Binding to 0.0.0.0:8080 +[socket] SO_REUSEPORT enabled for load balancing +[socket] SO_REUSEPORT enabled for load balancing +[socket] SO_REUSEPORT enabled for load balancing +[socket] SO_REUSEPORT enabled for load balancing +[socket] SO_REUSEPORT enabled for load balancing +[socket] SO_REUSEPORT enabled for load balancing +[socket] Binding to 0.0.0.0:8080 +[socket] Binding to 0.0.0.0:8080 +[socket] SO_REUSEPORT enabled for load balancing +[socket] Binding to 0.0.0.0:8080 +[socket] SO_REUSEPORT enabled for load balancing +[socket] SO_REUSEPORT enabled for load balancing +[socket] SO_REUSEPORT enabled for load balancing +[socket] SO_REUSEPORT enabled for load balancing +[socket] SO_REUSEPORT enabled for load balancing +[socket] SO_REUSEPORT enabled for load balancing +[socket] SO_REUSEPORT enabled for load balancing +[socket] Binding to 0.0.0.0:8080 +[socket] Binding to 0.0.0.0:8080 +[socket] Binding to 0.0.0.0:8080 +[socket] Binding to 0.0.0.0:8080 +[socket] Binding to 0.0.0.0:8080 +[socket] SO_REUSEPORT enabled for load balancing +[socket] Binding to 0.0.0.0:8080 +[socket] SO_REUSEPORT enabled for load balancing +[socket] Binding to 0.0.0.0:8080 +[socket] SO_REUSEPORT enabled for load balancing +[socket] Binding to 0.0.0.0:8080 +[socket] SO_REUSEPORT enabled for load balancing +[socket] Binding to 0.0.0.0:8080 +[socket] Binding to 0.0.0.0:8080 +[socket] Binding to 0.0.0.0:8080 +[socket] Binding to 0.0.0.0:8080 +[socket] Binding to 0.0.0.0:8080 +[socket] SO_REUSEPORT enabled for load balancing +[socket] SO_REUSEPORT enabled for load balancing +[socket] SO_REUSEPORT enabled for load balancing +[socket] SO_REUSEPORT enabled for load balancing +[socket] Binding to 0.0.0.0:8080 +[socket] Binding to 0.0.0.0:8080 +listening on http://localhost:8081/ +listening on http://localhost:8080/ (io_uring) diff --git a/site/static/logs/latency-500k-8cpu/1024/vanilla-epoll.log b/site/static/logs/latency-500k-8cpu/1024/vanilla-epoll.log new file mode 100644 index 000000000..dee8f8a58 --- /dev/null +++ b/site/static/logs/latency-500k-8cpu/1024/vanilla-epoll.log @@ -0,0 +1,6 @@ +[socket] Binding to 0.0.0.0:8081 +[socket] SO_REUSEPORT enabled for load balancing +[socket] Binding to 0.0.0.0:8080 +[socket] SO_REUSEPORT enabled for load balancing +listening on http://localhost:8080/ +listening on http://localhost:8081/ diff --git a/site/static/logs/latency-500k-8cpu/1024/vanilla-io_uring.log b/site/static/logs/latency-500k-8cpu/1024/vanilla-io_uring.log new file mode 100644 index 000000000..ab45fc825 --- /dev/null +++ b/site/static/logs/latency-500k-8cpu/1024/vanilla-io_uring.log @@ -0,0 +1,20 @@ +[socket] Binding to 0.0.0.0:8081 +[socket] SO_REUSEPORT enabled for load balancing +[socket] SO_REUSEPORT enabled for load balancing +[socket] SO_REUSEPORT enabled for load balancing +[socket] SO_REUSEPORT enabled for load balancing +[socket] SO_REUSEPORT enabled for load balancing +[socket] Binding to 0.0.0.0:8080 +[socket] Binding to 0.0.0.0:8080 +[socket] Binding to 0.0.0.0:8080 +[socket] Binding to 0.0.0.0:8080 +[socket] Binding to 0.0.0.0:8080 +[socket] Binding to 0.0.0.0:8080 +[socket] Binding to 0.0.0.0:8080 +[socket] Binding to 0.0.0.0:8080 +[socket] SO_REUSEPORT enabled for load balancing +[socket] SO_REUSEPORT enabled for load balancing +[socket] SO_REUSEPORT enabled for load balancing +[socket] SO_REUSEPORT enabled for load balancing +listening on http://localhost:8081/ +listening on http://localhost:8080/ (io_uring) diff --git a/site/static/logs/limited-conn/4096/vanilla-epoll.log b/site/static/logs/limited-conn/4096/vanilla-epoll.log index 9de548a21..1c153209f 100644 --- a/site/static/logs/limited-conn/4096/vanilla-epoll.log +++ b/site/static/logs/limited-conn/4096/vanilla-epoll.log @@ -1,6 +1,6 @@ -[socket] Binding to 0.0.0.0:8081 [socket] SO_REUSEPORT enabled for load balancing -[socket] Binding to 0.0.0.0:8080 [socket] SO_REUSEPORT enabled for load balancing -listening on http://localhost:8081/ +[socket] Binding to 0.0.0.0:8081 +[socket] Binding to 0.0.0.0:8080 listening on http://localhost:8080/ +listening on http://localhost:8081/ diff --git a/site/static/logs/limited-conn/4096/vanilla-io_uring.log b/site/static/logs/limited-conn/4096/vanilla-io_uring.log index 58bd3e29f..df80e27a5 100644 --- a/site/static/logs/limited-conn/4096/vanilla-io_uring.log +++ b/site/static/logs/limited-conn/4096/vanilla-io_uring.log @@ -1,16 +1,7 @@ [socket] Binding to 0.0.0.0:8081 [socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 [socket] Binding to 0.0.0.0:8080 [socket] Binding to 0.0.0.0:8080 -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] Binding to 0.0.0.0:8080 [socket] Binding to 0.0.0.0:8080 [socket] Binding to 0.0.0.0:8080 [socket] Binding to 0.0.0.0:8080 @@ -19,126 +10,62 @@ [socket] SO_REUSEPORT enabled for load balancing [socket] SO_REUSEPORT enabled for load balancing [socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 -[socket] SO_REUSEPORT enabled for load balancing [socket] Binding to 0.0.0.0:8080 [socket] Binding to 0.0.0.0:8080 [socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing [socket] SO_REUSEPORT enabled for load balancing [socket] SO_REUSEPORT enabled for load balancing [socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 [socket] Binding to 0.0.0.0:8080 [socket] Binding to 0.0.0.0:8080 [socket] SO_REUSEPORT enabled for load balancing -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing [socket] SO_REUSEPORT enabled for load balancing [socket] Binding to 0.0.0.0:8080 [socket] SO_REUSEPORT enabled for load balancing -[socket] Binding to 0.0.0.0:8080 [socket] SO_REUSEPORT enabled for load balancing -[socket] Binding to 0.0.0.0:8080 [socket] SO_REUSEPORT enabled for load balancing -[socket] Binding to 0.0.0.0:8080 [socket] SO_REUSEPORT enabled for load balancing [socket] Binding to 0.0.0.0:8080 -[socket] SO_REUSEPORT enabled for load balancing [socket] Binding to 0.0.0.0:8080 [socket] SO_REUSEPORT enabled for load balancing [socket] Binding to 0.0.0.0:8080 [socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing [socket] Binding to 0.0.0.0:8080 -[socket] SO_REUSEPORT enabled for load balancing [socket] Binding to 0.0.0.0:8080 -[socket] SO_REUSEPORT enabled for load balancing [socket] Binding to 0.0.0.0:8080 -[socket] SO_REUSEPORT enabled for load balancing [socket] Binding to 0.0.0.0:8080 [socket] SO_REUSEPORT enabled for load balancing -[socket] Binding to 0.0.0.0:8080 [socket] SO_REUSEPORT enabled for load balancing -[socket] Binding to 0.0.0.0:8080 [socket] SO_REUSEPORT enabled for load balancing [socket] Binding to 0.0.0.0:8080 [socket] SO_REUSEPORT enabled for load balancing [socket] Binding to 0.0.0.0:8080 [socket] SO_REUSEPORT enabled for load balancing [socket] Binding to 0.0.0.0:8080 -[socket] SO_REUSEPORT enabled for load balancing [socket] Binding to 0.0.0.0:8080 [socket] SO_REUSEPORT enabled for load balancing -[socket] Binding to 0.0.0.0:8080 [socket] SO_REUSEPORT enabled for load balancing -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 [socket] SO_REUSEPORT enabled for load balancing -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 [socket] SO_REUSEPORT enabled for load balancing [socket] Binding to 0.0.0.0:8080 [socket] Binding to 0.0.0.0:8080 [socket] Binding to 0.0.0.0:8080 -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] Binding to 0.0.0.0:8080 -[socket] SO_REUSEPORT enabled for load balancing [socket] Binding to 0.0.0.0:8080 [socket] Binding to 0.0.0.0:8080 [socket] SO_REUSEPORT enabled for load balancing [socket] SO_REUSEPORT enabled for load balancing [socket] SO_REUSEPORT enabled for load balancing [socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 [socket] SO_REUSEPORT enabled for load balancing [socket] Binding to 0.0.0.0:8080 -[socket] SO_REUSEPORT enabled for load balancing [socket] Binding to 0.0.0.0:8080 [socket] SO_REUSEPORT enabled for load balancing [socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 [socket] SO_REUSEPORT enabled for load balancing [socket] Binding to 0.0.0.0:8080 [socket] SO_REUSEPORT enabled for load balancing [socket] SO_REUSEPORT enabled for load balancing [socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 -[socket] SO_REUSEPORT enabled for load balancing [socket] Binding to 0.0.0.0:8080 [socket] Binding to 0.0.0.0:8080 [socket] SO_REUSEPORT enabled for load balancing @@ -151,39 +78,15 @@ [socket] SO_REUSEPORT enabled for load balancing [socket] Binding to 0.0.0.0:8080 [socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] Binding to 0.0.0.0:8080 -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] Binding to 0.0.0.0:8080 [socket] SO_REUSEPORT enabled for load balancing [socket] Binding to 0.0.0.0:8080 [socket] SO_REUSEPORT enabled for load balancing [socket] Binding to 0.0.0.0:8080 -[socket] SO_REUSEPORT enabled for load balancing [socket] Binding to 0.0.0.0:8080 [socket] SO_REUSEPORT enabled for load balancing [socket] Binding to 0.0.0.0:8080 [socket] SO_REUSEPORT enabled for load balancing [socket] Binding to 0.0.0.0:8080 -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing [socket] Binding to 0.0.0.0:8080 [socket] Binding to 0.0.0.0:8080 [socket] Binding to 0.0.0.0:8080 @@ -191,70 +94,39 @@ [socket] SO_REUSEPORT enabled for load balancing [socket] SO_REUSEPORT enabled for load balancing [socket] Binding to 0.0.0.0:8080 -[socket] SO_REUSEPORT enabled for load balancing [socket] Binding to 0.0.0.0:8080 -[socket] SO_REUSEPORT enabled for load balancing -[socket] Binding to 0.0.0.0:8080 -[socket] SO_REUSEPORT enabled for load balancing -[socket] Binding to 0.0.0.0:8080 -[socket] SO_REUSEPORT enabled for load balancing [socket] Binding to 0.0.0.0:8080 [socket] SO_REUSEPORT enabled for load balancing [socket] SO_REUSEPORT enabled for load balancing [socket] SO_REUSEPORT enabled for load balancing [socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing [socket] Binding to 0.0.0.0:8080 [socket] Binding to 0.0.0.0:8080 [socket] SO_REUSEPORT enabled for load balancing [socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 [socket] SO_REUSEPORT enabled for load balancing [socket] SO_REUSEPORT enabled for load balancing [socket] Binding to 0.0.0.0:8080 -[socket] SO_REUSEPORT enabled for load balancing [socket] Binding to 0.0.0.0:8080 -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing [socket] Binding to 0.0.0.0:8080 [socket] Binding to 0.0.0.0:8080 [socket] Binding to 0.0.0.0:8080 [socket] SO_REUSEPORT enabled for load balancing [socket] SO_REUSEPORT enabled for load balancing -[socket] Binding to 0.0.0.0:8080 [socket] SO_REUSEPORT enabled for load balancing [socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 [socket] SO_REUSEPORT enabled for load balancing [socket] Binding to 0.0.0.0:8080 [socket] Binding to 0.0.0.0:8080 [socket] SO_REUSEPORT enabled for load balancing [socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 [socket] Binding to 0.0.0.0:8080 [socket] Binding to 0.0.0.0:8080 [socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] Binding to 0.0.0.0:8080 [socket] Binding to 0.0.0.0:8080 [socket] SO_REUSEPORT enabled for load balancing [socket] SO_REUSEPORT enabled for load balancing -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 -[socket] SO_REUSEPORT enabled for load balancing [socket] SO_REUSEPORT enabled for load balancing +[socket] Binding to 0.0.0.0:8080 listening on http://localhost:8081/ listening on http://localhost:8080/ (io_uring) diff --git a/site/static/logs/pipelined/4096/vanilla-epoll.log b/site/static/logs/pipelined/4096/vanilla-epoll.log index 9de548a21..dee8f8a58 100644 --- a/site/static/logs/pipelined/4096/vanilla-epoll.log +++ b/site/static/logs/pipelined/4096/vanilla-epoll.log @@ -2,5 +2,5 @@ [socket] SO_REUSEPORT enabled for load balancing [socket] Binding to 0.0.0.0:8080 [socket] SO_REUSEPORT enabled for load balancing -listening on http://localhost:8081/ listening on http://localhost:8080/ +listening on http://localhost:8081/ diff --git a/site/static/logs/pipelined/4096/vanilla-io_uring.log b/site/static/logs/pipelined/4096/vanilla-io_uring.log index 463bccd41..591aa9352 100644 --- a/site/static/logs/pipelined/4096/vanilla-io_uring.log +++ b/site/static/logs/pipelined/4096/vanilla-io_uring.log @@ -1,30 +1,14 @@ -[socket] Binding to 0.0.0.0:8081 -[socket] SO_REUSEPORT enabled for load balancing -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 [socket] SO_REUSEPORT enabled for load balancing +[socket] Binding to 0.0.0.0:8081 [socket] SO_REUSEPORT enabled for load balancing [socket] SO_REUSEPORT enabled for load balancing -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 [socket] SO_REUSEPORT enabled for load balancing -[socket] Binding to 0.0.0.0:8080 [socket] SO_REUSEPORT enabled for load balancing [socket] Binding to 0.0.0.0:8080 -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing [socket] Binding to 0.0.0.0:8080 [socket] Binding to 0.0.0.0:8080 -[socket] SO_REUSEPORT enabled for load balancing [socket] Binding to 0.0.0.0:8080 -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing [socket] Binding to 0.0.0.0:8080 -[socket] SO_REUSEPORT enabled for load balancing [socket] Binding to 0.0.0.0:8080 [socket] Binding to 0.0.0.0:8080 [socket] Binding to 0.0.0.0:8080 @@ -33,69 +17,29 @@ [socket] SO_REUSEPORT enabled for load balancing [socket] SO_REUSEPORT enabled for load balancing [socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing [socket] Binding to 0.0.0.0:8080 [socket] Binding to 0.0.0.0:8080 [socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 [socket] Binding to 0.0.0.0:8080 [socket] SO_REUSEPORT enabled for load balancing -[socket] Binding to 0.0.0.0:8080 -[socket] SO_REUSEPORT enabled for load balancing -[socket] Binding to 0.0.0.0:8080 [socket] SO_REUSEPORT enabled for load balancing [socket] SO_REUSEPORT enabled for load balancing [socket] Binding to 0.0.0.0:8080 [socket] SO_REUSEPORT enabled for load balancing -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 [socket] SO_REUSEPORT enabled for load balancing -[socket] Binding to 0.0.0.0:8080 [socket] SO_REUSEPORT enabled for load balancing [socket] Binding to 0.0.0.0:8080 [socket] SO_REUSEPORT enabled for load balancing [socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 [socket] SO_REUSEPORT enabled for load balancing [socket] Binding to 0.0.0.0:8080 -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing [socket] Binding to 0.0.0.0:8080 [socket] Binding to 0.0.0.0:8080 -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing [socket] Binding to 0.0.0.0:8080 -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] Binding to 0.0.0.0:8080 -[socket] SO_REUSEPORT enabled for load balancing -[socket] Binding to 0.0.0.0:8080 -[socket] SO_REUSEPORT enabled for load balancing -[socket] Binding to 0.0.0.0:8080 -[socket] SO_REUSEPORT enabled for load balancing -[socket] Binding to 0.0.0.0:8080 -[socket] SO_REUSEPORT enabled for load balancing [socket] Binding to 0.0.0.0:8080 [socket] SO_REUSEPORT enabled for load balancing [socket] SO_REUSEPORT enabled for load balancing [socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing [socket] Binding to 0.0.0.0:8080 [socket] Binding to 0.0.0.0:8080 [socket] Binding to 0.0.0.0:8080 @@ -103,30 +47,15 @@ [socket] Binding to 0.0.0.0:8080 [socket] Binding to 0.0.0.0:8080 [socket] Binding to 0.0.0.0:8080 -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing [socket] Binding to 0.0.0.0:8080 [socket] Binding to 0.0.0.0:8080 [socket] Binding to 0.0.0.0:8080 [socket] Binding to 0.0.0.0:8080 [socket] Binding to 0.0.0.0:8080 [socket] Binding to 0.0.0.0:8080 -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] Binding to 0.0.0.0:8080 -[socket] SO_REUSEPORT enabled for load balancing -[socket] Binding to 0.0.0.0:8080 -[socket] SO_REUSEPORT enabled for load balancing [socket] Binding to 0.0.0.0:8080 [socket] SO_REUSEPORT enabled for load balancing [socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 [socket] SO_REUSEPORT enabled for load balancing [socket] SO_REUSEPORT enabled for load balancing [socket] SO_REUSEPORT enabled for load balancing @@ -136,40 +65,13 @@ [socket] SO_REUSEPORT enabled for load balancing [socket] SO_REUSEPORT enabled for load balancing [socket] SO_REUSEPORT enabled for load balancing -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 [socket] SO_REUSEPORT enabled for load balancing -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 [socket] SO_REUSEPORT enabled for load balancing -[socket] Binding to 0.0.0.0:8080 [socket] SO_REUSEPORT enabled for load balancing [socket] SO_REUSEPORT enabled for load balancing -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 [socket] SO_REUSEPORT enabled for load balancing -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 [socket] SO_REUSEPORT enabled for load balancing [socket] SO_REUSEPORT enabled for load balancing -[socket] Binding to 0.0.0.0:8080 -[socket] SO_REUSEPORT enabled for load balancing -[socket] Binding to 0.0.0.0:8080 -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] Binding to 0.0.0.0:8080 [socket] SO_REUSEPORT enabled for load balancing [socket] SO_REUSEPORT enabled for load balancing [socket] Binding to 0.0.0.0:8080 @@ -178,25 +80,13 @@ [socket] Binding to 0.0.0.0:8080 [socket] SO_REUSEPORT enabled for load balancing [socket] Binding to 0.0.0.0:8080 -[socket] SO_REUSEPORT enabled for load balancing [socket] Binding to 0.0.0.0:8080 [socket] SO_REUSEPORT enabled for load balancing [socket] Binding to 0.0.0.0:8080 -[socket] SO_REUSEPORT enabled for load balancing [socket] Binding to 0.0.0.0:8080 [socket] Binding to 0.0.0.0:8080 [socket] Binding to 0.0.0.0:8080 [socket] SO_REUSEPORT enabled for load balancing -[socket] Binding to 0.0.0.0:8080 -[socket] SO_REUSEPORT enabled for load balancing -[socket] Binding to 0.0.0.0:8080 -[socket] SO_REUSEPORT enabled for load balancing -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing [socket] SO_REUSEPORT enabled for load balancing [socket] SO_REUSEPORT enabled for load balancing [socket] SO_REUSEPORT enabled for load balancing @@ -213,18 +103,6 @@ [socket] SO_REUSEPORT enabled for load balancing [socket] SO_REUSEPORT enabled for load balancing [socket] SO_REUSEPORT enabled for load balancing -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing [socket] SO_REUSEPORT enabled for load balancing [socket] SO_REUSEPORT enabled for load balancing [socket] SO_REUSEPORT enabled for load balancing @@ -232,23 +110,16 @@ [socket] SO_REUSEPORT enabled for load balancing [socket] SO_REUSEPORT enabled for load balancing [socket] Binding to 0.0.0.0:8080 +[socket] SO_REUSEPORT enabled for load balancing [socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 -[socket] Binding to 0.0.0.0:8080 +[socket] SO_REUSEPORT enabled for load balancing [socket] Binding to 0.0.0.0:8080 [socket] Binding to 0.0.0.0:8080 [socket] Binding to 0.0.0.0:8080 [socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing -[socket] SO_REUSEPORT enabled for load balancing [socket] Binding to 0.0.0.0:8080 -[socket] SO_REUSEPORT enabled for load balancing [socket] Binding to 0.0.0.0:8080 -[socket] SO_REUSEPORT enabled for load balancing [socket] Binding to 0.0.0.0:8080 -[socket] SO_REUSEPORT enabled for load balancing [socket] Binding to 0.0.0.0:8080 [socket] Binding to 0.0.0.0:8080 [socket] Binding to 0.0.0.0:8080 @@ -256,5 +127,6 @@ [socket] Binding to 0.0.0.0:8080 [socket] Binding to 0.0.0.0:8080 [socket] Binding to 0.0.0.0:8080 -listening on http://localhost:8080/ (io_uring) +[socket] Binding to 0.0.0.0:8080 listening on http://localhost:8081/ +listening on http://localhost:8080/ (io_uring) diff --git a/site/static/logs/production-stack/1024/vanilla-production.log b/site/static/logs/production-stack/1024/vanilla-production.log new file mode 100644 index 000000000..bcc1b0fe0 --- /dev/null +++ b/site/static/logs/production-stack/1024/vanilla-production.log @@ -0,0 +1 @@ +Error response from daemon: No such container: httparena-bench-vanilla-production diff --git a/site/static/logs/production-stack/256/vanilla-production.log b/site/static/logs/production-stack/256/vanilla-production.log new file mode 100644 index 000000000..bcc1b0fe0 --- /dev/null +++ b/site/static/logs/production-stack/256/vanilla-production.log @@ -0,0 +1 @@ +Error response from daemon: No such container: httparena-bench-vanilla-production diff --git a/site/static/logs/static-tls/1024/vanilla-epoll.log b/site/static/logs/static-tls/1024/vanilla-epoll.log new file mode 100644 index 000000000..4f224bfad --- /dev/null +++ b/site/static/logs/static-tls/1024/vanilla-epoll.log @@ -0,0 +1,7 @@ +[socket] SO_REUSEPORT enabled for load balancing +[socket] Binding to 0.0.0.0:8081 +[socket] Binding to 0.0.0.0:8080 +[socket] SO_REUSEPORT enabled for load balancing +listening on http://localhost:8080/ +listening on http://localhost:8081/ +[ktls] engaged: kernel TLS TX+RX (TLS 1.3, AES-128-GCM) diff --git a/site/static/logs/static-tls/1024/vanilla-io_uring.log b/site/static/logs/static-tls/1024/vanilla-io_uring.log new file mode 100644 index 000000000..79366426f --- /dev/null +++ b/site/static/logs/static-tls/1024/vanilla-io_uring.log @@ -0,0 +1,133 @@ +[socket] Binding to 0.0.0.0:8081 +[socket] SO_REUSEPORT enabled for load balancing +[socket] Binding to 0.0.0.0:8080 +[socket] Binding to 0.0.0.0:8080 +[socket] Binding to 0.0.0.0:8080 +[socket] SO_REUSEPORT enabled for load balancing +[socket] SO_REUSEPORT enabled for load balancing +[socket] Binding to 0.0.0.0:8080 +[socket] Binding to 0.0.0.0:8080 +[socket] SO_REUSEPORT enabled for load balancing +[socket] Binding to 0.0.0.0:8080 +[socket] SO_REUSEPORT enabled for load balancing +[socket] SO_REUSEPORT enabled for load balancing +[socket] SO_REUSEPORT enabled for load balancing +[socket] Binding to 0.0.0.0:8080 +[socket] SO_REUSEPORT enabled for load balancing +[socket] Binding to 0.0.0.0:8080 +[socket] Binding to 0.0.0.0:8080 +[socket] Binding to 0.0.0.0:8080 +[socket] SO_REUSEPORT enabled for load balancing +[socket] Binding to 0.0.0.0:8080 +[socket] SO_REUSEPORT enabled for load balancing +[socket] SO_REUSEPORT enabled for load balancing +[socket] SO_REUSEPORT enabled for load balancing +[socket] Binding to 0.0.0.0:8080 +[socket] Binding to 0.0.0.0:8080 +[socket] SO_REUSEPORT enabled for load balancing +[socket] SO_REUSEPORT enabled for load balancing +[socket] Binding to 0.0.0.0:8080 +[socket] Binding to 0.0.0.0:8080 +[socket] Binding to 0.0.0.0:8080 +[socket] Binding to 0.0.0.0:8080 +[socket] SO_REUSEPORT enabled for load balancing +[socket] SO_REUSEPORT enabled for load balancing +[socket] SO_REUSEPORT enabled for load balancing +[socket] SO_REUSEPORT enabled for load balancing +[socket] SO_REUSEPORT enabled for load balancing +[socket] SO_REUSEPORT enabled for load balancing +[socket] Binding to 0.0.0.0:8080 +[socket] Binding to 0.0.0.0:8080 +[socket] Binding to 0.0.0.0:8080 +[socket] Binding to 0.0.0.0:8080 +[socket] SO_REUSEPORT enabled for load balancing +[socket] SO_REUSEPORT enabled for load balancing +[socket] SO_REUSEPORT enabled for load balancing +[socket] Binding to 0.0.0.0:8080 +[socket] SO_REUSEPORT enabled for load balancing +[socket] Binding to 0.0.0.0:8080 +[socket] SO_REUSEPORT enabled for load balancing +[socket] Binding to 0.0.0.0:8080 +[socket] SO_REUSEPORT enabled for load balancing +[socket] Binding to 0.0.0.0:8080 +[socket] SO_REUSEPORT enabled for load balancing +[socket] Binding to 0.0.0.0:8080 +[socket] Binding to 0.0.0.0:8080 +[socket] Binding to 0.0.0.0:8080 +[socket] SO_REUSEPORT enabled for load balancing +[socket] Binding to 0.0.0.0:8080 +[socket] SO_REUSEPORT enabled for load balancing +[socket] Binding to 0.0.0.0:8080 +[socket] SO_REUSEPORT enabled for load balancing +[socket] Binding to 0.0.0.0:8080 +[socket] SO_REUSEPORT enabled for load balancing +[socket] SO_REUSEPORT enabled for load balancing +[socket] Binding to 0.0.0.0:8080 +[socket] Binding to 0.0.0.0:8080 +[socket] SO_REUSEPORT enabled for load balancing +[socket] SO_REUSEPORT enabled for load balancing +[socket] Binding to 0.0.0.0:8080 +[socket] Binding to 0.0.0.0:8080 +[socket] SO_REUSEPORT enabled for load balancing +[socket] SO_REUSEPORT enabled for load balancing +[socket] Binding to 0.0.0.0:8080 +[socket] Binding to 0.0.0.0:8080 +[socket] Binding to 0.0.0.0:8080 +[socket] Binding to 0.0.0.0:8080 +[socket] Binding to 0.0.0.0:8080 +[socket] SO_REUSEPORT enabled for load balancing +[socket] Binding to 0.0.0.0:8080 +[socket] Binding to 0.0.0.0:8080 +[socket] SO_REUSEPORT enabled for load balancing +[socket] Binding to 0.0.0.0:8080 +[socket] SO_REUSEPORT enabled for load balancing +[socket] SO_REUSEPORT enabled for load balancing +[socket] SO_REUSEPORT enabled for load balancing +[socket] Binding to 0.0.0.0:8080 +[socket] SO_REUSEPORT enabled for load balancing +[socket] SO_REUSEPORT enabled for load balancing +[socket] Binding to 0.0.0.0:8080 +[socket] SO_REUSEPORT enabled for load balancing +[socket] Binding to 0.0.0.0:8080 +[socket] SO_REUSEPORT enabled for load balancing +[socket] Binding to 0.0.0.0:8080 +[socket] Binding to 0.0.0.0:8080 +[socket] SO_REUSEPORT enabled for load balancing +[socket] SO_REUSEPORT enabled for load balancing +[socket] SO_REUSEPORT enabled for load balancing +[socket] SO_REUSEPORT enabled for load balancing +[socket] SO_REUSEPORT enabled for load balancing +[socket] SO_REUSEPORT enabled for load balancing +[socket] SO_REUSEPORT enabled for load balancing +[socket] Binding to 0.0.0.0:8080 +[socket] Binding to 0.0.0.0:8080 +[socket] Binding to 0.0.0.0:8080 +[socket] Binding to 0.0.0.0:8080 +[socket] SO_REUSEPORT enabled for load balancing +[socket] Binding to 0.0.0.0:8080 +[socket] SO_REUSEPORT enabled for load balancing +[socket] Binding to 0.0.0.0:8080 +[socket] SO_REUSEPORT enabled for load balancing +[socket] Binding to 0.0.0.0:8080 +[socket] Binding to 0.0.0.0:8080 +[socket] SO_REUSEPORT enabled for load balancing +[socket] SO_REUSEPORT enabled for load balancing +[socket] SO_REUSEPORT enabled for load balancing +[socket] Binding to 0.0.0.0:8080 +[socket] Binding to 0.0.0.0:8080 +[socket] Binding to 0.0.0.0:8080 +[socket] Binding to 0.0.0.0:8080 +[socket] SO_REUSEPORT enabled for load balancing +[socket] SO_REUSEPORT enabled for load balancing +[socket] SO_REUSEPORT enabled for load balancing +[socket] SO_REUSEPORT enabled for load balancing +[socket] SO_REUSEPORT enabled for load balancing +[socket] SO_REUSEPORT enabled for load balancing +[socket] SO_REUSEPORT enabled for load balancing +[socket] Binding to 0.0.0.0:8080 +[socket] Binding to 0.0.0.0:8080 +[socket] Binding to 0.0.0.0:8080 +[socket] Binding to 0.0.0.0:8080 +listening on http://localhost:8081/ +[ktls] engaged: kernel TLS TX+RX (TLS 1.3, AES-128-GCM) +listening on http://localhost:8080/ (io_uring) diff --git a/site/static/logs/unary-grpc/1024/vanilla-h2c.log b/site/static/logs/unary-grpc/1024/vanilla-h2c.log new file mode 100644 index 000000000..a33b1d5ca --- /dev/null +++ b/site/static/logs/unary-grpc/1024/vanilla-h2c.log @@ -0,0 +1,6 @@ +[socket] Binding to 0.0.0.0:8080 +[socket] SO_REUSEPORT enabled for load balancing +[socket] Binding to 0.0.0.0:8082 +[socket] SO_REUSEPORT enabled for load balancing +listening on http://localhost:8082/ +listening on http://localhost:8080/ diff --git a/site/static/logs/unary-grpc/256/vanilla-h2c.log b/site/static/logs/unary-grpc/256/vanilla-h2c.log new file mode 100644 index 000000000..c135f8d73 --- /dev/null +++ b/site/static/logs/unary-grpc/256/vanilla-h2c.log @@ -0,0 +1,6 @@ +[socket] SO_REUSEPORT enabled for load balancing +[socket] Binding to 0.0.0.0:8080 +[socket] SO_REUSEPORT enabled for load balancing +[socket] Binding to 0.0.0.0:8082 +listening on http://localhost:8082/ +listening on http://localhost:8080/
idmessage