Live page: 10-second averages for the figures and the table

The big figures, the per-peer speeds and the busiest-first order
average the last 5 steps instead of swinging with every burst, and the
figures sit in fixed-width columns so they no longer push each other
around. The charts still show every step.
This commit is contained in:
Daniel Redetzke
2026-10-05 14:44:18 +03:00
parent dbd1808803
commit 8d97f6c61e
2 changed files with 12 additions and 6 deletions
+1 -1
View File
@@ -383,7 +383,7 @@ dialog::backdrop { background: rgba(22, 23, 26, .55); }
pre.log.tall { max-height: calc(100vh - 260px); min-height: 420px; } pre.log.tall { max-height: calc(100vh - 260px); min-height: 420px; }
/* live */ /* live */
.livenow { display: flex; flex-wrap: wrap; gap: 12px 40px; margin-top: 14px; } .livenow { display: grid; grid-template-columns: repeat(auto-fill, minmax(190px, 1fr)); gap: 12px 24px; margin-top: 14px; }
.livenow .k { font-size: 13px; color: var(--ink-2); } .livenow .k { font-size: 13px; color: var(--ink-2); }
.livenow .v { font-size: 30px; font-weight: 600; letter-spacing: -0.01em; margin-top: 4px; font-variant-numeric: tabular-nums; } .livenow .v { font-size: 30px; font-weight: 600; letter-spacing: -0.01em; margin-top: 4px; font-variant-numeric: tabular-nums; }
.livenow .v small { font-size: 16px; color: var(--ink-3); font-weight: 500; margin-left: 6px; } .livenow .v small { font-size: 16px; color: var(--ink-3); font-weight: 500; margin-left: 6px; }
+11 -5
View File
@@ -1119,6 +1119,10 @@
// Below this a peer counts as idle: keepalives and background chatter. // Below this a peer counts as idle: keepalives and background chatter.
const IDLE_BPS = 2000; const IDLE_BPS = 2000;
// The figures and the table average the last few steps so they do not
// swing with every burst; the charts show each step.
const AVG_STEPS = 5;
const calm = () => window.matchMedia('(prefers-reduced-motion: reduce)').matches; const calm = () => window.matchMedia('(prefers-reduced-motion: reduce)').matches;
// countTo moves the number in el from its last value to v over a short // countTo moves the number in el from its last value to v over a short
@@ -1251,17 +1255,19 @@
} }, 'Pause'); } }, 'Pause');
const subText = () => paused const subText = () => paused
? ['Paused · the chart keeps the moment you paused'] ? ['Paused · the chart keeps the moment you paused']
: [h('span', { class: 'dot ok pulse' }), ' Updated every ' + live.step + ' s · speeds are averages over the step']; : [h('span', { class: 'dot ok pulse' }), ' Updated every ' + live.step + ' s · figures are ' + AVG_STEPS * live.step + '-second averages'];
const sub = h('p', { class: 'sub livesub' }, subText()); const sub = h('p', { class: 'sub livesub' }, subText());
const draw = (slide) => { const draw = (slide) => {
const pts = live.points; const pts = live.points;
const sumAt = (p) => Object.values(p.peers).reduce((a, [d, u]) => ({ down: a.down + d, up: a.up + u }), { down: 0, up: 0 }); const sumAt = (p) => Object.values(p.peers).reduce((a, [d, u]) => ({ down: a.down + d, up: a.up + u }), { down: 0, up: 0 });
const series = pts.map((p) => ({ t: p.t, ...sumAt(p) })); const series = pts.map((p) => ({ t: p.t, ...sumAt(p) }));
const now = series[series.length - 1] || { down: 0, up: 0 }; const recent = pts.slice(-AVG_STEPS);
const last = pts.length ? pts[pts.length - 1].peers : {}; const avg = (f) => recent.length ? recent.reduce((a, p) => a + f(p), 0) / recent.length : 0;
countTo(down, now.down); const last = {};
countTo(up, now.up); for (const p of peers) last[p.id] = [avg((x) => (x.peers[p.id] || [0, 0])[0]), avg((x) => (x.peers[p.id] || [0, 0])[1])];
countTo(down, avg((p) => sumAt(p).down));
countTo(up, avg((p) => sumAt(p).up));
active.replaceChildren(String(peers.filter((p) => { const r = last[p.id]; return r && r[0] + r[1] >= IDLE_BPS; }).length), active.replaceChildren(String(peers.filter((p) => { const r = last[p.id]; return r && r[0] + r[1] >= IDLE_BPS; }).length),
h('small', null, '/ ' + peers.filter((p) => p.stats.online).length + ' online')); h('small', null, '/ ' + peers.filter((p) => p.stats.online).length + ' online'));
lc.update(series, live.size, live.step, slide); lc.update(series, live.size, live.step, slide);