strand

Performance

Strand aims to be fast when something moves and to cost nothing when nothing does. This page says how it gets there, and how to measure your own shell.

An idle shell does no work

The program is one graph of values (see state and reactivity). When nothing is written, nothing is recomputed and no frame is asked for. A service wakes the shell only as often as what you read from it changes: a clock that shows minutes wakes it once a minute, and the battery when the battery changes. Services nobody reads are not running at all.

Only what changed is painted

Each frame repaints only the area that changed, its damage. When the clock ticks, Strand repaints the clock's text, not the bar. On the demo bar (strand run --demo), 2560 px wide at scale 1 and 1.25, a minute tick, even one that changes every digit and the text's width, repaints at most 2,000 px².

Layout is just as narrow. x, y, scale, rotate and opacity never lay the tree out again, and a size that springs lays out only the part of the tree under the nearest ancestor whose size stays put (see layout).

CPU and GPU

Strand draws on the CPU by default, into shared memory, with exact damage: that is the cheapest way to draw a bar whose clock ticks. When a large area animates, the GPU is faster, so a surface moves to it:

  • A surface moves to the GPU at the first large frame (at least 200,000 pixels of damage) of an animation, such as a panel opening, a scroll or a theme crossfade, or at the third large frame in a row of something that animates with no spring, such as a shader's clock.
  • It goes back to the CPU once it has been settled, with only small frames or none, for 3 seconds. A surface that animates again within 30 seconds of going back waits 15 seconds the next time, so one you use every few seconds is not handed back and forth.
  • A small animation the CPU draws slowly (4 ms or more a frame) keeps its surface on the GPU.
  • The GPU device is started with the shell, off the drawing path, and kept, so an animation never waits for it. Where no GPU can exist, Strand never asks for one. After 3 lost devices in one run the GPU stays off until Strand restarts, and everything is drawn on the CPU.

strand report shows each surface's backend and why.

Strand's own build is held to memory and speed budgets, set in design.md. They catch a change that makes Strand slower or bigger, and are never a limit on what your shell may do.

Measuring your own shell

strand report describes the running shell: the process's PSS, the GPU's status, and for each surface its backend, why it is on the GPU and its frame times (p50, p95 and p99 over the frames drawn among its last 600 paints).

This page on GitHubThis page as Markdownllms.txt