diff options
| author | Gabriel Schneider <[email protected]> | 2026-09-25 17:10:23 -0300 |
|---|---|---|
| committer | Gabriel Schneider <[email protected]> | 2026-09-25 17:52:33 -0300 |
| commit | 73602127d15d10a1932b6fe916bd18a608054980 (patch) | |
| tree | 0165c9a3638ea5c2031cad1189a9cd5e89a2dd77 /src/serve.zig | |
| parent | df20863879fe2d83077534f4726a985ffc239def (diff) | |
| download | cloud9-73602127d15d10a1932b6fe916bd18a608054980.tar.gz cloud9-73602127d15d10a1932b6fe916bd18a608054980.zip | |
fs, serve: set an engine up in place, so a large fid table costs only the fids used
A kernel mount (9ns) holds a fid for every inode the kernel caches, so a
server that wants `ls -l` of a directory of thousands of files to work
needs a fid table of tens of thousands. Server.initIn sets an engine up
in place and, with fid_index, never writes a fid slot at or past
high_water; the walks over the table (references, reset, orphan) stop
there. Runner.init sets each connection's small fields one by one and
leaves the engine to start(), so connection slots nobody uses are never
written.
Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
Diffstat (limited to 'src/serve.zig')
| -rw-r--r-- | src/serve.zig | 16 |
1 files changed, 14 insertions, 2 deletions
diff --git a/src/serve.zig b/src/serve.zig index 10c8d01..0311f3d 100644 --- a/src/serve.zig +++ b/src/serve.zig @@ -178,7 +178,7 @@ pub fn Runner(comptime Backend: type, comptime opts: fs.Options, comptime limits c.room = .unset; // Under the lock: the slot is already visible as live. c.lock(); - c.engine = .init(.{ .in = &c.in, .out = &c.out, .root = r.root, .seed = r.seed ^ c.index }); + c.engine.initIn(.{ .in = &c.in, .out = &c.out, .root = r.root, .seed = r.seed ^ c.index }); c.unlock(); if (r.handler.opened) |f| f(r.handler.ctx, c); } @@ -308,7 +308,19 @@ pub fn Runner(comptime Backend: type, comptime opts: fs.Options, comptime limits r.slots = .init; r.stopping = .init(false); r.active = .init(0); - for (&r.conns, 0..) |*c, i| c.* = .{ .runner = r, .index = @intCast(i) }; + // Field by field: a connection's engine and buffers are written + // when a client takes the slot (`start`), so a runner sized for + // many connections costs nothing for the ones never used. + for (&r.conns, 0..) |*c, i| { + c.runner = r; + c.index = @intCast(i); + c.user = null; + c.mutex = .init; + c.flags = .init(0); + c.signal = .unset; + c.room = .unset; + c.used = .init(false); + } } /// Binds `address` and starts accepting on it. Returns the bound |
