Files
explore/tools/perf
zeekay dee054786f test(perf): the harness that turns "feels slow" into a number
Two scripts, any Lux surface, from a URL. mobile-sweep reads scrollWidth vs
clientWidth AND every element's box at 393x852 — a body that cannot scroll is
not proof the content fits, it is proof the content is unreachable. perf adds
4x CPU + Slow-3G over CDP and reports LCP with the element that won it, CLS, an
INP proxy, long tasks, and bytes by type.

First run against production, as the before number:

  explore.lux.network        overflowPx  clippedEls  worstRight  small<44
    /                                 0          64        1113        53
    /blocks                           4           6         397        15
    /txs                            823        2820        1216        14
    /accounts                         0           0           0        11

  exchange.lux.network
    /                                 0           5         402        17
    /swap                             0           0           0        18
    /explore                          0         445         927         7
    /positions                        0           0           0         6

/txs pushes a 393px phone sideways by 823px and puts 2820 elements off the side
of the screen; /explore on the exchange clips 445 of them into a body that will
not scroll to reach them.

Screenshots are gated on a positive assertion — more than 200 characters of
text — because a shot of a spinner, a login wall or an unstyled flash is worse
than no shot.
2026-07-27 18:39:49 -07:00
..

perf — the two numbers a claim needs

An improvement without a before number is a claim. These two scripts produce the before number, for any Lux surface, from a URL.

node tools/perf/mobile-sweep.mjs https://explore.lux.network "explore LIVE" "/,/blocks,/txs"
node tools/perf/perf.mjs        https://explore.lux.network "explore LIVE" "/,/txs"

mobile-sweep is layout only, so it needs no throttling and runs a route per second. It reports, at an iPhone 15 Pro logical viewport (393x852, DPR 3, touch):

  • overflowPx — scrollWidth - clientWidth on the document. The page scrolls sideways.
  • clippedEls — elements whose box lies outside the viewport. This is the number that matters when overflowPx is 0: a body that cannot scroll does not mean the content fits, it means the content is unreachable. Read it with perf.mjs's containment check before calling it a defect — an element inside an overflow-x: auto ancestor is scrollable, not clipped.
  • small<44 — interactive elements under 44px tall, the floor Apple and Google both publish.

perf.mjs adds 4x CPU throttling and a Slow-3G network profile over CDP and reports LCP (with the element that won it), CLS, an INP proxy, long-task count and total blocking time, bytes by type, and the same layout audit. Pass --desktop for 1440x900. SHOT_DIR=… captures a screenshot, but only when the page has more than 200 characters of text — a screenshot of a spinner or a login wall is worse than no screenshot.

Both take a real origin, so they measure production the same way they measure a next start or a static out/ on localhost. Compare like with like: serve local builds through something that sends brotli, or every local LCP will look three times worse than the CDN it is bound for.