From a78a6d3877705b693eaf8b388622ff6c10c9177b Mon Sep 17 00:00:00 2001 From: praisethemoon Date: Mon, 18 May 2026 13:39:28 +0200 Subject: [PATCH 1/2] typev: aadd staatic, upload and echo benchs --- .../typev/bundle/benchmark-code/src/assets.tc | 216 +++++++++++ .../typev/bundle/benchmark-code/src/http.tc | 65 +++- .../typev/bundle/benchmark-code/src/main.tc | 85 ++++- .../typev/bundle/benchmark-code/src/ws.tc | 354 ++++++++++++++++++ frameworks/typev/bundle/output.tvbc | Bin 16501 -> 28673 bytes frameworks/typev/meta.json | 6 +- 6 files changed, 722 insertions(+), 4 deletions(-) create mode 100644 frameworks/typev/bundle/benchmark-code/src/assets.tc create mode 100644 frameworks/typev/bundle/benchmark-code/src/ws.tc diff --git a/frameworks/typev/bundle/benchmark-code/src/assets.tc b/frameworks/typev/bundle/benchmark-code/src/assets.tc new file mode 100644 index 000000000..253b5b4bd --- /dev/null +++ b/frameworks/typev/bundle/benchmark-code/src/assets.tc @@ -0,0 +1,216 @@ +// assets.tc — GET /static/ serving for the HttpArena `static` test. +// +// Every asset, plus its precompressed .gz / .br siblings, is loaded once at +// module init. A request builds ~250 bytes of headers in the caller's +// scratch buffer and streams the asset body straight from the loaded copy — +// no per-request copy of the body. + +from std.fs import readBytes +from std.socket import tcp_write +from response import writeBytes, writeInt + +// One static asset: raw bytes, optional precompressed variants, metadata. +// raw/gz/br are uint[] — that is what readBytes returns and what tcp_write +// consumes, so the bytes never need re-typing. gz/br stay empty if absent. +type Asset = struct { + name: byte[], + ctype: byte[], + raw: uint[], + gz: uint[], + br: uint[] +} + +type StaticSet = struct { + items: Asset[], + n: int +} + +// The container mounts the asset tree here (same as /data/dataset.json). +let const STATIC_DIR: string = "/data/static/" + +// Content-Type values, byte-encoded once. +let local const CT_CSS: byte[] = "text/css".bytes() +let local const CT_JS: byte[] = "application/javascript".bytes() +let local const CT_JSON: byte[] = "application/json".bytes() +let local const CT_HTML: byte[] = "text/html".bytes() +let local const CT_SVG: byte[] = "image/svg+xml".bytes() +let local const CT_WOFF2: byte[] = "font/woff2".bytes() +let local const CT_WEBP: byte[] = "image/webp".bytes() + +// Response structural literals. +let local const S_STATUS_CT: byte[] = "HTTP/1.1 200 OK\r\nContent-Type: ".bytes() +let local const S_ENC_BR: byte[] = "\r\nContent-Encoding: br".bytes() +let local const S_ENC_GZIP: byte[] = "\r\nContent-Encoding: gzip".bytes() +let local const S_CL: byte[] = "\r\nContent-Length: ".bytes() +let local const S_CONN_KA: byte[] = "\r\nConnection: keep-alive\r\n\r\n".bytes() +let local const S_CONN_CL: byte[] = "\r\nConnection: close\r\n\r\n".bytes() +let local const S_NOT_FOUND: byte[] = "HTTP/1.1 404 Not Found\r\nContent-Length: 0\r\nConnection: close\r\n\r\n".bytes() + +// Read one asset and, if compressible, its .gz / .br precompressed siblings. +local fn loadAsset(name: string, ctype: byte[], compressible: bool) -> Asset { + let (raw, st) = readBytes(STATIC_DIR + name) + let gz: uint[] = [] + let br: uint[] = [] + if compressible { + let (g, gst) = readBytes(STATIC_DIR + name + ".gz") + if gst == 0 { + gz = g + } + let (b, bst) = readBytes(STATIC_DIR + name + ".br") + if bst == 0 { + br = b + } + } + let a: Asset = {name: name.bytes(), ctype: ctype, raw: raw, gz: gz, br: br} + return a +} + +// Load the full asset set once. The 20 names are fixed by the benchmark. +fn loadStatic() -> StaticSet { + let items: Asset[] = [] + items.push(loadAsset("reset.css", CT_CSS, true)) + items.push(loadAsset("layout.css", CT_CSS, true)) + items.push(loadAsset("theme.css", CT_CSS, true)) + items.push(loadAsset("components.css", CT_CSS, true)) + items.push(loadAsset("utilities.css", CT_CSS, true)) + items.push(loadAsset("analytics.js", CT_JS, true)) + items.push(loadAsset("helpers.js", CT_JS, true)) + items.push(loadAsset("app.js", CT_JS, true)) + items.push(loadAsset("vendor.js", CT_JS, true)) + items.push(loadAsset("router.js", CT_JS, true)) + items.push(loadAsset("header.html", CT_HTML, true)) + items.push(loadAsset("footer.html", CT_HTML, true)) + items.push(loadAsset("regular.woff2", CT_WOFF2, false)) + items.push(loadAsset("bold.woff2", CT_WOFF2, false)) + items.push(loadAsset("logo.svg", CT_SVG, true)) + items.push(loadAsset("icon-sprite.svg", CT_SVG, true)) + items.push(loadAsset("hero.webp", CT_WEBP, false)) + items.push(loadAsset("thumb1.webp", CT_WEBP, false)) + items.push(loadAsset("thumb2.webp", CT_WEBP, false)) + items.push(loadAsset("manifest.json", CT_JSON, true)) + let s: StaticSet = {items: items, n: items.length as int} + return s +} + +let const STATIC: StaticSet = loadStatic() + +// Index of the asset whose name equals buf[start..end), or -1 if none. +local fn findAsset(buf: byte[], start: uint, end: uint) -> int { + if end < start { + return -1 + } + let want: uint = end - start + foreach i in 0, STATIC.n { + let nm = STATIC.items[i as uint].name + if nm.length == want { + let hit: bool = true + foreach k: uint in 0u, want { + if (buf[start + k] as int) != (nm[k] as int) { + hit = false + break + } + } + if hit { + return i + } + } + } + return -1 +} + +// Write all `len` bytes of the mutable buffer `b` to fd, shifting the unsent +// tail forward on a partial send. `b` is caller scratch — shifting is fine. +local fn sendBuf(fd: int, b: byte[], len: uint) -> bool { + let remaining: uint = len + while remaining > 0u { + let w = tcp_write(fd, b, remaining) + if w <= 0 { + return false + } + let n: uint = w as uint + if n >= remaining { + return true + } + let rest: uint = remaining - n + foreach k: uint in 0u, rest { + b[k] = b[n + k] + } + remaining = rest + } + return true +} + +// Send all `len` bytes of `src` without mutating it; a partial send is +// finished by copying the unsent tail through `scratch` (capacity `scap`). +local fn sendConst(fd: int, src: uint[], len: uint, scratch: byte[], scap: uint) -> bool { + let w = tcp_write(fd, src, len) + if w < 0 { + return false + } + let sent: uint = w as uint + while sent < len { + let rest: uint = len - sent + let chunk: uint = if rest > scap => scap else rest + foreach k: uint in 0u, chunk { + scratch[k] = src[sent + k] as byte + } + let w2 = tcp_write(fd, scratch, chunk) + if w2 <= 0 { + return false + } + sent = sent + (w2 as uint) + } + return true +} + +// Serve GET /static/. `scratch`/`scap` is the caller's output buffer, +// reused for header assembly and partial-send finishing. false on socket error. +fn serveStatic(fd: int, buf: byte[], pathStart: uint, pathEnd: uint, + acceptBr: bool, acceptGzip: bool, keepAlive: bool, + scratch: byte[], scap: uint) -> bool { + // request target is "/static/" — skip the 8-byte "/static/" prefix + let nameStart: uint = pathStart + 8u + let idx: int = if pathEnd > nameStart => findAsset(buf, nameStart, pathEnd) else -1 + if idx < 0 { + return sendConst(fd, S_NOT_FOUND, S_NOT_FOUND.length, scratch, scap) + } + + let a = STATIC.items[idx as uint] + + // pick the best available encoding: br > gzip > identity + let body: uint[] = a.raw + let useBr: bool = false + let useGz: bool = false + if acceptBr && a.br.length > 0u { + body = a.br + useBr = true + } else if acceptGzip && a.gz.length > 0u { + body = a.gz + useGz = true + } + let bodyLen: uint = body.length + + // assemble headers in the scratch buffer + let p: uint = writeBytes(scratch, 0u, S_STATUS_CT) + p = writeBytes(scratch, p, a.ctype) + if useBr { + p = writeBytes(scratch, p, S_ENC_BR) + } else if useGz { + p = writeBytes(scratch, p, S_ENC_GZIP) + } + p = writeBytes(scratch, p, S_CL) + p = writeInt(scratch, p, bodyLen as int) + if keepAlive { + p = writeBytes(scratch, p, S_CONN_KA) + } else { + p = writeBytes(scratch, p, S_CONN_CL) + } + + if !sendBuf(fd, scratch, p) { + return false + } + if bodyLen > 0u { + return sendConst(fd, body, bodyLen, scratch, scap) + } + return true +} diff --git a/frameworks/typev/bundle/benchmark-code/src/http.tc b/frameworks/typev/bundle/benchmark-code/src/http.tc index 6d9f30415..d0935bc42 100644 --- a/frameworks/typev/bundle/benchmark-code/src/http.tc +++ b/frameworks/typev/bundle/benchmark-code/src/http.tc @@ -8,11 +8,22 @@ type Req = struct { isPipeline: bool, isBaseline: bool, isJson: bool, + isStatic: bool, + isUpload: bool, isPost: bool, keepAlive: bool, result: int, jcount: int, - jmult: int + jmult: int, + pathStart: uint, + pathEnd: uint, + acceptBr: bool, + acceptGzip: bool, + contentLen: int, + bodyStart: uint, + isWs: bool, + wsKeyStart: uint, + wsKeyEnd: uint } // Result of decoding a chunked body. @@ -24,7 +35,7 @@ type Chunk = struct { // Allocate one Req / Chunk — a handler makes these once and reuses them. fn newReq() -> Req { - let r: Req = {complete: false, consumed: 0u, isPipeline: false, isBaseline: false, isJson: false, isPost: false, keepAlive: true, result: 0, jcount: 0, jmult: 0} + let r: Req = {complete: false, consumed: 0u, isPipeline: false, isBaseline: false, isJson: false, isStatic: false, isUpload: false, isPost: false, keepAlive: true, result: 0, jcount: 0, jmult: 0, pathStart: 0u, pathEnd: 0u, acceptBr: false, acceptGzip: false, contentLen: 0, bodyStart: 0u, isWs: false, wsKeyStart: 0u, wsKeyEnd: 0u} return r } @@ -39,6 +50,10 @@ let local const HDR_TRANSFER_ENCODING: byte[] = "transfer-encoding".bytes() let local const HDR_CONNECTION: byte[] = "connection".bytes() let local const VAL_CHUNKED: byte[] = "chunked".bytes() let local const VAL_CLOSE: byte[] = "close".bytes() +let local const HDR_ACCEPT_ENCODING: byte[] = "accept-encoding".bytes() +let local const VAL_BR: byte[] = "br".bytes() +let local const VAL_GZIP: byte[] = "gzip".bytes() +let local const HDR_WS_KEY: byte[] = "sec-websocket-key".bytes() // Parse a decimal integer from buf[start..end), ignoring non-digit bytes. local fn parseDigits(buf: byte[], start: uint, end: uint) -> int { @@ -185,11 +200,22 @@ fn parseRequest(buf: byte[], len: uint, mut r: Req, mut c: Chunk) -> void { r.isPipeline = false r.isBaseline = false r.isJson = false + r.isStatic = false + r.isUpload = false r.isPost = false r.keepAlive = true r.result = 0 r.jcount = 0 r.jmult = 0 + r.pathStart = 0u + r.pathEnd = 0u + r.acceptBr = false + r.acceptGzip = false + r.contentLen = 0 + r.bodyStart = 0u + r.isWs = false + r.wsKeyStart = 0u + r.wsKeyEnd = 0u if len < 4u { return } @@ -224,6 +250,17 @@ fn parseRequest(buf: byte[], len: uint, mut r: Req, mut c: Chunk) -> void { r.isPipeline = rc == 112 r.isBaseline = rc == 98 r.isJson = rc == 106 + r.isStatic = rc == 115 + r.isUpload = rc == 117 + r.isWs = rc == 119 + + // request target = buf[pathStart .. pathEnd) — up to the next space + let pathEnd: uint = pathStart + while pathEnd < he && (buf[pathEnd] as int) != 32 { + pathEnd = pathEnd + 1u + } + r.pathStart = pathStart + r.pathEnd = pathEnd // end of request line (first CR) let lineEnd: uint = pathStart @@ -250,10 +287,34 @@ fn parseRequest(buf: byte[], len: uint, mut r: Req, mut c: Chunk) -> void { if containsCI(buf, h, le, VAL_CLOSE) { r.keepAlive = false } + } else if matchHeader(buf, h, le, HDR_ACCEPT_ENCODING) { + if containsCI(buf, h, le, VAL_BR) { + r.acceptBr = true + } + if containsCI(buf, h, le, VAL_GZIP) { + r.acceptGzip = true + } + } else if matchHeader(buf, h, le, HDR_WS_KEY) { + let vs: uint = h + HDR_WS_KEY.length + 1u + while vs < le && (buf[vs] as int) == 32 { + vs = vs + 1u + } + r.wsKeyStart = vs + r.wsKeyEnd = le } h = le + 2u } + // upload: parsed headers are enough — handle_client streams the body + // (Content-Length framed; the benchmark never chunk-encodes uploads). + if r.isUpload { + r.complete = true + r.consumed = 0u + r.bodyStart = bodyStart + r.contentLen = contentLen + return + } + // body let bodyVal: int = 0 let consumed: uint = bodyStart diff --git a/frameworks/typev/bundle/benchmark-code/src/main.tc b/frameworks/typev/bundle/benchmark-code/src/main.tc index d36587c72..3be5cc06a 100644 --- a/frameworks/typev/bundle/benchmark-code/src/main.tc +++ b/frameworks/typev/bundle/benchmark-code/src/main.tc @@ -10,6 +10,8 @@ from std.socket import tcp_listen, tcp_accept, tcp_read, tcp_write, tcp_close from http import parseRequest, newReq, newChunk from response import writePipeline, writeBaseline, PIPE_BATCH, PIPE_BATCH_N, RESP_LEN from dataset import writeJson +from assets import serveStatic +from ws import wsHandshake, wsServe, wsReject // Per-connection receive / output buffer capacities. let const BUFCAP: uint = 65536u @@ -58,6 +60,43 @@ fn blastPipe(fd: int, scratch: byte[], total: uint) -> bool { return writeAll(fd, scratch, rest) } +// Stream-drain a Content-Length upload body: `cl` total body bytes, some of +// which already sit in buf[bodyStart..curLen). Reads the rest 64KB at a time +// (never buffering the whole body) and leaves any trailing next-request bytes +// at buf[0..]. Returns (leftover length, false on socket error). +fn drainUpload(fd: int, buf: byte[], bufcap: uint, bodyStart: uint, cl: uint, curLen: uint) -> (uint, bool) { + let inBuf: uint = curLen - bodyStart + if inBuf >= cl { + let tail: uint = inBuf - cl + foreach k: uint in 0u, tail { + buf[k] = buf[bodyStart + cl + k] + } + return (tail, true) + } + let need: uint = cl - inBuf + let tail: uint = 0u + let ok: bool = true + while need > 0u { + let got = tcp_read(fd, buf, bufcap) + if got <= 0 { + ok = false + need = 0u + } else { + let g: uint = got as uint + if g <= need { + need = need - g + } else { + tail = g - need + foreach k: uint in 0u, tail { + buf[k] = buf[need + k] + } + need = 0u + } + } + } + return (tail, ok) +} + // Serve one connection. fn handle_client(fd: int) -> void { let buf: byte[] = [] @@ -133,7 +172,51 @@ fn handle_client(fd: int) -> void { } opos = 0u } - if req.isJson { + if req.isStatic { + // static responses stream directly — flush any + // batched output first, then serve the asset + if opos > 0u { + if !writeAll(fd, obuf, opos) { + running = false + } + opos = 0u + } + if !serveStatic(fd, buf, req.pathStart, req.pathEnd, req.acceptBr, req.acceptGzip, req.keepAlive, obuf, OBUFCAP) { + running = false + parsing = false + } + } else if req.isUpload { + // stream-drain the body, then ack the byte count + let cl: uint = if req.contentLen > 0 => (req.contentLen as uint) else 0u + let (newLen, ok) = drainUpload(fd, buf, BUFCAP, req.bodyStart, cl, len) + len = newLen + if ok { + opos = writeBaseline(obuf, opos, cl as int, req.keepAlive) + } else { + running = false + parsing = false + } + } else if req.isWs { + // WebSocket: 101 handshake, then echo frames until + // the peer closes. wsServe owns the connection. + if opos > 0u { + if !writeAll(fd, obuf, opos) { + running = false + } + opos = 0u + } + if running { + if req.wsKeyEnd > req.wsKeyStart { + if wsHandshake(fd, buf, req.wsKeyStart, req.wsKeyEnd, obuf) { + wsServe(fd, buf, tmp, obuf, BUFCAP, OBUFCAP, req.consumed, len - req.consumed) + } + } else { + wsReject(fd, obuf) + } + } + running = false + parsing = false + } else if req.isJson { opos = writeJson(obuf, opos, req.jcount, req.jmult, req.keepAlive) } else if req.isBaseline { opos = writeBaseline(obuf, opos, req.result, req.keepAlive) diff --git a/frameworks/typev/bundle/benchmark-code/src/ws.tc b/frameworks/typev/bundle/benchmark-code/src/ws.tc new file mode 100644 index 000000000..65e00633d --- /dev/null +++ b/frameworks/typev/bundle/benchmark-code/src/ws.tc @@ -0,0 +1,354 @@ +// ws.tc — WebSocket echo for the HttpArena `echo-ws` / `echo-ws-pipeline` +// tests. Handles the RFC 6455 upgrade handshake (SHA-1 + base64) and a +// frame echo loop: read masked client frames, echo them unmasked. + +from std.socket import tcp_write, tcp_read +from response import writeBytes + +// Low 32 bits mask — SHA-1 is 32-bit arithmetic; typev `uint` is 64-bit. +let local const M32: uint = 4294967295u + +let local const B64: byte[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".bytes() +let local const WS_GUID: byte[] = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11".bytes() +let local const WS_101: byte[] = "HTTP/1.1 101 Switching Protocols\r\nUpgrade: websocket\r\nConnection: Upgrade\r\nSec-WebSocket-Accept: ".bytes() +let local const WS_CRLF2: byte[] = "\r\n\r\n".bytes() +let local const WS_BAD: byte[] = "HTTP/1.1 400 Bad Request\r\nContent-Length: 0\r\nConnection: close\r\n\r\n".bytes() + +// Write all `len` bytes of the mutable buffer `b` to fd; shift on a partial +// send (b is caller scratch — shifting is fine). false on socket error. +local fn wsSend(fd: int, b: byte[], len: uint) -> bool { + let remaining: uint = len + while remaining > 0u { + let w = tcp_write(fd, b, remaining) + if w <= 0 { + return false + } + let n: uint = w as uint + if n >= remaining { + return true + } + let rest: uint = remaining - n + foreach k: uint in 0u, rest { + b[k] = b[n + k] + } + remaining = rest + } + return true +} + +// 32-bit rotate-left. +local fn rotl32(x: uint, n: uint) -> uint { + return ((x << n) | (x >> (32u - n))) & M32 +} + +// SHA-1 of data[0..n) — returns the 20-byte digest. +local fn sha1(data: byte[], n: uint) -> byte[] { + let padded: uint = ((n + 8u) / 64u + 1u) * 64u + let msg: byte[] = new byte[](padded) + foreach i: uint in 0u, n { + msg[i] = data[i] + } + msg[n] = 128 as byte + foreach i: uint in n + 1u, padded { + msg[i] = 0 as byte + } + let bits: uint = n * 8u + foreach i: uint in 0u, 8u { + msg[padded - 1u - i] = ((bits >> (8u * i)) & 255u) as byte + } + + let h0: uint = 1732584193u + let h1: uint = 4023233417u + let h2: uint = 2562383102u + let h3: uint = 271733878u + let h4: uint = 3285377520u + let w: uint[] = new uint[](80) + let blocks: uint = padded / 64u + + foreach b: uint in 0u, blocks { + let base: uint = b * 64u + foreach t: uint in 0u, 16u { + let o: uint = base + t * 4u + w[t] = (((msg[o] as uint) << 24u) | ((msg[o + 1u] as uint) << 16u) + | ((msg[o + 2u] as uint) << 8u) | (msg[o + 3u] as uint)) & M32 + } + foreach t: uint in 16u, 80u { + w[t] = rotl32((w[t - 3u] ^ w[t - 8u] ^ w[t - 14u] ^ w[t - 16u]) & M32, 1u) + } + let a: uint = h0 + let bb: uint = h1 + let c: uint = h2 + let d: uint = h3 + let e: uint = h4 + foreach t: uint in 0u, 80u { + let f: uint = 0u + let k: uint = 0u + if t < 20u { + f = (bb & c) | ((M32 ^ bb) & d) + k = 1518500249u + } else if t < 40u { + f = bb ^ c ^ d + k = 1859775393u + } else if t < 60u { + f = (bb & c) | (bb & d) | (c & d) + k = 2400959708u + } else { + f = bb ^ c ^ d + k = 3395469782u + } + let tt: uint = (rotl32(a, 5u) + (f & M32) + e + k + w[t]) & M32 + e = d + d = c + c = rotl32(bb, 30u) + bb = a + a = tt + } + h0 = (h0 + a) & M32 + h1 = (h1 + bb) & M32 + h2 = (h2 + c) & M32 + h3 = (h3 + d) & M32 + h4 = (h4 + e) & M32 + } + + let digest: byte[] = new byte[](20) + let hs: uint[] = [h0, h1, h2, h3, h4] + foreach i: uint in 0u, 5u { + let v: uint = hs[i] + digest[i * 4u] = ((v >> 24u) & 255u) as byte + digest[i * 4u + 1u] = ((v >> 16u) & 255u) as byte + digest[i * 4u + 2u] = ((v >> 8u) & 255u) as byte + digest[i * 4u + 3u] = (v & 255u) as byte + } + return digest +} + +// Base64-encode data[0..n). +local fn b64encode(data: byte[], n: uint) -> byte[] { + let outLen: uint = ((n + 2u) / 3u) * 4u + let out: byte[] = new byte[](outLen) + let i: uint = 0u + let o: uint = 0u + while i + 3u <= n { + let x: uint = ((data[i] as uint) << 16u) | ((data[i + 1u] as uint) << 8u) | (data[i + 2u] as uint) + out[o] = B64[(x >> 18u) & 63u] + out[o + 1u] = B64[(x >> 12u) & 63u] + out[o + 2u] = B64[(x >> 6u) & 63u] + out[o + 3u] = B64[x & 63u] + i = i + 3u + o = o + 4u + } + let rem: uint = n - i + if rem == 1u { + let x: uint = (data[i] as uint) << 16u + out[o] = B64[(x >> 18u) & 63u] + out[o + 1u] = B64[(x >> 12u) & 63u] + out[o + 2u] = 61 as byte + out[o + 3u] = 61 as byte + } else if rem == 2u { + let x: uint = ((data[i] as uint) << 16u) | ((data[i + 1u] as uint) << 8u) + out[o] = B64[(x >> 18u) & 63u] + out[o + 1u] = B64[(x >> 12u) & 63u] + out[o + 2u] = B64[(x >> 6u) & 63u] + out[o + 3u] = 61 as byte + } + return out +} + +// Sec-WebSocket-Accept = base64(SHA1(key + GUID)). +local fn wsAccept(key: byte[], keyStart: uint, keyEnd: uint) -> byte[] { + let keyLen: uint = keyEnd - keyStart + let concat: byte[] = new byte[](keyLen + WS_GUID.length) + foreach i: uint in 0u, keyLen { + concat[i] = key[keyStart + i] + } + foreach i: uint in 0u, WS_GUID.length { + concat[keyLen + i] = WS_GUID[i] + } + let digest: byte[] = sha1(concat, concat.length) + return b64encode(digest, 20u) +} + +// Send the 101 upgrade response; `scratch` is the caller's output buffer. +fn wsHandshake(fd: int, buf: byte[], keyStart: uint, keyEnd: uint, scratch: byte[]) -> bool { + let accept: byte[] = wsAccept(buf, keyStart, keyEnd) + let p: uint = writeBytes(scratch, 0u, WS_101) + p = writeBytes(scratch, p, accept) + p = writeBytes(scratch, p, WS_CRLF2) + return wsSend(fd, scratch, p) +} + +// Reject a non-upgrade GET /ws with 400. +fn wsReject(fd: int, scratch: byte[]) -> void { + let p: uint = writeBytes(scratch, 0u, WS_BAD) + wsSend(fd, scratch, p) +} + +// One parsed WS frame; `ok` is false if buf doesn't yet hold a whole frame. +type WsFrame = struct { + ok: bool, + opcode: int, + masked: bool, + payloadOff: uint, + payloadLen: uint, + maskOff: uint, + frameLen: uint +} + +// Parse one frame from buf[0..len) into `f`. +local fn wsParseFrame(buf: byte[], len: uint, mut f: WsFrame) -> void { + f.ok = false + if len < 2u { + return + } + let b0: int = buf[0] as int + let b1: int = buf[1] as int + f.opcode = b0 & 15 + f.masked = (b1 & 128) != 0 + let len7: int = b1 & 127 + let hdr: uint = 2u + let plen: uint = len7 as uint + if len7 == 126 { + if len < 4u { + return + } + plen = ((buf[2] as uint) << 8u) | (buf[3] as uint) + hdr = 4u + } else if len7 == 127 { + if len < 10u { + return + } + plen = 0u + foreach i: uint in 0u, 8u { + plen = (plen << 8u) | (buf[2u + i] as uint) + } + hdr = 10u + } + f.maskOff = hdr + if f.masked { + hdr = hdr + 4u + } + f.payloadOff = hdr + f.payloadLen = plen + f.frameLen = hdr + plen + if len < f.frameLen { + return + } + f.ok = true +} + +// Build an unmasked server frame [FIN|opcode][len][payload] into dst at pos, +// the payload copied from src[srcOff..srcOff+plen). Returns the new position. +local fn wsBuildFrame(dst: byte[], pos: uint, opcode: int, src: byte[], srcOff: uint, plen: uint) -> uint { + let p: uint = pos + dst[p] = (128 | opcode) as byte + p = p + 1u + if plen < 126u { + dst[p] = plen as byte + p = p + 1u + } else if plen < 65536u { + dst[p] = 126 as byte + dst[p + 1u] = ((plen >> 8u) & 255u) as byte + dst[p + 2u] = (plen & 255u) as byte + p = p + 3u + } else { + dst[p] = 127 as byte + foreach i: uint in 0u, 8u { + dst[p + 1u + i] = ((plen >> (8u * (7u - i))) & 255u) as byte + } + p = p + 9u + } + foreach i: uint in 0u, plen { + dst[p + i] = src[srcOff + i] + } + return p + plen +} + +// WebSocket echo loop. Runs until the peer closes or a socket error. `loLen` +// bytes of already-received frame data sit at buf[loStart..loStart+loLen). +fn wsServe(fd: int, buf: byte[], tmp: byte[], obuf: byte[], bcap: uint, ocap: uint, loStart: uint, loLen: uint) -> void { + foreach k: uint in 0u, loLen { + buf[k] = buf[loStart + k] + } + let len: uint = loLen + let opos: uint = 0u + let running: bool = true + let f: WsFrame = {ok: false, opcode: 0, masked: false, payloadOff: 0u, payloadLen: 0u, maskOff: 0u, frameLen: 0u} + + while running { + // drain every complete frame currently buffered + let draining: bool = true + while draining { + wsParseFrame(buf, len, f) + if !f.ok { + draining = false + } else { + // unmask the payload in place + if f.masked { + foreach i: uint in 0u, f.payloadLen { + let mb: int = buf[f.maskOff + (i % 4u)] as int + let pb: int = buf[f.payloadOff + i] as int + buf[f.payloadOff + i] = ((pb ^ mb) & 255) as byte + } + } + let need: uint = f.payloadLen + 10u + if f.opcode == 8 { + // close — echo a close frame, then stop + if opos + need > ocap { + wsSend(fd, obuf, opos) + opos = 0u + } + if need <= ocap { + opos = wsBuildFrame(obuf, opos, 8, buf, f.payloadOff, f.payloadLen) + } + running = false + draining = false + } else if need > ocap { + // frame larger than the output buffer — give up + running = false + draining = false + } else { + let echoOp: int = if f.opcode == 9 => 10 else f.opcode + if opos + need > ocap { + if !wsSend(fd, obuf, opos) { + running = false + draining = false + } + opos = 0u + } + if running { + opos = wsBuildFrame(obuf, opos, echoOp, buf, f.payloadOff, f.payloadLen) + } + } + // drop the consumed frame + let rem: uint = len - f.frameLen + foreach k: uint in 0u, rem { + buf[k] = buf[f.frameLen + k] + } + len = rem + } + } + // flush echoes accumulated this pass before blocking on a read + if opos > 0u { + if !wsSend(fd, obuf, opos) { + running = false + } + opos = 0u + } + if running { + if len >= bcap { + running = false + } else { + let got: int = tcp_read(fd, tmp, bcap - len) + if got <= 0 { + running = false + } else { + let g: uint = got as uint + foreach k: uint in 0u, g { + buf[len + k] = tmp[k] + } + len = len + g + } + } + } + } +} diff --git a/frameworks/typev/bundle/output.tvbc b/frameworks/typev/bundle/output.tvbc index 768b58e93fbadec2a597f818bfe92b9fdf710ef6..baf128c9c1b178062f441bd06f06c265a09fccf6 100644 GIT binary patch literal 28673 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 diff --git a/frameworks/typev/meta.json b/frameworks/typev/meta.json index c8246896f..b91f4fc1c 100644 --- a/frameworks/typev/meta.json +++ b/frameworks/typev/meta.json @@ -10,7 +10,11 @@ "pipelined", "baseline", "limited-conn", - "json" + "json", + "static", + "upload", + "echo-ws", + "echo-ws-pipeline" ], "maintainers": ["praisethemoon"] } From 109f3425ac21bac329d57d127b3af4077dcd1aa8 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Mon, 18 May 2026 13:48:39 +0000 Subject: [PATCH 2/2] Benchmark results: typev --- site/data/baseline-4096.json | 16 +++++++-------- site/data/baseline-512.json | 16 +++++++-------- site/data/echo-ws-16384.json | 19 ++++++++++++++++++ site/data/echo-ws-4096.json | 19 ++++++++++++++++++ site/data/echo-ws-512.json | 19 ++++++++++++++++++ site/data/echo-ws-pipeline-16384.json | 19 ++++++++++++++++++ site/data/echo-ws-pipeline-4096.json | 19 ++++++++++++++++++ site/data/echo-ws-pipeline-512.json | 19 ++++++++++++++++++ site/data/json-4096.json | 18 ++++++++--------- site/data/limited-conn-4096.json | 18 ++++++++--------- site/data/limited-conn-512.json | 18 ++++++++--------- site/data/pipelined-4096.json | 14 ++++++------- site/data/pipelined-512.json | 14 ++++++------- site/data/static-1024.json | 19 ++++++++++++++++++ site/data/static-4096.json | 19 ++++++++++++++++++ site/data/static-6800.json | 19 ++++++++++++++++++ site/data/upload-256.json | 20 +++++++++++++++++++ site/data/upload-32.json | 20 +++++++++++++++++++ site/static/logs/baseline/4096/typev.log | 2 +- site/static/logs/baseline/512/typev.log | 2 +- .../logs/echo-ws-pipeline/16384/typev.log | 3 +++ .../logs/echo-ws-pipeline/4096/typev.log | 3 +++ .../logs/echo-ws-pipeline/512/typev.log | 3 +++ site/static/logs/echo-ws/16384/typev.log | 3 +++ site/static/logs/echo-ws/4096/typev.log | 3 +++ site/static/logs/echo-ws/512/typev.log | 3 +++ site/static/logs/json/4096/typev.log | 2 +- site/static/logs/limited-conn/4096/typev.log | 2 +- site/static/logs/limited-conn/512/typev.log | 2 +- site/static/logs/pipelined/4096/typev.log | 2 +- site/static/logs/pipelined/512/typev.log | 2 +- site/static/logs/static/1024/typev.log | 3 +++ site/static/logs/static/4096/typev.log | 3 +++ site/static/logs/static/6800/typev.log | 3 +++ site/static/logs/upload/256/typev.log | 3 +++ site/static/logs/upload/32/typev.log | 3 +++ 36 files changed, 308 insertions(+), 64 deletions(-) create mode 100644 site/static/logs/echo-ws-pipeline/16384/typev.log create mode 100644 site/static/logs/echo-ws-pipeline/4096/typev.log create mode 100644 site/static/logs/echo-ws-pipeline/512/typev.log create mode 100644 site/static/logs/echo-ws/16384/typev.log create mode 100644 site/static/logs/echo-ws/4096/typev.log create mode 100644 site/static/logs/echo-ws/512/typev.log create mode 100644 site/static/logs/static/1024/typev.log create mode 100644 site/static/logs/static/4096/typev.log create mode 100644 site/static/logs/static/6800/typev.log create mode 100644 site/static/logs/upload/256/typev.log create mode 100644 site/static/logs/upload/32/typev.log diff --git a/site/data/baseline-4096.json b/site/data/baseline-4096.json index a5a82d840..0a1ea0507 100644 --- a/site/data/baseline-4096.json +++ b/site/data/baseline-4096.json @@ -1248,19 +1248,19 @@ { "framework": "typev", "language": "Type-C", - "rps": 1918007, - "avg_latency": "199us", - "p99_latency": "1.20ms", - "cpu": "6737.7%", - "memory": "384MiB", + "rps": 1920429, + "avg_latency": "182us", + "p99_latency": "961us", + "cpu": "6204.2%", + "memory": "390MiB", "connections": 4096, "threads": 64, "duration": "5s", "pipeline": 1, - "bandwidth": "164.58MB/s", - "input_bw": "148.16MB/s", + "bandwidth": "164.75MB/s", + "input_bw": "148.35MB/s", "reconnects": 0, - "status_2xx": 9590035, + "status_2xx": 9602145, "status_3xx": 0, "status_4xx": 0, "status_5xx": 0 diff --git a/site/data/baseline-512.json b/site/data/baseline-512.json index b50732187..1632b88e8 100644 --- a/site/data/baseline-512.json +++ b/site/data/baseline-512.json @@ -1248,19 +1248,19 @@ { "framework": "typev", "language": "Type-C", - "rps": 1871533, - "avg_latency": "124us", - "p99_latency": "680us", - "cpu": "6498.3%", - "memory": "251MiB", + "rps": 1920320, + "avg_latency": "134us", + "p99_latency": "764us", + "cpu": "6506.2%", + "memory": "209MiB", "connections": 512, "threads": 64, "duration": "5s", "pipeline": 1, - "bandwidth": "160.59MB/s", - "input_bw": "144.57MB/s", + "bandwidth": "164.78MB/s", + "input_bw": "148.34MB/s", "reconnects": 0, - "status_2xx": 9357667, + "status_2xx": 9601602, "status_3xx": 0, "status_4xx": 0, "status_5xx": 0 diff --git a/site/data/echo-ws-16384.json b/site/data/echo-ws-16384.json index bae5a5762..18901f96d 100644 --- a/site/data/echo-ws-16384.json +++ b/site/data/echo-ws-16384.json @@ -366,6 +366,25 @@ "status_4xx": 0, "status_5xx": 0 }, + { + "framework": "typev", + "language": "Type-C", + "rps": 2916886, + "avg_latency": "181us", + "p99_latency": "1.47ms", + "cpu": "6178.8%", + "memory": "500MiB", + "connections": 16384, + "threads": 64, + "duration": "5s", + "pipeline": 1, + "bandwidth": "19.48MB/s", + "reconnects": 4384, + "status_2xx": 14584434, + "status_3xx": 0, + "status_4xx": 0, + "status_5xx": 0 + }, { "framework": "workerman-websocket", "language": "PHP", diff --git a/site/data/echo-ws-4096.json b/site/data/echo-ws-4096.json index 7ec2dd446..9cd8a76fd 100644 --- a/site/data/echo-ws-4096.json +++ b/site/data/echo-ws-4096.json @@ -366,6 +366,25 @@ "status_4xx": 0, "status_5xx": 0 }, + { + "framework": "typev", + "language": "Type-C", + "rps": 3032878, + "avg_latency": "180us", + "p99_latency": "794us", + "cpu": "6184.7%", + "memory": "454MiB", + "connections": 4096, + "threads": 64, + "duration": "5s", + "pipeline": 1, + "bandwidth": "20.24MB/s", + "reconnects": 0, + "status_2xx": 15164394, + "status_3xx": 0, + "status_4xx": 0, + "status_5xx": 0 + }, { "framework": "workerman-websocket", "language": "PHP", diff --git a/site/data/echo-ws-512.json b/site/data/echo-ws-512.json index 262b06e94..edbc7432d 100644 --- a/site/data/echo-ws-512.json +++ b/site/data/echo-ws-512.json @@ -366,6 +366,25 @@ "status_4xx": 0, "status_5xx": 0 }, + { + "framework": "typev", + "language": "Type-C", + "rps": 2870165, + "avg_latency": "103us", + "p99_latency": "347us", + "cpu": "6621.8%", + "memory": "270MiB", + "connections": 512, + "threads": 64, + "duration": "5s", + "pipeline": 1, + "bandwidth": "19.16MB/s", + "reconnects": 0, + "status_2xx": 14350827, + "status_3xx": 0, + "status_4xx": 0, + "status_5xx": 0 + }, { "framework": "workerman-websocket", "language": "PHP", diff --git a/site/data/echo-ws-pipeline-16384.json b/site/data/echo-ws-pipeline-16384.json index 71a6dee19..c25f010cd 100644 --- a/site/data/echo-ws-pipeline-16384.json +++ b/site/data/echo-ws-pipeline-16384.json @@ -226,5 +226,24 @@ "status_3xx": 0, "status_4xx": 0, "status_5xx": 0 + }, + { + "framework": "typev", + "language": "Type-C", + "rps": 19144384, + "avg_latency": "182us", + "p99_latency": "161us", + "cpu": "6222.4%", + "memory": "1.2GiB", + "connections": 16384, + "threads": 64, + "duration": "5s", + "pipeline": 16, + "bandwidth": "127.79MB/s", + "reconnects": 4093, + "status_2xx": 95721920, + "status_3xx": 0, + "status_4xx": 0, + "status_5xx": 0 } ] \ No newline at end of file diff --git a/site/data/echo-ws-pipeline-4096.json b/site/data/echo-ws-pipeline-4096.json index 62addc674..63462f94a 100644 --- a/site/data/echo-ws-pipeline-4096.json +++ b/site/data/echo-ws-pipeline-4096.json @@ -226,5 +226,24 @@ "status_3xx": 0, "status_4xx": 0, "status_5xx": 0 + }, + { + "framework": "typev", + "language": "Type-C", + "rps": 19144768, + "avg_latency": "202us", + "p99_latency": "573us", + "cpu": "6613.2%", + "memory": "428MiB", + "connections": 4096, + "threads": 64, + "duration": "5s", + "pipeline": 16, + "bandwidth": "127.77MB/s", + "reconnects": 0, + "status_2xx": 95723840, + "status_3xx": 0, + "status_4xx": 0, + "status_5xx": 0 } ] \ No newline at end of file diff --git a/site/data/echo-ws-pipeline-512.json b/site/data/echo-ws-pipeline-512.json index 1916a4e04..acd796999 100644 --- a/site/data/echo-ws-pipeline-512.json +++ b/site/data/echo-ws-pipeline-512.json @@ -226,5 +226,24 @@ "status_3xx": 0, "status_4xx": 0, "status_5xx": 0 + }, + { + "framework": "typev", + "language": "Type-C", + "rps": 18569209, + "avg_latency": "163us", + "p99_latency": "153us", + "cpu": "6477.0%", + "memory": "195MiB", + "connections": 512, + "threads": 64, + "duration": "5s", + "pipeline": 16, + "bandwidth": "123.93MB/s", + "reconnects": 0, + "status_2xx": 92846048, + "status_3xx": 0, + "status_4xx": 0, + "status_5xx": 0 } ] \ No newline at end of file diff --git a/site/data/json-4096.json b/site/data/json-4096.json index 3e0419d56..03c89b93f 100644 --- a/site/data/json-4096.json +++ b/site/data/json-4096.json @@ -996,19 +996,19 @@ { "framework": "typev", "language": "Type-C", - "rps": 1077677, - "avg_latency": "3.34ms", - "p99_latency": "1.36ms", - "cpu": "6730.8%", - "memory": "402MiB", + "rps": 1055884, + "avg_latency": "3.42ms", + "p99_latency": "2.89ms", + "cpu": "6719.4%", + "memory": "404MiB", "connections": 4096, "threads": 64, "duration": "5s", "pipeline": 1, - "bandwidth": "3.63GB/s", - "input_bw": "51.39MB/s", - "reconnects": 215192, - "status_2xx": 5388386, + "bandwidth": "3.56GB/s", + "input_bw": "50.35MB/s", + "reconnects": 211239, + "status_2xx": 5279420, "status_3xx": 0, "status_4xx": 0, "status_5xx": 0 diff --git a/site/data/limited-conn-4096.json b/site/data/limited-conn-4096.json index 57515ad90..8cf3d37fd 100644 --- a/site/data/limited-conn-4096.json +++ b/site/data/limited-conn-4096.json @@ -1248,19 +1248,19 @@ { "framework": "typev", "language": "Type-C", - "rps": 1282861, - "avg_latency": "3.13ms", - "p99_latency": "194.90ms", - "cpu": "6597.3%", - "memory": "304MiB", + "rps": 1299282, + "avg_latency": "3.09ms", + "p99_latency": "192.70ms", + "cpu": "6664.6%", + "memory": "354MiB", "connections": 4096, "threads": 64, "duration": "5s", "pipeline": 1, - "bandwidth": "110.08MB/s", - "input_bw": "99.10MB/s", - "reconnects": 641598, - "status_2xx": 6414306, + "bandwidth": "111.49MB/s", + "input_bw": "100.37MB/s", + "reconnects": 649635, + "status_2xx": 6496412, "status_3xx": 0, "status_4xx": 0, "status_5xx": 0 diff --git a/site/data/limited-conn-512.json b/site/data/limited-conn-512.json index d6e34bfea..280ec6434 100644 --- a/site/data/limited-conn-512.json +++ b/site/data/limited-conn-512.json @@ -1248,19 +1248,19 @@ { "framework": "typev", "language": "Type-C", - "rps": 912050, - "avg_latency": "552us", - "p99_latency": "20.10ms", - "cpu": "4779.8%", - "memory": "211MiB", + "rps": 881664, + "avg_latency": "571us", + "p99_latency": "20.40ms", + "cpu": "4727.6%", + "memory": "238MiB", "connections": 512, "threads": 64, "duration": "5s", "pipeline": 1, - "bandwidth": "78.26MB/s", - "input_bw": "70.45MB/s", - "reconnects": 456012, - "status_2xx": 4560254, + "bandwidth": "75.65MB/s", + "input_bw": "68.11MB/s", + "reconnects": 440820, + "status_2xx": 4408321, "status_3xx": 0, "status_4xx": 0, "status_5xx": 0 diff --git a/site/data/pipelined-4096.json b/site/data/pipelined-4096.json index ee44759cd..d44398474 100644 --- a/site/data/pipelined-4096.json +++ b/site/data/pipelined-4096.json @@ -1182,18 +1182,18 @@ { "framework": "typev", "language": "Type-C", - "rps": 48398726, - "avg_latency": "246us", - "p99_latency": "1.18ms", - "cpu": "6254.3%", - "memory": "355MiB", + "rps": 48124140, + "avg_latency": "260us", + "p99_latency": "1.19ms", + "cpu": "6140.7%", + "memory": "387MiB", "connections": 4096, "threads": 64, "duration": "5s", "pipeline": 16, - "bandwidth": "4.06GB/s", + "bandwidth": "4.03GB/s", "reconnects": 0, - "status_2xx": 241993632, + "status_2xx": 240620704, "status_3xx": 0, "status_4xx": 0, "status_5xx": 0 diff --git a/site/data/pipelined-512.json b/site/data/pipelined-512.json index 3da9a418d..60ce8f178 100644 --- a/site/data/pipelined-512.json +++ b/site/data/pipelined-512.json @@ -1182,18 +1182,18 @@ { "framework": "typev", "language": "Type-C", - "rps": 47930259, - "avg_latency": "169us", - "p99_latency": "981us", - "cpu": "6303.1%", - "memory": "276MiB", + "rps": 48515708, + "avg_latency": "167us", + "p99_latency": "959us", + "cpu": "6431.7%", + "memory": "296MiB", "connections": 512, "threads": 64, "duration": "5s", "pipeline": 16, - "bandwidth": "4.02GB/s", + "bandwidth": "4.07GB/s", "reconnects": 0, - "status_2xx": 239651296, + "status_2xx": 242578544, "status_3xx": 0, "status_4xx": 0, "status_5xx": 0 diff --git a/site/data/static-1024.json b/site/data/static-1024.json index 9740a800d..e09622497 100644 --- a/site/data/static-1024.json +++ b/site/data/static-1024.json @@ -1021,6 +1021,25 @@ "status_4xx": 0, "status_5xx": 0 }, + { + "framework": "typev", + "language": "Type-C", + "rps": 973340, + "avg_latency": "15.68ms", + "p99_latency": "15.68ms", + "cpu": "6476.6%", + "memory": "413MiB", + "connections": 1024, + "threads": 64, + "duration": "5s", + "pipeline": 1, + "bandwidth": "14.85GB", + "reconnects": 0, + "status_2xx": 4948245, + "status_3xx": 0, + "status_4xx": 0, + "status_5xx": 0 + }, { "framework": "userver", "language": "C++", diff --git a/site/data/static-4096.json b/site/data/static-4096.json index 08348c944..d52ea704d 100644 --- a/site/data/static-4096.json +++ b/site/data/static-4096.json @@ -1021,6 +1021,25 @@ "status_4xx": 0, "status_5xx": 0 }, + { + "framework": "typev", + "language": "Type-C", + "rps": 1071937, + "avg_latency": "21.09ms", + "p99_latency": "21.09ms", + "cpu": "6300.9%", + "memory": "595MiB", + "connections": 4096, + "threads": 64, + "duration": "5s", + "pipeline": 1, + "bandwidth": "16.35GB", + "reconnects": 0, + "status_2xx": 5466442, + "status_3xx": 0, + "status_4xx": 0, + "status_5xx": 0 + }, { "framework": "userver", "language": "C++", diff --git a/site/data/static-6800.json b/site/data/static-6800.json index c6cf78da4..35ccb20d2 100644 --- a/site/data/static-6800.json +++ b/site/data/static-6800.json @@ -1021,6 +1021,25 @@ "status_4xx": 0, "status_5xx": 0 }, + { + "framework": "typev", + "language": "Type-C", + "rps": 1072338, + "avg_latency": "11.49ms", + "p99_latency": "11.49ms", + "cpu": "6445.8%", + "memory": "1.3GiB", + "connections": 6800, + "threads": 64, + "duration": "5s", + "pipeline": 1, + "bandwidth": "16.36GB", + "reconnects": 0, + "status_2xx": 5468921, + "status_3xx": 0, + "status_4xx": 0, + "status_5xx": 0 + }, { "framework": "userver", "language": "C++", diff --git a/site/data/upload-256.json b/site/data/upload-256.json index 351952774..351fb0a07 100644 --- a/site/data/upload-256.json +++ b/site/data/upload-256.json @@ -918,6 +918,26 @@ "status_4xx": 0, "status_5xx": 0 }, + { + "framework": "typev", + "language": "Type-C", + "rps": 2999, + "avg_latency": "77.80ms", + "p99_latency": "220.30ms", + "cpu": "3858.7%", + "memory": "266MiB", + "connections": 256, + "threads": 64, + "duration": "5s", + "pipeline": 1, + "bandwidth": "279.19KB/s", + "input_bw": "23.79GB/s", + "reconnects": 2978, + "status_2xx": 15086, + "status_3xx": 0, + "status_4xx": 0, + "status_5xx": 0 + }, { "framework": "uvicorn", "language": "Python", diff --git a/site/data/upload-32.json b/site/data/upload-32.json index 132ddf6ec..cb11eeac7 100644 --- a/site/data/upload-32.json +++ b/site/data/upload-32.json @@ -918,6 +918,26 @@ "status_4xx": 0, "status_5xx": 0 }, + { + "framework": "typev", + "language": "Type-C", + "rps": 3084, + "avg_latency": "10.35ms", + "p99_latency": "31.00ms", + "cpu": "1933.4%", + "memory": "192MiB", + "connections": 32, + "threads": 64, + "duration": "5s", + "pipeline": 1, + "bandwidth": "286.69KB/s", + "input_bw": "24.46GB/s", + "reconnects": 3082, + "status_2xx": 15420, + "status_3xx": 0, + "status_4xx": 0, + "status_5xx": 0 + }, { "framework": "uvicorn", "language": "Python", diff --git a/site/static/logs/baseline/4096/typev.log b/site/static/logs/baseline/4096/typev.log index 9178c2f16..60a37c7c5 100644 --- a/site/static/logs/baseline/4096/typev.log +++ b/site/static/logs/baseline/4096/typev.log @@ -1,3 +1,3 @@ -typev: loaded '/app/output.tvbc' (v15, 30 functions, entry=29) +typev: loaded '/app/output.tvbc' (v15, 48 functions, entry=47) typev: workers=64 (sysconf _SC_NPROCESSORS_ONLN=128, TV_WORKERS=64) typev HttpArena server listening on :8080 diff --git a/site/static/logs/baseline/512/typev.log b/site/static/logs/baseline/512/typev.log index 9178c2f16..60a37c7c5 100644 --- a/site/static/logs/baseline/512/typev.log +++ b/site/static/logs/baseline/512/typev.log @@ -1,3 +1,3 @@ -typev: loaded '/app/output.tvbc' (v15, 30 functions, entry=29) +typev: loaded '/app/output.tvbc' (v15, 48 functions, entry=47) typev: workers=64 (sysconf _SC_NPROCESSORS_ONLN=128, TV_WORKERS=64) typev HttpArena server listening on :8080 diff --git a/site/static/logs/echo-ws-pipeline/16384/typev.log b/site/static/logs/echo-ws-pipeline/16384/typev.log new file mode 100644 index 000000000..60a37c7c5 --- /dev/null +++ b/site/static/logs/echo-ws-pipeline/16384/typev.log @@ -0,0 +1,3 @@ +typev: loaded '/app/output.tvbc' (v15, 48 functions, entry=47) +typev: workers=64 (sysconf _SC_NPROCESSORS_ONLN=128, TV_WORKERS=64) +typev HttpArena server listening on :8080 diff --git a/site/static/logs/echo-ws-pipeline/4096/typev.log b/site/static/logs/echo-ws-pipeline/4096/typev.log new file mode 100644 index 000000000..60a37c7c5 --- /dev/null +++ b/site/static/logs/echo-ws-pipeline/4096/typev.log @@ -0,0 +1,3 @@ +typev: loaded '/app/output.tvbc' (v15, 48 functions, entry=47) +typev: workers=64 (sysconf _SC_NPROCESSORS_ONLN=128, TV_WORKERS=64) +typev HttpArena server listening on :8080 diff --git a/site/static/logs/echo-ws-pipeline/512/typev.log b/site/static/logs/echo-ws-pipeline/512/typev.log new file mode 100644 index 000000000..60a37c7c5 --- /dev/null +++ b/site/static/logs/echo-ws-pipeline/512/typev.log @@ -0,0 +1,3 @@ +typev: loaded '/app/output.tvbc' (v15, 48 functions, entry=47) +typev: workers=64 (sysconf _SC_NPROCESSORS_ONLN=128, TV_WORKERS=64) +typev HttpArena server listening on :8080 diff --git a/site/static/logs/echo-ws/16384/typev.log b/site/static/logs/echo-ws/16384/typev.log new file mode 100644 index 000000000..60a37c7c5 --- /dev/null +++ b/site/static/logs/echo-ws/16384/typev.log @@ -0,0 +1,3 @@ +typev: loaded '/app/output.tvbc' (v15, 48 functions, entry=47) +typev: workers=64 (sysconf _SC_NPROCESSORS_ONLN=128, TV_WORKERS=64) +typev HttpArena server listening on :8080 diff --git a/site/static/logs/echo-ws/4096/typev.log b/site/static/logs/echo-ws/4096/typev.log new file mode 100644 index 000000000..60a37c7c5 --- /dev/null +++ b/site/static/logs/echo-ws/4096/typev.log @@ -0,0 +1,3 @@ +typev: loaded '/app/output.tvbc' (v15, 48 functions, entry=47) +typev: workers=64 (sysconf _SC_NPROCESSORS_ONLN=128, TV_WORKERS=64) +typev HttpArena server listening on :8080 diff --git a/site/static/logs/echo-ws/512/typev.log b/site/static/logs/echo-ws/512/typev.log new file mode 100644 index 000000000..60a37c7c5 --- /dev/null +++ b/site/static/logs/echo-ws/512/typev.log @@ -0,0 +1,3 @@ +typev: loaded '/app/output.tvbc' (v15, 48 functions, entry=47) +typev: workers=64 (sysconf _SC_NPROCESSORS_ONLN=128, TV_WORKERS=64) +typev HttpArena server listening on :8080 diff --git a/site/static/logs/json/4096/typev.log b/site/static/logs/json/4096/typev.log index 9178c2f16..60a37c7c5 100644 --- a/site/static/logs/json/4096/typev.log +++ b/site/static/logs/json/4096/typev.log @@ -1,3 +1,3 @@ -typev: loaded '/app/output.tvbc' (v15, 30 functions, entry=29) +typev: loaded '/app/output.tvbc' (v15, 48 functions, entry=47) typev: workers=64 (sysconf _SC_NPROCESSORS_ONLN=128, TV_WORKERS=64) typev HttpArena server listening on :8080 diff --git a/site/static/logs/limited-conn/4096/typev.log b/site/static/logs/limited-conn/4096/typev.log index 9178c2f16..60a37c7c5 100644 --- a/site/static/logs/limited-conn/4096/typev.log +++ b/site/static/logs/limited-conn/4096/typev.log @@ -1,3 +1,3 @@ -typev: loaded '/app/output.tvbc' (v15, 30 functions, entry=29) +typev: loaded '/app/output.tvbc' (v15, 48 functions, entry=47) typev: workers=64 (sysconf _SC_NPROCESSORS_ONLN=128, TV_WORKERS=64) typev HttpArena server listening on :8080 diff --git a/site/static/logs/limited-conn/512/typev.log b/site/static/logs/limited-conn/512/typev.log index 9178c2f16..60a37c7c5 100644 --- a/site/static/logs/limited-conn/512/typev.log +++ b/site/static/logs/limited-conn/512/typev.log @@ -1,3 +1,3 @@ -typev: loaded '/app/output.tvbc' (v15, 30 functions, entry=29) +typev: loaded '/app/output.tvbc' (v15, 48 functions, entry=47) typev: workers=64 (sysconf _SC_NPROCESSORS_ONLN=128, TV_WORKERS=64) typev HttpArena server listening on :8080 diff --git a/site/static/logs/pipelined/4096/typev.log b/site/static/logs/pipelined/4096/typev.log index 9178c2f16..60a37c7c5 100644 --- a/site/static/logs/pipelined/4096/typev.log +++ b/site/static/logs/pipelined/4096/typev.log @@ -1,3 +1,3 @@ -typev: loaded '/app/output.tvbc' (v15, 30 functions, entry=29) +typev: loaded '/app/output.tvbc' (v15, 48 functions, entry=47) typev: workers=64 (sysconf _SC_NPROCESSORS_ONLN=128, TV_WORKERS=64) typev HttpArena server listening on :8080 diff --git a/site/static/logs/pipelined/512/typev.log b/site/static/logs/pipelined/512/typev.log index 9178c2f16..60a37c7c5 100644 --- a/site/static/logs/pipelined/512/typev.log +++ b/site/static/logs/pipelined/512/typev.log @@ -1,3 +1,3 @@ -typev: loaded '/app/output.tvbc' (v15, 30 functions, entry=29) +typev: loaded '/app/output.tvbc' (v15, 48 functions, entry=47) typev: workers=64 (sysconf _SC_NPROCESSORS_ONLN=128, TV_WORKERS=64) typev HttpArena server listening on :8080 diff --git a/site/static/logs/static/1024/typev.log b/site/static/logs/static/1024/typev.log new file mode 100644 index 000000000..60a37c7c5 --- /dev/null +++ b/site/static/logs/static/1024/typev.log @@ -0,0 +1,3 @@ +typev: loaded '/app/output.tvbc' (v15, 48 functions, entry=47) +typev: workers=64 (sysconf _SC_NPROCESSORS_ONLN=128, TV_WORKERS=64) +typev HttpArena server listening on :8080 diff --git a/site/static/logs/static/4096/typev.log b/site/static/logs/static/4096/typev.log new file mode 100644 index 000000000..60a37c7c5 --- /dev/null +++ b/site/static/logs/static/4096/typev.log @@ -0,0 +1,3 @@ +typev: loaded '/app/output.tvbc' (v15, 48 functions, entry=47) +typev: workers=64 (sysconf _SC_NPROCESSORS_ONLN=128, TV_WORKERS=64) +typev HttpArena server listening on :8080 diff --git a/site/static/logs/static/6800/typev.log b/site/static/logs/static/6800/typev.log new file mode 100644 index 000000000..60a37c7c5 --- /dev/null +++ b/site/static/logs/static/6800/typev.log @@ -0,0 +1,3 @@ +typev: loaded '/app/output.tvbc' (v15, 48 functions, entry=47) +typev: workers=64 (sysconf _SC_NPROCESSORS_ONLN=128, TV_WORKERS=64) +typev HttpArena server listening on :8080 diff --git a/site/static/logs/upload/256/typev.log b/site/static/logs/upload/256/typev.log new file mode 100644 index 000000000..60a37c7c5 --- /dev/null +++ b/site/static/logs/upload/256/typev.log @@ -0,0 +1,3 @@ +typev: loaded '/app/output.tvbc' (v15, 48 functions, entry=47) +typev: workers=64 (sysconf _SC_NPROCESSORS_ONLN=128, TV_WORKERS=64) +typev HttpArena server listening on :8080 diff --git a/site/static/logs/upload/32/typev.log b/site/static/logs/upload/32/typev.log new file mode 100644 index 000000000..60a37c7c5 --- /dev/null +++ b/site/static/logs/upload/32/typev.log @@ -0,0 +1,3 @@ +typev: loaded '/app/output.tvbc' (v15, 48 functions, entry=47) +typev: workers=64 (sysconf _SC_NPROCESSORS_ONLN=128, TV_WORKERS=64) +typev HttpArena server listening on :8080