Skip to content

Make state-broadcast throttle and meter-poll cadence configurable (20 Hz may be excessive on constrained hosts) #1878

Description

@Leontoorenburg

rigplane 2.10.0 · web/server.py, web/radio_poller.py · type: enhancement

Motivation — RX audio glitches. Raising this throttle was the single biggest reduction in
audible RX audio dropouts on our constrained host: the hardcoded ~20 Hz keeps the single event
loop doing state-rebuild work that competes with audio egress. (Companion issues: #1876, #1877, #1879.)

Summary

Two hot-path cadences are hardcoded:

  • State-broadcast throttle = 50 ms (~20 Hz) in _broadcast_state_update.
  • Meter poll = 25 ms (~40 Hz) (_FAST_INTERVAL) in radio_poller.

For a human-readable control UI (S-meter, ALC, SWR) these are far faster than perceptually needed,
and on a single-event-loop, CPU-contended host the per-tick build cost (see the demand-independent
work issue) dominates. We'd like an env knob to trade UI refresh rate for CPU headroom without
patching source
— the project standard for tunables.

What we measured

On our Always-Free micro, raising the broadcast throttle from 50 ms to 150 ms (~7 Hz) was the
single biggest win: idle CPU ~30% → ~20%, and moderate-stress RX frame deficit dropped to ~0. A
7 Hz S-meter is visually fine; force=True broadcasts (connect, real tuning) bypass the throttle so
those stay instant. We are not suggesting you lower the default — just expose it.

Current code

        now = time.monotonic()
        if not force and now - self._last_state_broadcast < 0.05:     # hardcoded 50 ms
            ...
                delay = max(0.0, 0.05 - (now - self._last_state_broadcast))

Proposed

Read an env-config value (default unchanged at 0.05) — mirrors the existing
ICOM_AUDIO_* tunables in core/env_config.py:

        interval = self._state_broadcast_interval_s        # from env, default 0.05
        if not force and now - self._last_state_broadcast < interval:
            ...
                delay = max(0.0, interval - (now - self._last_state_broadcast))

e.g. ICOM_STATE_BROADCAST_INTERVAL_S (default 0.05). Optionally the same for the meter poll
cadence (ICOM_METER_POLL_INTERVAL_S), with a floor to keep the CI-V session warm.

Open question for you

Is 20 Hz state delivery actually required by the frontend, or would a lower default (say 10 Hz) be
safe upstream? If meters are the only thing moving that fast, decoupling meter cadence from the rest
of the state broadcast might be the cleaner long-term answer.

Patch (demonstration only)

The actual ask is the env-knob version above; this diff just hardcodes 0.15 s to show the site/effect:

--- a/rigplane/web/server.py
+++ b/rigplane/web/server.py
@@ -1222,7 +1222,7 @@
         import time
 
         now = time.monotonic()
-        if not force and now - self._last_state_broadcast < 0.05:
+        if not force and now - self._last_state_broadcast < 0.15:  # demo: ideally an env knob (see issue)
             try:
                 asyncio.get_running_loop()
             except RuntimeError:
@@ -1231,7 +1231,7 @@
                 self._pending_state_broadcast_task is None
                 or self._pending_state_broadcast_task.done()
             ):
-                delay = max(0.0, 0.05 - (now - self._last_state_broadcast))
+                delay = max(0.0, 0.15 - (now - self._last_state_broadcast))
                 self._pending_state_broadcast_task = self._spawn(
                     self._delayed_state_broadcast(delay)
                 )

Source files are CRLF; apply with --ignore-whitespace if your working tree is LF.


Reported by Leon Toorenburg (WW0R). Diagnosis by Claude (Anthropic Claude Code). Measured on an
Oracle Always-Free micro; the 150 ms value is our deployment tuning, offered as evidence, not a
default-change request.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions