Skip to content

[C] Add ringzero-ws - WebSocket#815

Merged
MDA2AV merged 2 commits into
mainfrom
add-ringzero-ws
Jun 6, 2026
Merged

[C] Add ringzero-ws - WebSocket#815
MDA2AV merged 2 commits into
mainfrom
add-ringzero-ws

Conversation

@MDA2AV
Copy link
Copy Markdown
Owner

@MDA2AV MDA2AV commented Jun 6, 2026

Description

A WebSocket echo server written directly on raw io_uring (liburing), with the WebSocket protocol hand-rolled — no tokio-tungstenite, no library WS stack. It's the io_uring sibling of the ringzero HTTP engine.

Added as an engine-tier entry: the lowest-level way to serve echo-ws on the modern Linux completion-based I/O path.

The "ring-zero" I/O path

  • One io_uring per core, each with its own SO_REUSEPORT listener — kernel-sharded accept, no shared queue, no cross-core work-stealing.
  • Multishot accept — one SQE yields every new connection.
  • Multishot recv + provided buffer ring — the kernel writes incoming bytes straight into a registered slab (io_uring_setup_buf_ring); frames are parsed in place and the buffer is recycled immediately (zero-copy ingest).
  • IORING_SETUP_SINGLE_ISSUER | DEFER_TASKRUN for the single-thread-per-ring fast path (with a fallback for older kernels). Echoes are batched into a per-connection write queue; the in-flight chunk is sealed so the kernel never sees a reallocated buffer.

Hand-rolled WebSocket

  • RFC 6455 handshake — request parsing, Sec-WebSocket-Accept derivation, 101 reply, with from-scratch SHA-1 + base64. liburing is the only dependency.
  • Frame codec — 7/16/64-bit lengths, client→server unmasking, partial frames carried across reads. Echoes re-emitted as unmasked server frames preserving FIN + opcode. PingPong, Close echoed.

Tests

Subscribes to echo-ws and echo-ws-pipeline. Passes validate-ws.py (7/7), plus 200 KB-frame (multi-buffer reassembly), 2,000-frame pipelined, and 50-connection concurrent stress tests via the Docker build.

🤖 Generated with Claude Code

Hand-rolled WebSocket echo server on raw io_uring (liburing), with no
WebSocket library. Multishot accept + multishot recv into a provided
buffer ring give zero-copy ingest; the RFC 6455 handshake (with
from-scratch SHA-1 + base64), frame parser/masking, and batched echo
write path are implemented directly against io_uring completions. One
ring per core with SO_REUSEPORT, matching the ringzero engine.

Subscribes to echo-ws and echo-ws-pipeline. Passes validate-ws.py (7/7)
plus large-frame / pipelined / concurrent stress tests via the Docker
build.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@MDA2AV
Copy link
Copy Markdown
Owner Author

MDA2AV commented Jun 6, 2026

/benchmark -f ringzero-ws

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Jun 6, 2026

👋 /benchmark request received. A collaborator will review and approve the run.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Jun 6, 2026

Benchmark Results

Framework: ringzero-ws | Test: all tests

Test Conn RPS CPU Mem Δ RPS Δ Mem
echo-ws 512 4,360,772 6143.2% 211MiB NEW NEW
echo-ws 4096 4,481,908 6181.8% 230MiB NEW NEW
echo-ws 16384 4,123,360 6405.9% 337MiB NEW NEW
echo-ws-pipeline 512 66,785,414 6294.6% 207MiB NEW NEW
echo-ws-pipeline 4096 68,784,556 6408.1% 232MiB NEW NEW
echo-ws-pipeline 16384 61,210,198 6399.0% 336MiB NEW NEW
Full log
  Thread Stats   Avg      p50      p90      p99    p99.9
    Latency    122us    117us    176us    220us    257us

  333805776 frames sent in 5.00s, 333927072 frames received
  Throughput: 66.75M req/s
  Bandwidth:  445.42MB/s
  WS upgrades: 512
  WS frames:   333927072
  Latency samples: 333852573 / 333927072 responses (100.0%)
[info] CPU 6294.6% | Mem 207MiB

[run 3/3]
gcannon v0.5.3 [WS]
  Target:    localhost:8080/ws
  Threads:   64
  Conns:     512 (8/thread)
  Pipeline:  16
  Req/conn:  unlimited (keep-alive)
  Expected:  200
  Duration:  5s


  Thread Stats   Avg      p50      p90      p99    p99.9
    Latency    122us    118us    173us    225us    273us

  332576368 frames sent in 5.00s, 332576368 frames received
  Throughput: 66.50M req/s
  Bandwidth:  443.91MB/s
  WS upgrades: 512
  WS frames:   332576368
  Latency samples: 332574832 / 332576368 responses (100.0%)
[info] CPU 6246.1% | Mem 202MiB

=== Best: 66785414 req/s (CPU: 6294.6%, Mem: 207MiB) ===
[info] saved results/echo-ws-pipeline/512/ringzero-ws.json
httparena-bench-ringzero-ws
httparena-bench-ringzero-ws

==============================================
=== ringzero-ws / echo-ws-pipeline / 4096c (tool=gcannon) ===
==============================================
[info] ws-only framework — skipping HTTP probe (sleep 2s for startup)

[run 1/3]
gcannon v0.5.3 [WS]
  Target:    localhost:8080/ws
  Threads:   64
  Conns:     4096 (64/thread)
  Pipeline:  16
  Req/conn:  unlimited (keep-alive)
  Expected:  200
  Duration:  5s


  Thread Stats   Avg      p50      p90      p99    p99.9
    Latency    944us    891us   1.18ms   1.30ms   1.49ms

  343834384 frames sent in 5.00s, 343771920 frames received
  Throughput: 68.73M req/s
  Bandwidth:  458.92MB/s
  WS upgrades: 4096
  WS frames:   343771920
  Latency samples: 343771920 / 343771920 responses (100.0%)
[info] CPU 6100.5% | Mem 230MiB

[run 2/3]
gcannon v0.5.3 [WS]
  Target:    localhost:8080/ws
  Threads:   64
  Conns:     4096 (64/thread)
  Pipeline:  16
  Req/conn:  unlimited (keep-alive)
  Expected:  200
  Duration:  5s


  Thread Stats   Avg      p50      p90      p99    p99.9
    Latency    951us    896us   1.18ms   1.33ms   1.48ms

  343953520 frames sent in 5.00s, 343922784 frames received
  Throughput: 68.76M req/s
  Bandwidth:  459.10MB/s
  WS upgrades: 4096
  WS frames:   343922784
  Latency samples: 343920288 / 343922784 responses (100.0%)
[info] CPU 6408.1% | Mem 232MiB

[run 3/3]
gcannon v0.5.3 [WS]
  Target:    localhost:8080/ws
  Threads:   64
  Conns:     4096 (64/thread)
  Pipeline:  16
  Req/conn:  unlimited (keep-alive)
  Expected:  200
  Duration:  5s


  Thread Stats   Avg      p50      p90      p99    p99.9
    Latency    963us    955us   1.17ms   1.31ms   1.44ms

  339809088 frames sent in 5.00s, 339808912 frames received
  Throughput: 67.94M req/s
  Bandwidth:  453.54MB/s
  WS upgrades: 4096
  WS frames:   339808912
  Latency samples: 339859056 / 339808912 responses (100.0%)
[info] CPU 6246.4% | Mem 231MiB

=== Best: 68784556 req/s (CPU: 6408.1%, Mem: 232MiB) ===
[info] saved results/echo-ws-pipeline/4096/ringzero-ws.json
httparena-bench-ringzero-ws
httparena-bench-ringzero-ws

==============================================
=== ringzero-ws / echo-ws-pipeline / 16384c (tool=gcannon) ===
==============================================
[info] ws-only framework — skipping HTTP probe (sleep 2s for startup)

[run 1/3]
gcannon v0.5.3 [WS]
  Target:    localhost:8080/ws
  Threads:   64
  Conns:     16384 (256/thread)
  Pipeline:  16
  Req/conn:  unlimited (keep-alive)
  Expected:  200
  Duration:  5s


  Thread Stats   Avg      p50      p90      p99    p99.9
    Latency   4.30ms   4.33ms   4.73ms   5.10ms   10.00ms

  298734448 frames sent in 5.00s, 298475520 frames received
  Throughput: 59.68M req/s
  Bandwidth:  398.79MB/s
  WS upgrades: 16384
  WS frames:   298475520
  Latency samples: 298475520 / 298475520 responses (100.0%)
[info] CPU 5989.3% | Mem 337MiB

[run 2/3]
gcannon v0.5.3 [WS]
  Target:    localhost:8080/ws
  Threads:   64
  Conns:     16384 (256/thread)
  Pipeline:  16
  Req/conn:  unlimited (keep-alive)
  Expected:  200
  Duration:  5s


  Thread Stats   Avg      p50      p90      p99    p99.9
    Latency   4.27ms   4.32ms   4.69ms   5.19ms   7.69ms

  306313136 frames sent in 5.00s, 306050992 frames received
  Throughput: 61.18M req/s
  Bandwidth:  408.85MB/s
  WS upgrades: 16384
  WS frames:   306050992
  Latency samples: 306050992 / 306050992 responses (100.0%)
[info] CPU 6399.0% | Mem 336MiB

[run 3/3]
gcannon v0.5.3 [WS]
  Target:    localhost:8080/ws
  Threads:   64
  Conns:     16384 (256/thread)
  Pipeline:  16
  Req/conn:  unlimited (keep-alive)
  Expected:  200
  Duration:  5s


  Thread Stats   Avg      p50      p90      p99    p99.9
    Latency   4.28ms   4.31ms   4.71ms   5.33ms   7.64ms

  304985024 frames sent in 5.00s, 304726976 frames received
  Throughput: 60.92M req/s
  Bandwidth:  407.07MB/s
  WS upgrades: 16384
  WS frames:   304726976
  Latency samples: 304726976 / 304726976 responses (100.0%)
[info] CPU 6147.6% | Mem 336MiB

=== Best: 61210198 req/s (CPU: 6399.0%, Mem: 336MiB) ===
[info] saved results/echo-ws-pipeline/16384/ringzero-ws.json
httparena-bench-ringzero-ws
httparena-bench-ringzero-ws
[info] rebuilding site/data/*.json
[updated] /home/diogo/actions-runner/_work/HttpArena/HttpArena/site/data/frameworks.json
[updated] /home/diogo/actions-runner/_work/HttpArena/HttpArena/site/data/echo-ws-16384.json
[updated] /home/diogo/actions-runner/_work/HttpArena/HttpArena/site/data/echo-ws-4096.json
[updated] /home/diogo/actions-runner/_work/HttpArena/HttpArena/site/data/echo-ws-512.json
[updated] /home/diogo/actions-runner/_work/HttpArena/HttpArena/site/data/echo-ws-pipeline-16384.json
[updated] /home/diogo/actions-runner/_work/HttpArena/HttpArena/site/data/echo-ws-pipeline-4096.json
[updated] /home/diogo/actions-runner/_work/HttpArena/HttpArena/site/data/echo-ws-pipeline-512.json
[updated] /home/diogo/actions-runner/_work/HttpArena/HttpArena/site/data/current.json
[info] done
[info] restoring loopback MTU to 65536

@MDA2AV
Copy link
Copy Markdown
Owner Author

MDA2AV commented Jun 6, 2026

/benchmark -f ringzero-ws --save

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Jun 6, 2026

👋 /benchmark request received. A collaborator will review and approve the run.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Jun 6, 2026

Benchmark Results

Framework: ringzero-ws | Test: all tests

Test Conn RPS CPU Mem Δ RPS Δ Mem
echo-ws 512 4,353,147 6200.6% 210MiB NEW NEW
echo-ws 4096 4,429,548 6408.1% 231MiB NEW NEW
echo-ws 16384 4,066,852 6398.4% 336MiB NEW NEW
echo-ws-pipeline 512 66,683,702 6289.2% 203MiB NEW NEW
echo-ws-pipeline 4096 68,438,198 6160.2% 228MiB NEW NEW
echo-ws-pipeline 16384 61,261,692 6136.3% 337MiB NEW NEW
Full log
  Thread Stats   Avg      p50      p90      p99    p99.9
    Latency    123us    118us    177us    224us    294us

  330936768 frames sent in 5.00s, 330974784 frames received
  Throughput: 66.17M req/s
  Bandwidth:  441.71MB/s
  WS upgrades: 512
  WS frames:   330974784
  Latency samples: 331043631 / 330974784 responses (100.0%)
[info] CPU 6284.1% | Mem 208MiB

[run 3/3]
gcannon v0.5.3 [WS]
  Target:    localhost:8080/ws
  Threads:   64
  Conns:     512 (8/thread)
  Pipeline:  16
  Req/conn:  unlimited (keep-alive)
  Expected:  200
  Duration:  5s


  Thread Stats   Avg      p50      p90      p99    p99.9
    Latency    122us    118us    173us    218us    253us

  333369664 frames sent in 5.00s, 333418511 frames received
  Throughput: 66.66M req/s
  Bandwidth:  444.97MB/s
  WS upgrades: 512
  WS frames:   333418511
  Latency samples: 333368045 / 333418511 responses (100.0%)
[info] CPU 6289.2% | Mem 203MiB

=== Best: 66683702 req/s (CPU: 6289.2%, Mem: 203MiB) ===
[info] saved results/echo-ws-pipeline/512/ringzero-ws.json
httparena-bench-ringzero-ws
httparena-bench-ringzero-ws

==============================================
=== ringzero-ws / echo-ws-pipeline / 4096c (tool=gcannon) ===
==============================================
[info] ws-only framework — skipping HTTP probe (sleep 2s for startup)

[run 1/3]
gcannon v0.5.3 [WS]
  Target:    localhost:8080/ws
  Threads:   64
  Conns:     4096 (64/thread)
  Pipeline:  16
  Req/conn:  unlimited (keep-alive)
  Expected:  200
  Duration:  5s


  Thread Stats   Avg      p50      p90      p99    p99.9
    Latency    954us    899us   1.19ms   1.42ms   1.52ms

  342253456 frames sent in 5.00s, 342190992 frames received
  Throughput: 68.42M req/s
  Bandwidth:  456.82MB/s
  WS upgrades: 4096
  WS frames:   342190992
  Latency samples: 342190992 / 342190992 responses (100.0%)
[info] CPU 6160.2% | Mem 228MiB

[run 2/3]
gcannon v0.5.3 [WS]
  Target:    localhost:8080/ws
  Threads:   64
  Conns:     4096 (64/thread)
  Pipeline:  16
  Req/conn:  unlimited (keep-alive)
  Expected:  200
  Duration:  5s


  Thread Stats   Avg      p50      p90      p99    p99.9
    Latency    958us    908us   1.19ms   1.38ms   1.50ms

  341772192 frames sent in 5.00s, 341772176 frames received
  Throughput: 68.33M req/s
  Bandwidth:  456.13MB/s
  WS upgrades: 4096
  WS frames:   341772176
  Latency samples: 341798352 / 341772176 responses (100.0%)
[info] CPU 6395.0% | Mem 230MiB

[run 3/3]
gcannon v0.5.3 [WS]
  Target:    localhost:8080/ws
  Threads:   64
  Conns:     4096 (64/thread)
  Pipeline:  16
  Req/conn:  unlimited (keep-alive)
  Expected:  200
  Duration:  5s


  Thread Stats   Avg      p50      p90      p99    p99.9
    Latency    957us    911us   1.17ms   1.31ms   1.47ms

  341946544 frames sent in 5.00s, 341944480 frames received
  Throughput: 68.36M req/s
  Bandwidth:  456.37MB/s
  WS upgrades: 4096
  WS frames:   341944480
  Latency samples: 341943424 / 341944480 responses (100.0%)
[info] CPU 6219.4% | Mem 231MiB

=== Best: 68438198 req/s (CPU: 6160.2%, Mem: 228MiB) ===
[info] saved results/echo-ws-pipeline/4096/ringzero-ws.json
httparena-bench-ringzero-ws
httparena-bench-ringzero-ws

==============================================
=== ringzero-ws / echo-ws-pipeline / 16384c (tool=gcannon) ===
==============================================
[info] ws-only framework — skipping HTTP probe (sleep 2s for startup)

[run 1/3]
gcannon v0.5.3 [WS]
  Target:    localhost:8080/ws
  Threads:   64
  Conns:     16384 (256/thread)
  Pipeline:  16
  Req/conn:  unlimited (keep-alive)
  Expected:  200
  Duration:  5s


  Thread Stats   Avg      p50      p90      p99    p99.9
    Latency   4.30ms   4.34ms   4.72ms   5.09ms   5.95ms

  297993056 frames sent in 5.00s, 297730912 frames received
  Throughput: 59.52M req/s
  Bandwidth:  397.75MB/s
  WS upgrades: 16384
  WS frames:   297730912
  Latency samples: 297730912 / 297730912 responses (100.0%)
[info] CPU 5979.2% | Mem 337MiB

[run 2/3]
gcannon v0.5.3 [WS]
  Target:    localhost:8080/ws
  Threads:   64
  Conns:     16384 (256/thread)
  Pipeline:  16
  Req/conn:  unlimited (keep-alive)
  Expected:  200
  Duration:  5s


  Thread Stats   Avg      p50      p90      p99    p99.9
    Latency   4.26ms   4.31ms   4.68ms   5.06ms   7.53ms

  306212352 frames sent in 5.00s, 305950208 frames received
  Throughput: 61.16M req/s
  Bandwidth:  408.72MB/s
  WS upgrades: 16384
  WS frames:   305950208
  Latency samples: 305950208 / 305950208 responses (100.0%)
[info] CPU 6400.2% | Mem 337MiB

[run 3/3]
gcannon v0.5.3 [WS]
  Target:    localhost:8080/ws
  Threads:   64
  Conns:     16384 (256/thread)
  Pipeline:  16
  Req/conn:  unlimited (keep-alive)
  Expected:  200
  Duration:  5s


  Thread Stats   Avg      p50      p90      p99    p99.9
    Latency   4.25ms   4.28ms   4.67ms   5.06ms   10.50ms

  306566512 frames sent in 5.00s, 306308464 frames received
  Throughput: 61.23M req/s
  Bandwidth:  409.18MB/s
  WS upgrades: 16384
  WS frames:   306308464
  Latency samples: 306308464 / 306308464 responses (100.0%)
[info] CPU 6136.3% | Mem 337MiB

=== Best: 61261692 req/s (CPU: 6136.3%, Mem: 337MiB) ===
[info] saved results/echo-ws-pipeline/16384/ringzero-ws.json
httparena-bench-ringzero-ws
httparena-bench-ringzero-ws
[info] rebuilding site/data/*.json
[updated] /home/diogo/actions-runner/_work/HttpArena/HttpArena/site/data/frameworks.json
[updated] /home/diogo/actions-runner/_work/HttpArena/HttpArena/site/data/echo-ws-16384.json
[updated] /home/diogo/actions-runner/_work/HttpArena/HttpArena/site/data/echo-ws-4096.json
[updated] /home/diogo/actions-runner/_work/HttpArena/HttpArena/site/data/echo-ws-512.json
[updated] /home/diogo/actions-runner/_work/HttpArena/HttpArena/site/data/echo-ws-pipeline-16384.json
[updated] /home/diogo/actions-runner/_work/HttpArena/HttpArena/site/data/echo-ws-pipeline-4096.json
[updated] /home/diogo/actions-runner/_work/HttpArena/HttpArena/site/data/echo-ws-pipeline-512.json
[updated] /home/diogo/actions-runner/_work/HttpArena/HttpArena/site/data/current.json
[info] done
[info] restoring loopback MTU to 65536

@MDA2AV MDA2AV merged commit 5a3f45a into main Jun 6, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant