From b561d2b7e658f0b7a330751a3da9e5d93f777378 Mon Sep 17 00:00:00 2001 From: Claude Date: Fri, 3 Jul 2026 14:09:06 +0000 Subject: [PATCH] =?UTF-8?q?docs:=20record=20lock=20vs=20lock-free=20decode?= =?UTF-8?q?r=20A/B=20=E2=80=94=203-4.5x=20under=20concurrent=20decode?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Same-JVM interleaved comparison against the resurrected spin-lock implementation: single-threaded parity (the uncontended lock was ~free), but 8 threads sharing one decoder run 3.0-4.5x faster lock-free — the spin lock serialized the concurrent hit path just like the old global PoolRequests lock did. Co-Authored-By: Claude Fable 5 Claude-Session: https://claude.ai/code/session_018saXqYfAa3RvSJoDXK591R --- quartz/plans/2026-07-02-nostrclient-receiver-perf.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/quartz/plans/2026-07-02-nostrclient-receiver-perf.md b/quartz/plans/2026-07-02-nostrclient-receiver-perf.md index 34b51e8011..97062c0234 100644 --- a/quartz/plans/2026-07-02-nostrclient-receiver-perf.md +++ b/quartz/plans/2026-07-02-nostrclient-receiver-perf.md @@ -508,6 +508,13 @@ threads (80k duplicate-heavy frames, capacity 256 so rotations fire constantly) and asserts zero wrong messages with exact counter accounting; the benchmark assertion still holds post-refactor. +Same-JVM A/B against the resurrected spin-lock implementation (3 rounds, +interleaved): **1 thread — parity** (0.79–1.02×, noise around 1.0; the +uncontended lock was already ~free), **8 threads sharing one decoder — +lock-free wins 3.0–4.5×** (e.g. 127ms → 28ms for 128k frames). The lock was +serializing the concurrent hit path exactly the way the old global +PoolRequests lock did; ConcurrentHashMap removes it. + ### Bounded per-connection receive buffer (REVERTED — deliberate design choice) A 4096-frame bound on the reader→consumer channel was tried (backpressure