diff options
| author | eunhhu <[email protected]> | 2026-09-27 07:30:51 +0100 |
|---|---|---|
| committer | eunhhu <[email protected]> | 2026-09-27 07:30:51 +0100 |
| commit | eb37aad3ae7f9df1d6c0b09108e3a2d69d0d4d82 (patch) | |
| tree | 4ae7ca2e9ab8c0319c5215040b22c20b5832a909 /prototypes/connections/module-text.c | |
| parent | 194d243165c2b78d64e0263f39f7a63dbe4a1310 (diff) | |
| download | pure-eb37aad3ae7f9df1d6c0b09108e3a2d69d0d4d82.tar.gz pure-eb37aad3ae7f9df1d6c0b09108e3a2d69d0d4d82.zip | |
Read JSON bodies in place, groups included (082)
pure-serve no longer copies a JSON body's strings into the message's
payload. The ingress is the prefix, a table of each field's start and
size, and the body as it came; the connection thread scans the body
once, puts numbers into the prefix and records where each string is.
Only a string with escapes is unescaped, over itself (it never grows).
A group of fields comes as an object inside the body and, for a fixed
field, as its path in the query (?to.zip=7). A group where a field
belongs, a value where a group does, an array or true/false/null is
json_type; an unknown member, inside a group too, json_field.
The string scan and UTF-8 checks now pass over eight bytes at a time
while none needs a look (pure_utf8_step, so every text check gains).
On the Pi, posting {"name":"k","text":"x..."} to a stateless app went
from 652-655 to 3,737-3,953 requests/s with 256 KiB of text (server
CPU 1.52 to 0.25 ms a request, peak RSS 5.2 to 3.2-3.4 MiB) and from
29.1k to 76.3-76.7k/s with 4 KiB; the load generator gains a json
method and benchmarks/http/echo.aup is the app.
Diffstat (limited to 'prototypes/connections/module-text.c')
| -rw-r--r-- | prototypes/connections/module-text.c | 5 |
1 files changed, 5 insertions, 0 deletions
diff --git a/prototypes/connections/module-text.c b/prototypes/connections/module-text.c index 596585c..68c03b0 100644 --- a/prototypes/connections/module-text.c +++ b/prototypes/connections/module-text.c @@ -12,6 +12,11 @@ enum { CHUNK = 4096 }; bool pure_utf8_step(unsigned *state, PureSpan span) { unsigned remaining = *state & 3, range = *state >> 2; for (size_t i = 0; i < span.size; ++i) { + /* Eight ASCII bytes at a time between characters. */ + uint64_t word; + while (!remaining && span.size - i >= 8 && (memcpy(&word, span.data + i, 8), !(word & UINT64_C(0x8080808080808080)))) + i += 8; + if (i == span.size) break; unsigned char b = span.data[i]; if (remaining) { unsigned low = range == 1 ? 0xA0 : range == 3 ? 0x90 : 0x80; |
