Measure the Pi profile on the Pi, and keep only what helped
The first cut of ?pi=1 switched off the two things that look most expensive - the backdrop-filter glass blur and the decorative CSS animation loops - and made the device slower, not faster: 53.5% of a core idle became 118%. Measured on musicdolphin, sum of the Firefox process tree, idle on the browse screen, 15s average: full app 53.5% + ambient canvas at half resolution 25.0% <- the whole win + 30fps cap on top of that 25.0% (no idle change) + decorative CSS animation loops off 24.6% (noise; left on) + backdrop-filter glass blur off 118.1% <- 5x worse The blur is what promotes each glass panel to its own compositing layer. Without it the animated canvas and the whole album grid above it collapse into one layer and every canvas frame repaints all of it. The most expensive-looking CSS in the app is what was keeping the rest of it cheap. SHOW_GLASS_BLUR and SHOW_DECORATIVE_ANIMATIONS therefore go back to unconditionally on, in both the music app and the typing game, with the numbers written down next to them so the next person does not repeat this. What is left is one real change - paint a quarter of the pixels - plus three caps that only bite while something is playing and so are not in the table above: 30fps on the canvas, 60 bubbles alive at once, and ten progress-bar re-renders a second. Those three are unmeasured; measuring them means playing audio. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -95,27 +95,34 @@ seeking is the one thing a real player can do that the mockup could not.
|
||||
|
||||
## The Raspberry Pi profile
|
||||
|
||||
`?pi=1` loads the same app with the two per-frame costs cut down. It exists for
|
||||
musicdolphin - a Pi 4 driving a 1920x1080 kiosk screen, where the app was spending
|
||||
about 70% of a core with nothing happening.
|
||||
`?pi=1` loads the same app with the ambient canvas painting a quarter of the pixels. It
|
||||
exists for musicdolphin - a Pi 4 driving a 1920x1080 kiosk screen - where Firefox
|
||||
rasterizes 2D canvas in the content process, and the canvas repaints the whole screen
|
||||
every frame whether or not anything is playing.
|
||||
|
||||
What it changes, all of it in `src/lib/lowPower.ts`:
|
||||
Everything in `src/lib/lowPower.ts` was measured on the device. Sum of the Firefox
|
||||
process tree, idle on the browse screen, 15 s average:
|
||||
|
||||
| | Full | `?pi=1` |
|
||||
|---|---|---|
|
||||
| Ambient canvas backing store | 1:1 with the screen | half scale, capped at 1280 px |
|
||||
| Ambient canvas frame rate | display refresh | 30 fps |
|
||||
| Bubbles alive at once | unlimited | 60 |
|
||||
| Progress-bar re-renders | every animation frame | 10 per second |
|
||||
| `backdrop-filter` glass blur | on | off - plain translucent instead |
|
||||
| Decorative CSS animation loops | on | off |
|
||||
| | idle CPU |
|
||||
|---|---|
|
||||
| full app | 53.5% |
|
||||
| + ambient canvas at half resolution | **25.0%** |
|
||||
| + 30 fps cap on top of that | 25.0% |
|
||||
| + decorative CSS animation loops off | 24.6% |
|
||||
| + `backdrop-filter` glass blur off | **118.1%** |
|
||||
|
||||
The principle is *make the expensive thing cheaper before switching it off*. The canvas
|
||||
is the app's whole look, so it stays and paints a quarter of the pixels half as often -
|
||||
on a soft gradient behind content that is close to invisible. Only the effects with no
|
||||
cheap version go: a real backdrop blur, and the decorative loops that carry no
|
||||
information. The aquarium pets stay on even here; they are the reward the typing game
|
||||
pays out, and a handful of `transform` writes is not what is slow.
|
||||
Two things to take from that table. The canvas resolution is the whole win, and
|
||||
**turning off the backdrop blur makes it five times worse** - the blur is what promotes
|
||||
each glass panel to its own compositing layer, so a canvas frame underneath repaints
|
||||
only the canvas. Without it the canvas and the album grid above it share one layer and
|
||||
every frame repaints all of it. The most expensive-looking CSS in the app is what keeps
|
||||
the rest of it cheap; `SHOW_GLASS_BLUR` stays on everywhere, and so do the decorative
|
||||
loops, which measured as noise.
|
||||
|
||||
So the profile is one real change plus three caps that only bite while something is
|
||||
playing, and are therefore not in the table: 30 fps on the canvas, 60 bubbles alive at
|
||||
once, and ten progress-bar re-renders a second instead of sixty (`usePlaybackClock`
|
||||
pushes a React `setState` per animation frame, into both `PlayView` and `PlayerBar`).
|
||||
|
||||
The flag is read once at module load from the URL and nowhere else - no persistence, no
|
||||
auto-detection. That is what makes "is this the profile or the hardware?" answerable by
|
||||
|
||||
Reference in New Issue
Block a user