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 00000000..253b5b4b --- /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 6d9f3041..d0935bc4 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 d36587c7..3be5cc06 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 00000000..65e00633 --- /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 768b58e9..baf128c9 100644 Binary files a/frameworks/typev/bundle/output.tvbc and b/frameworks/typev/bundle/output.tvbc differ diff --git a/frameworks/typev/meta.json b/frameworks/typev/meta.json index c8246896..b91f4fc1 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"] } diff --git a/site/data/baseline-4096.json b/site/data/baseline-4096.json index a5a82d84..0a1ea050 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 b5073218..1632b88e 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 bae5a576..18901f96 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 7ec2dd44..9cd8a76f 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 262b06e9..edbc7432 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 71a6dee1..c25f010c 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 62addc67..63462f94 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 1916a4e0..acd79699 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 3e0419d5..03c89b93 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 57515ad9..8cf3d37f 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 d6e34bfe..280ec643 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 ee44759c..d4439847 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 3da9a418..60ce8f17 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 9740a800..e0962249 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 08348c94..d52ea704 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 c6cf78da..35ccb20d 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 35195277..351fb0a0 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 132ddf6e..cb11eeac 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 9178c2f1..60a37c7c 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 9178c2f1..60a37c7c 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 00000000..60a37c7c --- /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 00000000..60a37c7c --- /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 00000000..60a37c7c --- /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 00000000..60a37c7c --- /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 00000000..60a37c7c --- /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 00000000..60a37c7c --- /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 9178c2f1..60a37c7c 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 9178c2f1..60a37c7c 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 9178c2f1..60a37c7c 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 9178c2f1..60a37c7c 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 9178c2f1..60a37c7c 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 00000000..60a37c7c --- /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 00000000..60a37c7c --- /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 00000000..60a37c7c --- /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 00000000..60a37c7c --- /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 00000000..60a37c7c --- /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