Fold the leftover formatters into the SI ones and stop reallocating the draw scratch

This commit is contained in:
flamingcow
2026-08-04 13:37:19 -07:00
parent f5a6420cfa
commit 2035d42734
7 changed files with 42 additions and 60 deletions
-1
View File
@@ -1,2 +1 @@
/cabletest
/shots/
+17 -15
View File
@@ -34,6 +34,7 @@ type scanout struct {
type framebuffer struct {
fd int
back []byte
scratch []byte
w int
h int
pw int
@@ -252,6 +253,7 @@ func openFramebuffer() (*framebuffer, error) {
}
}
fb.back = make([]byte, fb.stride*fb.ph)
fb.scratch = make([]byte, fb.stride)
set := drm.ModeCrtc{
SetConnectorsPtr: uint64(uintptr(unsafe.Pointer(&fb.connID))),
@@ -316,15 +318,22 @@ type rgb struct {
func pixel(c rgb) uint32 { return drm.Pack(c.r, c.g, c.b) }
func (fb *framebuffer) fill(c rgb) {
// A run of one repeated pixel, reused between calls: a whole panel row is the
// longest anything here needs, and every draw is on the one render goroutine.
func (fb *framebuffer) pixelRun(n int, c rgb) []byte {
v := pixel(c)
row := make([]byte, fb.stride)
for x := 0; x+4 <= fb.stride; x += 4 {
row[x+0] = byte(v)
row[x+1] = byte(v >> 8)
row[x+2] = byte(v >> 16)
row[x+3] = byte(v >> 24)
s := fb.scratch[:n]
for i := 0; i+4 <= n; i += 4 {
s[i+0] = byte(v)
s[i+1] = byte(v >> 8)
s[i+2] = byte(v >> 16)
s[i+3] = byte(v >> 24)
}
return s
}
func (fb *framebuffer) fill(c rgb) {
row := fb.pixelRun(fb.stride, c)
for y := 0; y < fb.ph; y++ {
copy(fb.back[y*fb.stride:], row)
}
@@ -337,14 +346,7 @@ func (fb *framebuffer) rect(x0, y0, w, h int, c rgb) {
if x0 >= x1 || y0 >= y1 {
return
}
v := pixel(c)
span := make([]byte, (y1-y0)*4)
for i := 0; i+4 <= len(span); i += 4 {
span[i+0] = byte(v)
span[i+1] = byte(v >> 8)
span[i+2] = byte(v >> 16)
span[i+3] = byte(v >> 24)
}
span := fb.pixelRun((y1-y0)*4, c)
for x := x0; x < x1; x++ {
copy(fb.back[fb.offset(x, y1-1):], span)
}
+9 -9
View File
@@ -57,7 +57,7 @@ type direction struct {
base counterSet
heldFrames heldValue
heldSent heldValue
heldBytes heldValue
nic atomic.Uint64
poller *nicPoller
}
@@ -253,7 +253,7 @@ func (d *direction) reset() {
d.mu.Unlock()
d.heldFrames = heldValue{}
d.heldSent = heldValue{}
d.heldBytes = heldValue{}
d.cable.reset()
}
@@ -299,7 +299,7 @@ var intervalCols = []colSpec{
type view struct {
txPPS, rxPPS float64
txGbps, rxGbps float64
rxFrames, rxGot uint64
rxFrames, rxBytes uint64
since errs
window errs
cable cableView
@@ -326,7 +326,7 @@ func errsBetween(b, n counterSet) errs {
func (d *direction) counters(now counterSet) view {
return view{
rxFrames: now.s.rxFrames - d.base.s.rxFrames,
rxGot: now.s.rxBytes - d.base.s.rxBytes,
rxBytes: now.s.rxBytes - d.base.s.rxBytes,
cable: d.cable.view(),
since: errsBetween(d.base, now),
}
@@ -340,7 +340,7 @@ func totalView(views []view) view {
t.txGbps += v.txGbps
t.rxGbps += v.rxGbps
t.rxFrames += v.rxFrames
t.rxGot += v.rxGot
t.rxBytes += v.rxBytes
t.since = t.since.add(v.since)
t.window = t.window.add(v.window)
}
@@ -393,7 +393,7 @@ func (d *direction) displayView(t time.Time) view {
d.mu.Unlock()
v.rxFrames = d.heldFrames.get(t, v.rxFrames)
v.rxGot = d.heldSent.get(t, v.rxGot)
v.rxBytes = d.heldBytes.get(t, v.rxBytes)
return v
}
@@ -678,9 +678,9 @@ func run(aName, bName string, nsPerM float64) error {
{"probe", fmt.Sprintf("ethertype 0x%04x every %s", probeEther, probeInterval)},
{"batch", fmt.Sprintf("%d frames per syscall", batchSize)},
{"calibration", fmt.Sprintf("%g ns/m, zero taken from the shortest delay seen so far", nsPerM)},
{"buffers", fmt.Sprintf("sndbuf %s, rcvbuf %s",
humanBytes(uint64(sockBufSize(dirs[0].txFDs[0], unix.SO_SNDBUF))),
humanBytes(uint64(sockBufSize(dirs[0].rxFDs[0], unix.SO_RCVBUF))))},
{"buffers", fmt.Sprintf("sndbuf %sB, rcvbuf %sB",
scaleCount(uint64(sockBufSize(dirs[0].txFDs[0], unix.SO_SNDBUF))),
scaleCount(uint64(sockBufSize(dirs[0].rxFDs[0], unix.SO_RCVBUF))))},
}))
fmt.Println()
+2 -2
View File
@@ -26,8 +26,8 @@ func TestResetDoesNotUnderflowTotals(t *testing.T) {
if v.rxFrames != 0 {
t.Errorf("rxFrames = %d, want 0", v.rxFrames)
}
if v.rxGot != 0 {
t.Errorf("rxGot = %d, want 0", v.rxGot)
if v.rxBytes != 0 {
t.Errorf("rxBytes = %d, want 0", v.rxBytes)
}
// The rolling window and the rates are about now rather than since the
+1 -1
View File
@@ -49,7 +49,7 @@ func (v cableView) minText() string {
if !v.ok {
return "-"
}
return commasInt(v.min)
return commas(uint64(v.min))
}
// Averaging the two directions cancels the phy asymmetry between them, which is
-19
View File
@@ -71,25 +71,6 @@ func commas(v uint64) string {
return strings.Join(append([]string{s}, parts...), ",")
}
func commasInt(v int64) string {
if v < 0 {
return "-" + commas(uint64(-v))
}
return commas(uint64(v))
}
func humanBytes(b uint64) string {
const unit = 1000.0
v := float64(b)
for _, suffix := range []string{"B", "kB", "MB", "GB", "TB"} {
if v < unit {
return fmt.Sprintf("%.1f %s", v, suffix)
}
v /= unit
}
return fmt.Sprintf("%.1f PB", v)
}
// The magnitude letter goes with the figure so the unit can stay a fixed word
// on the label. Below a thousand no letter is left dangling, since a trailing
// space would push the figure off centre.
+1 -1
View File
@@ -344,7 +344,7 @@ func (d *display) render(v view, elapsed time.Duration, cable string) error {
d.stats(d.gridB, x, w, d.sinceYs[0], []statCell{
{scaleTime(elapsed), "elapsed", uiFg},
{scaleCount(v.rxFrames), "packets", uiFg},
{scaleCount(v.rxGot), "bytes", uiFg},
{scaleCount(v.rxBytes), "bytes", uiFg},
{cable, "m", uiFg},
})
d.errCounts(x, w, d.sinceYs[1], v.since)