Android perf: fix fader stutter (appendLog), drawText feedback widget, bisect docs
Bisect session with per-suspect kill switches (see BISECT_LOG.md): - appendLog was the confirmed stutter culprit — ran per-message (~110/sec) on the main thread even with the log panel hidden; A/B verified. Disabled via DEBUG_DISABLE_APPEND_LOG; shippable visible-only fix still TODO. - Per-message Log.d also disabled (freebie, no felt difference). - Glow, gradient fill, network flash, feedback setText all exonerated and restored; switches left in place at false. - FocusFeedbackWidgetView rewritten: TextView -> bare View + canvas.drawText. 60hz updates are now field-assign + invalidate, no per-update text Layout. - ContextMenuViewLogic: explicit color-picker branch for the new view type. - Timecode chunkiness root cause was REAPER audio buffer size (source-side burst cadence), documented in PERF_SESSION_2026-07-31.md; stutter bug report stamped RESOLVED. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,97 @@
|
||||
# Focus Fader Stutter — Bisect Log
|
||||
|
||||
Companion to FEEDBACK_STUTTER_BUG.md. One kill-switch per suspect; flip one,
|
||||
rebuild, drag a Focus Fader while 60hz feedback streams, record the result here,
|
||||
then either keep it off or restore it and move to the next.
|
||||
|
||||
## Ranked suspect list
|
||||
|
||||
| # | Suspect | Where | Switch |
|
||||
|---|---------|-------|--------|
|
||||
| 1 | appendLog per message (even when panel hidden) | ArrangeFunctionsWebSocket.appendLog | `DEBUG_DISABLE_APPEND_LOG` |
|
||||
| 2 | logScrollView.post(fullScroll) per message | inside appendLog | covered by #1 |
|
||||
| 3 | Runnable flood (~3 posts/msg, 300+/sec) | appendLog + dispatch handlers | mostly covered by #1 |
|
||||
| 4 | flashCard per message at 60hz | ArrangeFunctionsWebSocket.flashCard → ArrangeCardView.flashActivity | `DEBUG_DISABLE_NETWORK_FLASH` |
|
||||
| 5 | setText at 60hz on feedback TextView | FocusFeedbackWidgetView.setTextFromNetwork | `DEBUG_DISABLE_FEEDBACK_SETTEXT` |
|
||||
| 6 | LAYER_TYPE_SOFTWARE + blur glow on fader | FocusFaderWidgetView ctor (also FaderWidgetView) | `DEBUG_DISABLE_GLOW` (one per class) |
|
||||
| 7 | new LinearGradient every onDraw | FocusFaderWidgetView.onDraw (also FaderWidgetView) | `DEBUG_DISABLE_GRADIENT_FILL` (one per class) |
|
||||
| 8 | Log.d full-JSON concat per message | ArrangeFunctionsWebSocket.onMessage | `DEBUG_DISABLE_RECEIVE_LOGCAT` |
|
||||
| 9 | Echo stream (sent values come back, run appendLog+flashCard mid-drag) | handleWidgetUpdateF | partially covered by #1 |
|
||||
| 10 | vibrator.vibrate at value edges | FocusFaderWidgetView.checkEdgeHaptic | not yet added |
|
||||
|
||||
## Verdict (2026-07-31)
|
||||
|
||||
**appendLog was the stutter.** A/B confirmed: re-enabling it brings the stutter
|
||||
back immediately. Receive-logcat kept off as a freebie (no felt difference).
|
||||
Everything else exonerated and restored to original behavior — including the
|
||||
glow/software-layer rendering, which Paul tested and cleared.
|
||||
|
||||
Final switch states: `DEBUG_DISABLE_APPEND_LOG = true`,
|
||||
`DEBUG_DISABLE_RECEIVE_LOGCAT = true`, all others `false` (original behavior).
|
||||
|
||||
**Timecode fluidity root cause (found by Paul, same day):** REAPER's audio
|
||||
buffer size. REAPER emits OSC feedback per audio block, so a large buffer
|
||||
makes updates arrive in chunky bursts — uneven cadence no client-side
|
||||
rendering can smooth. Lowering the buffer restored fluid feedback. The
|
||||
drawText rewrite of FocusFeedbackWidgetView (done just before this discovery)
|
||||
stays: it's the cheapest render path and collapses same-frame updates to one
|
||||
draw regardless of source pacing.
|
||||
|
||||
## Test runs
|
||||
|
||||
### Run 1 — DEBUG_DISABLE_APPEND_LOG = true (suspects 1+2, most of 3)
|
||||
- Date: 2026-07-31
|
||||
- Switches off: appendLog (all in/out log lines + auto-scroll posts)
|
||||
- Side effect while off: debug log panel shows nothing new when opened
|
||||
- Result: **CONFIRMED CULPRIT — "way smoother"** with appendLog disabled.
|
||||
- A/B re-test same day: re-enabled appendLog, stutter came back immediately;
|
||||
disabled again. Not a placebo — appendLog is definitively implicated.
|
||||
Left OFF for now; permanent fix TBD.
|
||||
|
||||
### Run 2 — DEBUG_DISABLE_RECEIVE_LOGCAT = true (suspect 8)
|
||||
- Date: 2026-07-31
|
||||
- Switches off: appendLog (kept off from Run 1) + per-message Log.d in onMessage
|
||||
- Side effect while off: incoming messages no longer visible in logcat
|
||||
- Result: **No perceptible difference.** Kept off anyway (free optimization,
|
||||
nobody reads logcat during performance).
|
||||
|
||||
### Run 3 — DEBUG_DISABLE_GLOW = true (suspect 6)
|
||||
- Date: 2026-07-31
|
||||
- Switches off: appendLog + receive-logcat (from Runs 1-2) + shadow-layer glow
|
||||
and software rendering in FocusFaderWidgetView AND FaderWidgetView
|
||||
- Side effect while off: faders lose their glow — plain value line + dot
|
||||
- Result: **Exonerated.** Still smooth with glow off, but no felt difference
|
||||
attributable to it — Paul: "the glow wasn't an issue." Turned back ON
|
||||
(original software-layer glow restored) at end of bisect.
|
||||
|
||||
### Run 4 — DEBUG_DISABLE_NETWORK_FLASH = true (suspect 4)
|
||||
- Date: 2026-07-31
|
||||
- Switches off: appendLog + receive-logcat + glow (Runs 1-3) + network-triggered
|
||||
activity-ring flashes (local touch flashes still work)
|
||||
- Side effect while off: cards don't blink green on desktop-driven updates
|
||||
- Result: **SKIPPED — suspect was already inert.** The tablet's "Activity:
|
||||
ON/OFF" button (default OFF) was off during all stutter tests, and
|
||||
flashActivity() early-returns on that flag before any timer work. Kill
|
||||
switch left in place (harmless, skips a registry lookup) but this suspect
|
||||
is exonerated for the observed stutter.
|
||||
|
||||
### Run 5 — DEBUG_DISABLE_FEEDBACK_SETTEXT = true (suspect 5, plus its share of 3)
|
||||
- Date: 2026-07-31
|
||||
- Switches off: appendLog + receive-logcat + glow (Runs 1-3) + the ENTIRE
|
||||
widget_feedback UI path: the runOnUiThread post, registry lookup, and
|
||||
setText all skipped (placed before the post, so this also removes 60/sec
|
||||
of the runnable flood)
|
||||
- Side effect while off: feedback readouts (timecode etc.) freeze at last text
|
||||
- Result: **Nothing earth-shaking — no clear felt difference.** Switch turned
|
||||
back OFF (readouts are needed regardless). 60hz setText is tolerable now
|
||||
that appendLog is gone; candidate for once-per-frame conflation later, not
|
||||
a primary culprit.
|
||||
|
||||
### Run 6 — DEBUG_DISABLE_GRADIENT_FILL = true (suspect 7)
|
||||
- Date: 2026-07-31
|
||||
- Switches off: appendLog + receive-logcat + glow (kept from earlier runs);
|
||||
gradient fill replaced with flat translucent fill in both fader classes
|
||||
- Side effect while off: fader fill is flat color, no fade-to-transparent
|
||||
- Result: **No felt difference — gradient turned back ON** (look kept).
|
||||
Create-once gradient (setLocalMatrix) stays on the permanent-fix list as
|
||||
hygiene, not a culprit.
|
||||
Reference in New Issue
Block a user