Fold the leftover formatters into the SI ones and stop reallocating the draw scratch
This commit is contained in:
@@ -1,2 +1 @@
|
||||
/cabletest
|
||||
/shots/
|
||||
|
||||
@@ -32,13 +32,14 @@ type scanout struct {
|
||||
// w and h are the logical canvas, which is portrait; pw and ph are the panel,
|
||||
// which is landscape.
|
||||
type framebuffer struct {
|
||||
fd int
|
||||
back []byte
|
||||
w int
|
||||
h int
|
||||
pw int
|
||||
ph int
|
||||
stride int
|
||||
fd int
|
||||
back []byte
|
||||
scratch []byte
|
||||
w int
|
||||
h int
|
||||
pw int
|
||||
ph int
|
||||
stride int
|
||||
|
||||
bufs [scanoutBuffers]scanout
|
||||
front 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)
|
||||
}
|
||||
|
||||
@@ -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()
|
||||
}
|
||||
|
||||
@@ -297,12 +297,12 @@ var intervalCols = []colSpec{
|
||||
// Shared by the console table and the framebuffer so both show the same
|
||||
// figures.
|
||||
type view struct {
|
||||
txPPS, rxPPS float64
|
||||
txGbps, rxGbps float64
|
||||
rxFrames, rxGot uint64
|
||||
since errs
|
||||
window errs
|
||||
cable cableView
|
||||
txPPS, rxPPS float64
|
||||
txGbps, rxGbps float64
|
||||
rxFrames, rxBytes uint64
|
||||
since errs
|
||||
window errs
|
||||
cable cableView
|
||||
}
|
||||
|
||||
func errsBetween(b, n counterSet) errs {
|
||||
@@ -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
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user