[perf](trx-client): TCP_NODELAY, Arc spectrum bins, eliminate format allocs

Three hot-path optimizations in the client polling loop and SSE
spectrum stream:

- Set TCP_NODELAY on the client→server connection so each framed
  JSON command is sent immediately instead of being held up to 40 ms
  by Nagle's algorithm.

- Wrap SpectrumData in Arc<> inside SharedSpectrum.  snapshot() was
  cloning the full bin vector (~8 KB for 2048 f32 bins) for every SSE
  /spectrum client on every 40 ms tick.  With N clients that is N×8 KB
  per tick; now replace() pays one Arc::new() and each client gets an
  O(1) pointer clone.

- Eliminate the format!("{}\n", payload) intermediate String in the
  three send_command / send_command_no_state_update / send_get_rigs
  call sites.  Push '\n' in-place on the serialised payload String
  instead of allocating a second buffer.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
This commit is contained in:
2026-03-09 22:26:24 +01:00
parent 2030d0b050
commit de11c7ff51
2 changed files with 19 additions and 9 deletions
+5 -3
View File
@@ -41,16 +41,18 @@ pub trait FrontendSpawner {
#[derive(Debug, Default)]
pub struct SharedSpectrum {
revision: u64,
frame: Option<SpectrumData>,
// Arc so that each SSE client gets a cheap pointer clone instead of
// copying the entire bin vector (~8 KB for 2048 f32 bins).
frame: Option<Arc<SpectrumData>>,
}
impl SharedSpectrum {
pub fn replace(&mut self, frame: Option<SpectrumData>) {
self.revision = self.revision.wrapping_add(1);
self.frame = frame;
self.frame = frame.map(Arc::new);
}
pub fn snapshot(&self) -> (u64, Option<SpectrumData>) {
pub fn snapshot(&self) -> (u64, Option<Arc<SpectrumData>>) {
(self.revision, self.frame.clone())
}
}