Skip to content

Revert the three-second G radar trace: it was merged on a measurement of the wrong code path - #212

Merged
PurpleSentinel merged 2 commits into
mainfrom
revert/136-trail-sizing
Oct 16, 2026
Merged

PurpleSentinel merged 2 commits into
mainfrom
revert/136-trail-sizing

Conversation

@PurpleSentinel

Copy link
Copy Markdown
Contributor

Reverts #211. Requested after the regression was confirmed on hardware.

What went wrong

I measured the render cost while the device was being moved by hand, reasoning that a moving dot dirties more screen area than a parked one.

That is backwards here. Motion keeps GravityCalibration from completing, so resolve() returns an invalid result, so the meter state never reaches ready, so GRadarScreen::update() takes the early-out branch that hides every trail dot without positioning or restyling it:

if (!usable || index >= snapshot.trail_count) {
    lv_obj_add_flag(dot, LV_OBJ_FLAG_HIDDEN);
    continue;
}

Every number in #211 is the cost of drawing nothing. The scaling from 1,727 us to 2,395 us looked like a clean linear signal, which is what made it convincing.

Measured properly

Both columns with the device untouched, which is when the meter reaches ready and the trace is actually drawn:

24 points 60 points
object work, mean 4,889–6,252 us 13,658–18,303 us
object work, worst 8,386 us 20,677 us
share of the 50 ms display period 12–16% 36–41%
worst repaint 38,532–41,095 us 53,101–55,442 us
worst repaint vs the 25 ms service period 154–164% 212–221%
repaints per 10 s 147–152 166–170

Three times the object work and 14 ms more on the worst repaint. The increase was a regression, not the nearly-free change I reported. Object cost also grows faster than linearly in the dot count, which fits the invalid-area list saturating and joining rather than a fixed overhead plus a per-dot cost.

What this leaves

The revert is complete, including the instrumentation — the capacity derivation, the static_assert tying it to the display cadence, and the radar: / draw: reports all go back out. That is deliberate: this branch puts main back to a known state rather than keeping the half I still believe in. The instrumentation is worth re-landing on its own, without any capacity change, and I would rather propose that separately than smuggle it through a revert.

The pre-existing finding stands and is the more important one. At the restored 24 points a repaint already costs ~40 ms against a 25 ms service period, 147–152 times per 10 seconds, on the task that also dispatches the GNSS poll. At 25 Hz a fix is due every 40 ms. Nothing is visibly lost today, but there is no margin, and it is why the trace cannot grow until the drawing is made cheaper. That needs its own issue — with the measurement attached this time.

Verification

  • make repo-check passes
  • The 24-point figures above come from a build of the merged code with kImuTrailSpanMs alone changed back, flashed and captured, so the comparison differs by that constant and nothing else

🤖 Generated with Claude Code

PurpleSentinel and others added 2 commits October 16, 2026 22:00
The measurement it was merged on was taken while the device was being moved by
hand. Motion keeps the gravity calibration from completing, so resolve() stays
invalid, the meter state is not ready, and update() takes the branch that hides
every trail dot without positioning or restyling it. The apparently clean
scaling from 1,727 to 2,395 us was the cost of drawing nothing.

Measured again with the device untouched, which is when the trace is actually
drawn:

                                    24 points        60 points
  object work, mean                 4,889-6,252 us   13,658-18,303 us
  share of the 50 ms display period 12-16%           36-41%
  worst repaint                     38,532-41,095 us 53,101-55,442 us
  repaints per 10 s                 147-152          166-170

Three times the object work and 14 ms more repaint, so the increase was a
regression rather than nearly free.

Also records the pre-existing finding: at 24 points a repaint already costs
40 ms against a 25 ms service period, on the task that also dispatches the
receiver poll, and a fix is due every 40 ms at 25 Hz. The trace cannot grow
until that is addressed.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@PurpleSentinel
PurpleSentinel merged commit 3f314e9 into main Oct 16, 2026
3 checks passed
@PurpleSentinel
PurpleSentinel deleted the revert/136-trail-sizing branch October 16, 2026 21:05
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