Skip to content

perf(obd): stop busy-polling the sensor schedule every 10ms - #65

Merged
eigger merged 1 commit into
mainfrom
perf/obd-poll-loop-battery
Jul 30, 2026
Merged

perf(obd): stop busy-polling the sensor schedule every 10ms#65
eigger merged 1 commit into
mainfrom
perf/obd-poll-loop-battery

Conversation

@eigger

@eigger eigger commented Jul 30, 2026

Copy link
Copy Markdown
Owner

The OBD poll loop woke up on a fixed 10ms tick whenever no sensor was due, regardless of how far away the next one actually was. A sensor polled every 60s still triggered ~100 wakeups per second for the entire connection — 180,000 wakeups over a 30-minute drive versus the roughly 1,800 actually needed if it slept until the next sensor's due time. This runs inside a foreground service for as long as the OBD adapter stays connected, so it kept the CPU from reaching deep sleep for the whole trip — a plausible explanation for reports of high battery drain while connected.

nextPollAtMs is only ever written inside this same loop, so sleeping exactly until the earliest one is due changes nothing about correctness or responsiveness; it only removes the wasted wakeups in between. Extract the computation as computeIdleWaitMs, floored at the existing 10ms tick (guards against delay() on a negative or zero duration) and capped at 5s as a safety margin, so the loop still checks in periodically rather than sleeping for an unbounded stretch.

The two other delay(POLL_LOOP_MS) call sites are unchanged: one covers the brief startup window before ELM327 init completes, the other waits out tx_delay between queued commands (typically tens of milliseconds) — neither runs for the bulk of a connection's lifetime the way the idle-wait branch did.

The OBD poll loop woke up on a fixed 10ms tick whenever no sensor was due,
regardless of how far away the next one actually was. A sensor polled every
60s still triggered ~100 wakeups per second for the entire connection —
180,000 wakeups over a 30-minute drive versus the roughly 1,800 actually
needed if it slept until the next sensor's due time. This runs inside a
foreground service for as long as the OBD adapter stays connected, so it
kept the CPU from reaching deep sleep for the whole trip — a plausible
explanation for reports of high battery drain while connected.

nextPollAtMs is only ever written inside this same loop, so sleeping exactly
until the earliest one is due changes nothing about correctness or
responsiveness; it only removes the wasted wakeups in between. Extract the
computation as computeIdleWaitMs, floored at the existing 10ms tick (guards
against delay() on a negative or zero duration) and capped at 5s as a safety
margin, so the loop still checks in periodically rather than sleeping for an
unbounded stretch.

The two other delay(POLL_LOOP_MS) call sites are unchanged: one covers the
brief startup window before ELM327 init completes, the other waits out
tx_delay between queued commands (typically tens of milliseconds) — neither
runs for the bulk of a connection's lifetime the way the idle-wait branch did.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@eigger
eigger merged commit 97bc40f into main Jul 30, 2026
3 checks passed
@eigger
eigger deleted the perf/obd-poll-loop-battery branch July 30, 2026 13:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant