Draw every panel figure from the latest sample instead of holding the totals

This commit is contained in:
flamingcow
2026-08-04 13:49:21 -07:00
parent 4e60757937
commit fbfcabda7e
2 changed files with 6 additions and 31 deletions
+4 -26
View File
@@ -55,24 +55,8 @@ type direction struct {
drops uint64
base counterSet
heldFrames heldValue
heldBytes heldValue
nic atomic.Uint64
poller *nicPoller
}
// Monotonic totals climb by tens of thousands per frame, which is unreadable
// churn at 60Hz, so the drawn value is held and refreshed a few times a second.
type heldValue struct {
v uint64
at time.Time
}
func (h *heldValue) get(now time.Time, cur uint64) uint64 {
if now.Sub(h.at) >= totalsHold {
h.v, h.at = cur, now
}
return h.v
nic atomic.Uint64
poller *nicPoller
}
// Everything the display reads, taken at one instant, so a pair of these
@@ -238,8 +222,6 @@ func (d *direction) reset() {
d.win.push(d.base)
d.mu.Unlock()
d.heldFrames = heldValue{}
d.heldBytes = heldValue{}
d.cable.reset()
}
@@ -361,7 +343,7 @@ func (d *direction) sample() {
// Draws what the sampler last put in the ring rather than reading the counters
// again, so the display never participates in the measurement.
func (d *direction) displayView(t time.Time) view {
func (d *direction) displayView() view {
d.mu.Lock()
n := d.win.count()
if n == 0 {
@@ -377,9 +359,6 @@ func (d *direction) displayView(t time.Time) view {
v.txGbps = d.win.latest(txRateGbps)
v.rxGbps = d.win.latest(rxRateGbps)
d.mu.Unlock()
v.rxFrames = d.heldFrames.get(t, v.rxFrames)
v.rxBytes = d.heldBytes.get(t, v.rxBytes)
return v
}
@@ -569,7 +548,6 @@ const (
// How far back the shown errors reach and how many buckets the median runs
// over, so a step in the rate lands half this late.
rateWindowSpan = time.Second
totalsHold = 50 * time.Millisecond
)
// One sampler for both directions, so they are read back to back on one clock
@@ -734,7 +712,7 @@ func run(aName, bName string, nsPerM float64) error {
start = resetAll(dirs, stats)
}
for i, d := range dirs {
views[i] = d.displayView(now)
views[i] = d.displayView()
}
// Empty until the probe has a stamp from each direction, so the
// panel shows nothing there rather than a placeholder.
+2 -5
View File
@@ -1,9 +1,6 @@
package main
import (
"testing"
"time"
)
import "testing"
// A reset re-bases from a fresh capture while the ring still holds buckets from
// just before it, so the newest bucket must not be left behind the new origin.
@@ -22,7 +19,7 @@ func TestResetDoesNotUnderflowTotals(t *testing.T) {
d.rxStats[0].bytes.Store(9600)
d.reset()
v := d.displayView(time.Now())
v := d.displayView()
if v.rxFrames != 0 {
t.Errorf("rxFrames = %d, want 0", v.rxFrames)
}