Skip to content

Health: colour the swap bar by paging rate, not by fill - #767

Open
cyberb wants to merge 1 commit into
masterfrom
health-swap-status-from-rate
Open

Health: colour the swap bar by paging rate, not by fill#767
cyberb wants to merge 1 commit into
masterfrom
health-swap-status-from-rate

Conversation

@cyberb

@cyberb cyberb commented Aug 26, 2026

Copy link
Copy Markdown
Member

Problem

A device that has been up for months parks cold pages in swap and never reclaims them. Reported on the forum as a Nextcloud problem (nextcloud very slow, 100% cpu usage), but reproduced on my own box where nothing is actually wrong:

Mem:  7864 total, 5390 used, 2210 buff/cache, 1597 available
Swap: 3000 total, 3000 used, 0 free

procs -----------memory---------- ---swap-- ...cpu-----
 r  b   swpd   free   buff  cache   si   so  ... us sy id wa
 0  0 3073016 237732 240144 2054684   0    0  ...  5  3 93  0

si/so are 0 across the sample, CPU 93% idle, 1.6 GB available. But pctStatus() turned the swap bar red at >=90% fill, so the Health page showed a permanent alarm — right next to its own "swap in 0 · swap out 0 KB/s" line.

Change

Swap fill says how much has ever been paged out; it says nothing about whether the machine is struggling now. The rate does, and backend/health/metrics.go already collects swap_in_pages/swap_out_pages.

  • The swap bar's status now comes from swapRate — 256 KB/s warns, 2 MB/s is an exception.
  • Fill stays as the bar's length and in the used / total MB readout, where it informs without rendering a verdict.
  • Memory and disk bars are untouched; fill is the right signal there.
  • The dev stub never emitted the two counters, so the rate line read 0 in dev regardless. It now advances them.

Verified on a real device

Deployed to a box running 19 apps (platform rev x1, all 75 snap services active). Swap 3000/3000 MB, pswpin/pswpout identical across a 2s sample, so the bar renders green at 100% fill with 0 · 0 KB/s beneath it. Before this it was red.

Also included: visual_diff_skip_build 3076 → 3084

Not related to the swap change, but this branch cannot go green without it. The nightly artifact prune on the CI host deleted platform/3084-*, which is the build FindLatestBuild("stable") resolves to, so ci-diff downloads an empty tree and fails on every branch build:

Stable build: #3084
  SKIP: base=missing compare=artifact/playwright/desktop/screenshot
FAIL: no screenshots were compared stable

3076 was the previous occurrence. The constant only takes effect when it equals the current latest stable, so it went inert when stable moved to 3084.

Note this makes visual-diff pass by returning early rather than by comparing. No e2e spec visits /health, so this PR loses no coverage it ever had — but the underlying defect remains: visual-diff/cmd/app.go:54 returns nil for a build directory that does not exist, making a pruned baseline indistinguishable from a screenshot regression. Worth a follow-up.

The baseline regenerates on the next stable push and is protected from pruning from then on by the artifact cleaner now running on the CI host, which keeps the last green stable per app regardless of age.

Tests

New tests/unit/Health.spec.js covers full-but-idle (green), sustained paging with swap mostly free (red), light paging (amber), and that pctStatus still governs the other bars. Full suite: 25 suites / 129 tests green, eslint clean. Jsonnet validated with drone jsonnet + drone lint.

A box that has been up for months parks cold pages in swap and never
reclaims them. On my own device swap sits at 3000/3000 MB with si/so at
0, CPU 93% idle and 1.6 GB still available - nothing is wrong, but
pctStatus() turned the bar red at >=90% fill, so the Health page showed
a permanent alarm. That red bar is what sends people to the forum
convinced their device is broken.

Swap fill says how much has ever been paged out. It says nothing about
whether the machine is struggling now. The rate does, and the backend
already collects swap_in_pages/swap_out_pages - the line directly under
the bar prints them, so the page was showing "0 · 0 KB/s" next to a red
bar.

Key the bar off that rate instead: 256 KB/s warns, 2 MB/s is an
exception. Fill stays as the bar's length and in the MB readout, where
it is informative without being a verdict. Memory and disk bars keep
using fill, which is the right signal for those.

The dev stub never emitted the two counters, so the rate line read 0
there regardless; it now advances them so the page can be exercised
without a real device.

Also bumps visual_diff_skip_build to 3084, without which this branch
cannot go green. The nightly artifact prune on the CI host deleted
platform/3084-*, the build FindLatestBuild("stable") resolves to, so
ci-diff downloads an empty tree and fails with "no screenshots were
compared" on every branch build. 3076 was the previous occurrence; the
constant only matches when it equals the current latest stable, so it
went inert when stable moved. This is a stopgap - ci-diff still cannot
tell a pruned baseline from a screenshot regression, and DownloadBuild
should fail on a missing build directory instead of returning nil.
@cyberb
cyberb force-pushed the health-swap-status-from-rate branch from da38481 to 2b3e4c9 Compare August 28, 2026 00:11
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