πOverview
powpow is a high-performance, event notification library for Nim. It provides a low-level event loop and timer wheel, as well as higher-level abstractions for building TCP, UDP, HTTP/1.1 and WebSocket servers. It is designed to be minimal and efficient, with a focus on low-latency event handling and minimal overhead, providing a solid foundation for high-performance networked applications in Nim.
It is also used as a networking backend by Supranim β switch on --features:powpowwhen compiling a Supranim app.
The library is not production-ready yet and may contain bugs and securityvulnerabilities. It has been tested on Linux and macOS, but may not work on allplatforms. See security for the hardening already in place.
πDesign philosophy
- Low-level, minimal, high-performance. powpow does not ship a router, template engine or ORM. It gives you an event loop, sockets and protocol parsers, and lets you (or a framework) build the rest on top.
- Bring-your-own-router. The HTTP server exposes an
OnRequestCallbackand leaves routing entirely to the caller (see HTTP server). - Zero-copy where it counts. Request fields are materialized lazily from byte offsets; files are sent with
sendfile; responses can be streamed. - Platform-native event notification. Built on top of
epoll(Linux),kqueue(BSD, macOS) andIOCP(Windows), with apollfallback β plus an opt-in Linux io_uring backend (guide) that drives everything through submission/completion ops instead of readiness events.
πArchitecture
ββββββββββββββββββββββββββββββββ
β powpow.nim β (aggregate entry, re-exports)
ββββββββ¬βββββββββββ¬βββββββββββββ
βββββββββββββ΄βββ ββββββ΄ββββββββββββββ
β loop β β platform β
β timer wheel β β epoll|kqueue| β
β defer/idle β β poll|iocp β
βββββ¬βββββββββββ ββββββββββββββββββββ
βββββββββββββΌβββββββββββββββ
β β β
ββββββ΄βββββ βββββ΄βββββ βββββββ΄ββββββ
β signal β β net β β proto β
βrelay+OS β βtcp udp β βhttp ws β
β signals β βdns tls β βhttpserver β
βββββββββββ ββββββββββ βmultithreadβ
βratelimit β
βββββββββββββThe aggregate module src/powpow.nim re-exports:
typesβ core shared typesplatformβ the active I/O backend (exceptclose, which lives onLoop)loopβ the event loopnetβ TCP, UDP, DNS, TLS, socket helpers, raw-fd streamsprotoβ HTTP, WebSocket, multi-threaded server, rate limitersignalβ the signal relay and OS signal handlingfswatchβ file system monitoringstreamβ raw-fd streaming (IoStream, re-exported vianet)
πFeature matrix
| Area | Status |
|---|---|
Core event loop ( loop.nim) | Done β single-threaded reactor, 4-level timer wheel, deferred/idle/observer hooks, thread-safe postToLoop/ stop |
TCP networking ( net/tcp.nim) | Done β non-blocking server/client, connection pooling, corking, sendv, zero-copy file send, UDS, closeAfterDrain |
UDP networking ( net/udp.nim) | Done β bound and connected sockets |
Async DNS ( net/dns.nim) | Done β in-loop resolver, /etc/hosts + resolv.conf, A/AAAA, TTL cache |
OS signals ( signal.nim) | Done β signalfd (Linux), self-pipe (macOS/BSD/POSIX), Ctrl+C (Windows) |
File system watching ( fswatch.nim) | Done β kqueue (macOS/BSD), inotify (Linux); Windows not yet implemented |
Raw-fd streaming ( stream.nim) | Done β IoStream for pipes/socketpair/UDS/IPC; edge-triggered drain, write buffering, read backpressure; Windows not yet implemented |
HTTP/1.1 parser ( proto/http.nim) | Done β incremental zero-copy, chunked, streaming, multipart |
HTTP server ( proto/httpserver.nim) | Done β own-router design, static files, Range/conditional requests, pipelining |
WebSocket ( proto/ws.nim) | Done: RFC 6455 with standalone and HTTP-upgrade servers, wss:// on both ends, subprotocols, custom headers, keepalive timers, a self-managed client ( newWsClient) with auto-reconnect, and deflate |
Multi-threaded HTTP server ( proto/multithread.nim) | Done β SO_REUSEPORT, one loop per worker |
Thread pool ( threadpool.nim) | Done β N workers + dispatch thread owning a private loop; generic submitWork[T] results delivered as serialized callbacks; graceful drain close + discard shutdown |
TLS ( net/tls.nim) | Done β OpenSSL, implicit + upgrade (not on Windows) |
DTLS ( net/dtls.nim) | Done β DTLS 1.2 (RFC 6347) over the UDP backend: one socket, per-peer sessions, stateless HMAC cookie exchange, retransmission timers, idle/handshake sweepers (not on Windows) |
SIMD scanning ( proto/simdscan.nim) | Done β SSE2 CRLF detection with scalar fallback |
Rate limiting ( proto/ratelimit.nim) | Done β sliding window per IP, multi-window support (e.g. hourly + daily quotas checked atomically) |
io_uring backend ( io/uring.nim) | Done β opt-in Linux submission-based backend: full io_uring API binding, probe-based feature detection, zero-copy SEND_ZC + SPLICE file sends, registered buffers ( -d:powpowIoUring) |
HTTP/2 ( proto/http2*.nim) | Experimental β RFC 7540 server + multiplexing client with full HPACK, h2c (prior knowledge + Upgrade) and h2 over TLS/ALPN, flow control, GOAWAY draining; no push/priority yet (see HTTP/2) |
| HTTP/3 (QUIC) | Not planned |
πFeature details
πCore event loop
- Single-threaded non-blocking reactor
- I/O multiplexing via kqueue (macOS/BSD), epoll (Linux), IOCP (Windows) or poll (fallback)
- io_uring (Linux, opt-in): the same loop driven by submission/completion ops β one
io_uring_enterper iteration, op-driven sockets, kernel-timeout sleeps (guide) - 4-level hierarchical timer wheel β O(1) insert/fire/cancel
- One-shot and repeating interval timers
- Deferred callbacks (executed before each I/O poll iteration)
- Idle handlers (executed when no I/O events are pending)
- Pointer-based fd watcher dispatch β zero hash-table lookups on the hot path
- Generation-counter stale event detection
- Dead watcher sweep with zombie/retired list for in-flight event safety
- Thread-safe
stop()via eventfd (Linux) or self-pipe (macOS/BSD) - Buffer pool for shared read buffers
- Adaptive event capacity scaling (min 64, max 4096)
πio_uring backend
- Full io_uring API binding against
linux/io_uring.hβ all opcodes, register ops, SQE/CQE/setup/enter flags and the ABI structs, withio_uring_prep_*style helpers; no liburing dependency - Feature detection via
IORING_REGISTER_PROBE(per-opcode bitmap) instead of kernel-version guessing - Op-driven sockets: one-shot
ACCEPT/RECV/SEND/CONNECTper connection, multishot accept/recv on capable kernels - Zero-copy writes:
IORING_OP_SEND_ZCfor large payloads withIORING_CQE_F_NOTIFbuffer-lifetime tracking - Zero-copy file sends:
IORING_OP_SPLICE(file β pipe β socket) - Registered buffers:
IORING_REGISTER_BUFFERSlifecycle + opt-inSEND_ZC_FIXED(-d:powpowSendZcFixed)
πTCP networking
- Non-blocking TCP server with connection pooling
- Non-blocking TCP client with async connect (DNS resolved on the loop)
- Edge-triggered I/O events
- Write buffering with automatic corking (TCP_CORK / TCP_NOPUSH)
- Scatter-gather writes via
writev - Zero-copy file send via
sendfile(Linuxsendfile, macOSsendfile, POSIX fallback) - Graceful shutdown with close-after-drain (
closeAfterDrain) - Unix domain socket support (macOS/BSD/Linux)
SO_LINGER{0}for fast shutdown- Per-connection read buffer pooling
πAsync DNS
- In-loop DNS resolver (RFC 1035) β no blocking
getaddrinfo, no worker threads - Reads
/etc/hostsand/etc/resolv.conf(system resolver config) - A + AAAA queries with A-fallback; retries with timeout/attempts
- TTL-based result cache + negative caching
resolveAddrAsyncfor users;connectuses it automatically- Numeric IP literals resolve inline (zero DNS I/O)
πOS signals
- In-process
SignalRelaypub/sub bus (listen / listenOnce / unlisten) watchOsSignal/watchOsSignalsdeliver real OS signals through the loopOsSignalenum: SIGHUP, SIGINT, SIGQUIT, SIGUSR1/2, SIGPIPE, SIGALRM, SIGTERM, SIGURG, SIGCHLD, SIGIO- Platform-native delivery: signalfd (Linux), self-pipe (macOS/BSD/POSIX),
SetConsoleCtrlHandlerCtrl+C (Windows) β no global signal handlers - Graceful shutdown on SIGINT/SIGTERM without blocking the loop
πRaw-fd streaming
IoStreamwraps an arbitrary non-blocking fd and drives it from the loopopenStreamfor pipes, subprocess stdio, UDS and regular files;newStreamPaircreates a full-duplexsocketpair- Connection-style write path: direct write drained until EAGAIN, remainder buffered and flushed on Write events; 32 MiB queued-write cap
pause/resumegive real read backpressure (a paused reader fills the kernel pipe buffer and blocks the writer)closeis the single terminal transition and firesonCloseexactly once;closeAfterWriteflushes then delivers EOF to the peer- Platform notes: regular files work on kqueue but not epoll; Windows compiles the module away (IOCP is sockets-only)
πHTTP/1.1 parser
- Incremental, zero-copy parser β materialize strings lazily from byte offsets
- O(1) method dispatch via first-byte switch
- Pipelined request support
- Streaming body handling via callback
- Chunked transfer encoding
- Body streaming to file
- Multipart form data support
πHTTP server
- Implement-your-own-router β lower-level callback-based design
OnRequestCallback* = proc(req: HttpRequest, res: HttpResponse) {.gcsafe.}- Higher-level frameworks implement routing on top of this callback
- Streaming response body
- Static file serving with MIME type detection
- Conditional requests (If-Modified-Since, If-None-Match)
- Range requests with 206 Partial Content
- Directory listing
- CORS headers
- Streaming multipart upload handling
- Pipelined request-response processing
πWebSocket
- RFC 6455 compliant
- Standalone WebSocket server mode
- HTTP upgrade from
HttpServerroutes - Text, binary, ping/pong, and close frames
- Per-message deflate extension
- Masked frame handling
πMulti-threaded HTTP server
SO_REUSEPORTkernel-level connection distribution- One event loop + listen socket per worker thread
- Zero cross-thread communication β no single-threaded acceptor bottleneck
- Graceful shutdown via shutdown pipe
πSIMD-accelerated scanning
- SSE2-accelerated CRLF detection
- Scalar fallback for non-x86 architectures
πPlatform abstraction
kqueueβ macOS/BSD (high-performance, edge-triggered)epollβ Linux (with eventfd wake)pollβ POSIX fallbackiocpβ Windows (I/O Completion Ports)
πNetworking common
- Platform-agnostic socket API and address resolution (IPv4 + IPv6)
- Socket options: non-blocking,
SO_REUSEADDR,SO_REUSEPORT,TCP_NODELAY sendfilezero-copy file transmission- Cross-platform error handling (EAGAIN, EINPROGRESS, etc.)
- Auto-initialization (WSAStartup on Windows, SIGPIPE ignore on POSIX)
πWhere to go next
- Getting started
- Examples index β 19 runnable programs covering every feature
- API reference