| Commit message (Collapse) | Author | Age | Files | Lines |
| ... | |
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
After answering, a connection went back to recv for its next request and
got EAGAIN nearly every time: a failed syscall a request. A recv that
returns less than it asked for has emptied the socket, and the
edge-triggered epoll reports the next bytes when they come (epoll(7); as
nginx does), so the connection now waits for that; a peer that hung up
is read to its end as before.
Small keep-alive GETs, 64 connections, five rounds in rotation
(Raspberry Pi 5): 131.9k/s before this step, 139.9k after. With the
three steps before it (a burst's keys in one look, the clock once a
round, the head without printf): 116.1k -> 139.9k/s, p99 672 -> 512 us,
above the 127.0k of 2026-09-26's build that the app model had since
slowed. App reads: the total 111.5k -> 125.4k/s, a 20-row page 86.2k ->
94.3k; 1 MiB reads and durable posts unchanged.
|
| |
|
|
|
|
|
|
|
| |
Three snprintf calls a response (the head, its ETag and a delivery's
batch size) spent a sixth of a small read's user time in printf's
format scanning. The head is now written part by part, the same bytes
as before, clipped at the end of its buffer where snprintf's would-be
length could have sent bytes past it.
|
| |
|
|
|
|
|
|
|
|
| |
A connection's deadline was counted from a fresh clock_gettime on every
read and write, three times a request, and every event took the wall
clock again: 5.7% of a small read's user time. A connection thread now
reads the monotonic clock once after each epoll_wait and deadlines count
from that (they are 10 s by default and swept every second), and a
round's events share the time it began.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
A message for a document scanned the burst's pending keys with strcmp to
see whether its key was there, and the host scanned the burst's earlier
requests the same way before each one: both quadratic in the burst (64
concurrent reads, about 31 compares each, twice). The app now indexes its
pending documents by key (open addressing over an FNV-1a hash, 1 KiB),
answers pure_app_pending in one look, and the host asks it; whether the
current event's document is pending is a flag instead of a scan by
pointer. Bursts split where they did, except that on an owner, which
applies a round's reads first, an edit of a key read in the same round
now splits the burst at the host rather than the app saving on its own.
A unit test checks the index at 200 keys.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
--seal OUTPUT=KEY seals each request's body whole to the receiving node's
public key with HPKE (RFC 9180, base mode: X25519, HKDF-SHA256, AES-128-GCM
where the CPU has AES, else ChaCha20-Poly1305), bound to the request's
source, first number and count; X-Pure-Seal names the suite. A receiver's
--key is a raw 32-byte file, made 0600 when missing, held in OpenSSL's
secure heap; it opens the body where it lies (400 seal when it does not
open) and zeroes the plain text when the request's ticket goes.
--sealed-only refuses unsealed deliveries (403 unsealed).
The check puts a recording relay between two apps: every order applies
once, no body shows an item or a field name, a flipped bit is refused, a
replayed request applies nothing twice, and a seal to another key does not
open. Its hosts choose their own ports (--port 0). Sealed sends drain at
233-235k a second against 469-470k plain (Raspberry Pi 5): three X25519
operations a request, 164 us each. The plain request path measured the
same as before.
|
|
|
The app model, the tree store and the HTTP host lived in
prototypes/connections among the earlier document runtime, the store was
known only by its format's name, and Vega compiled six Pure sources by path.
Now, as the README's principle has it:
core/ runtime, flow and the app model (module*.c), with what the core
asks of storage (state.h, store.h)
store/ the tree store (PURETRE3, PUREREC1)
serve/ pure-serve: HTTP host, outbound delivery, JSON in place
cli/ pure-run, pure-edit-module
A top-level make builds libpure.a (app model and store, for hosts to link)
and the hosts; make check runs the store's and the app model's tests. The
earlier runtime still builds from prototypes/connections against core/ and
store/ (check, check-tree and check-core pass). Design 009 records the rule:
parts by role behind libraries; git repositories split by coupling, so the
store stays here while its contract moves with the core, and Vega stays apart.
|