summaryrefslogtreecommitdiff
path: root/src/serve.zig
diff options
context:
space:
mode:
authorGabriel Schneider <[email protected]>2026-09-25 17:10:23 -0300
committerGabriel Schneider <[email protected]>2026-09-25 17:52:33 -0300
commit73602127d15d10a1932b6fe916bd18a608054980 (patch)
tree0165c9a3638ea5c2031cad1189a9cd5e89a2dd77 /src/serve.zig
parentdf20863879fe2d83077534f4726a985ffc239def (diff)
downloadcloud9-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.zig16
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