Fold the leftover formatters into the SI ones and stop reallocating the draw scratch
This commit is contained in:
@@ -1,2 +1 @@
|
|||||||
/cabletest
|
|
||||||
/shots/
|
/shots/
|
||||||
|
|||||||
@@ -32,13 +32,14 @@ type scanout struct {
|
|||||||
// w and h are the logical canvas, which is portrait; pw and ph are the panel,
|
// w and h are the logical canvas, which is portrait; pw and ph are the panel,
|
||||||
// which is landscape.
|
// which is landscape.
|
||||||
type framebuffer struct {
|
type framebuffer struct {
|
||||||
fd int
|
fd int
|
||||||
back []byte
|
back []byte
|
||||||
w int
|
scratch []byte
|
||||||
h int
|
w int
|
||||||
pw int
|
h int
|
||||||
ph int
|
pw int
|
||||||
stride int
|
ph int
|
||||||
|
stride int
|
||||||
|
|
||||||
bufs [scanoutBuffers]scanout
|
bufs [scanoutBuffers]scanout
|
||||||
front int
|
front int
|
||||||
@@ -252,6 +253,7 @@ func openFramebuffer() (*framebuffer, error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
fb.back = make([]byte, fb.stride*fb.ph)
|
fb.back = make([]byte, fb.stride*fb.ph)
|
||||||
|
fb.scratch = make([]byte, fb.stride)
|
||||||
|
|
||||||
set := drm.ModeCrtc{
|
set := drm.ModeCrtc{
|
||||||
SetConnectorsPtr: uint64(uintptr(unsafe.Pointer(&fb.connID))),
|
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 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)
|
v := pixel(c)
|
||||||
row := make([]byte, fb.stride)
|
s := fb.scratch[:n]
|
||||||
for x := 0; x+4 <= fb.stride; x += 4 {
|
for i := 0; i+4 <= n; i += 4 {
|
||||||
row[x+0] = byte(v)
|
s[i+0] = byte(v)
|
||||||
row[x+1] = byte(v >> 8)
|
s[i+1] = byte(v >> 8)
|
||||||
row[x+2] = byte(v >> 16)
|
s[i+2] = byte(v >> 16)
|
||||||
row[x+3] = byte(v >> 24)
|
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++ {
|
for y := 0; y < fb.ph; y++ {
|
||||||
copy(fb.back[y*fb.stride:], row)
|
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 {
|
if x0 >= x1 || y0 >= y1 {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
v := pixel(c)
|
span := fb.pixelRun((y1-y0)*4, 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)
|
|
||||||
}
|
|
||||||
for x := x0; x < x1; x++ {
|
for x := x0; x < x1; x++ {
|
||||||
copy(fb.back[fb.offset(x, y1-1):], span)
|
copy(fb.back[fb.offset(x, y1-1):], span)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -57,7 +57,7 @@ type direction struct {
|
|||||||
base counterSet
|
base counterSet
|
||||||
|
|
||||||
heldFrames heldValue
|
heldFrames heldValue
|
||||||
heldSent heldValue
|
heldBytes heldValue
|
||||||
nic atomic.Uint64
|
nic atomic.Uint64
|
||||||
poller *nicPoller
|
poller *nicPoller
|
||||||
}
|
}
|
||||||
@@ -253,7 +253,7 @@ func (d *direction) reset() {
|
|||||||
d.mu.Unlock()
|
d.mu.Unlock()
|
||||||
|
|
||||||
d.heldFrames = heldValue{}
|
d.heldFrames = heldValue{}
|
||||||
d.heldSent = heldValue{}
|
d.heldBytes = heldValue{}
|
||||||
d.cable.reset()
|
d.cable.reset()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -297,12 +297,12 @@ var intervalCols = []colSpec{
|
|||||||
// Shared by the console table and the framebuffer so both show the same
|
// Shared by the console table and the framebuffer so both show the same
|
||||||
// figures.
|
// figures.
|
||||||
type view struct {
|
type view struct {
|
||||||
txPPS, rxPPS float64
|
txPPS, rxPPS float64
|
||||||
txGbps, rxGbps float64
|
txGbps, rxGbps float64
|
||||||
rxFrames, rxGot uint64
|
rxFrames, rxBytes uint64
|
||||||
since errs
|
since errs
|
||||||
window errs
|
window errs
|
||||||
cable cableView
|
cable cableView
|
||||||
}
|
}
|
||||||
|
|
||||||
func errsBetween(b, n counterSet) errs {
|
func errsBetween(b, n counterSet) errs {
|
||||||
@@ -326,7 +326,7 @@ func errsBetween(b, n counterSet) errs {
|
|||||||
func (d *direction) counters(now counterSet) view {
|
func (d *direction) counters(now counterSet) view {
|
||||||
return view{
|
return view{
|
||||||
rxFrames: now.s.rxFrames - d.base.s.rxFrames,
|
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(),
|
cable: d.cable.view(),
|
||||||
since: errsBetween(d.base, now),
|
since: errsBetween(d.base, now),
|
||||||
}
|
}
|
||||||
@@ -340,7 +340,7 @@ func totalView(views []view) view {
|
|||||||
t.txGbps += v.txGbps
|
t.txGbps += v.txGbps
|
||||||
t.rxGbps += v.rxGbps
|
t.rxGbps += v.rxGbps
|
||||||
t.rxFrames += v.rxFrames
|
t.rxFrames += v.rxFrames
|
||||||
t.rxGot += v.rxGot
|
t.rxBytes += v.rxBytes
|
||||||
t.since = t.since.add(v.since)
|
t.since = t.since.add(v.since)
|
||||||
t.window = t.window.add(v.window)
|
t.window = t.window.add(v.window)
|
||||||
}
|
}
|
||||||
@@ -393,7 +393,7 @@ func (d *direction) displayView(t time.Time) view {
|
|||||||
d.mu.Unlock()
|
d.mu.Unlock()
|
||||||
|
|
||||||
v.rxFrames = d.heldFrames.get(t, v.rxFrames)
|
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
|
return v
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -678,9 +678,9 @@ func run(aName, bName string, nsPerM float64) error {
|
|||||||
{"probe", fmt.Sprintf("ethertype 0x%04x every %s", probeEther, probeInterval)},
|
{"probe", fmt.Sprintf("ethertype 0x%04x every %s", probeEther, probeInterval)},
|
||||||
{"batch", fmt.Sprintf("%d frames per syscall", batchSize)},
|
{"batch", fmt.Sprintf("%d frames per syscall", batchSize)},
|
||||||
{"calibration", fmt.Sprintf("%g ns/m, zero taken from the shortest delay seen so far", nsPerM)},
|
{"calibration", fmt.Sprintf("%g ns/m, zero taken from the shortest delay seen so far", nsPerM)},
|
||||||
{"buffers", fmt.Sprintf("sndbuf %s, rcvbuf %s",
|
{"buffers", fmt.Sprintf("sndbuf %sB, rcvbuf %sB",
|
||||||
humanBytes(uint64(sockBufSize(dirs[0].txFDs[0], unix.SO_SNDBUF))),
|
scaleCount(uint64(sockBufSize(dirs[0].txFDs[0], unix.SO_SNDBUF))),
|
||||||
humanBytes(uint64(sockBufSize(dirs[0].rxFDs[0], unix.SO_RCVBUF))))},
|
scaleCount(uint64(sockBufSize(dirs[0].rxFDs[0], unix.SO_RCVBUF))))},
|
||||||
}))
|
}))
|
||||||
fmt.Println()
|
fmt.Println()
|
||||||
|
|
||||||
|
|||||||
+2
-2
@@ -26,8 +26,8 @@ func TestResetDoesNotUnderflowTotals(t *testing.T) {
|
|||||||
if v.rxFrames != 0 {
|
if v.rxFrames != 0 {
|
||||||
t.Errorf("rxFrames = %d, want 0", v.rxFrames)
|
t.Errorf("rxFrames = %d, want 0", v.rxFrames)
|
||||||
}
|
}
|
||||||
if v.rxGot != 0 {
|
if v.rxBytes != 0 {
|
||||||
t.Errorf("rxGot = %d, want 0", v.rxGot)
|
t.Errorf("rxBytes = %d, want 0", v.rxBytes)
|
||||||
}
|
}
|
||||||
|
|
||||||
// The rolling window and the rates are about now rather than since the
|
// 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 {
|
if !v.ok {
|
||||||
return "-"
|
return "-"
|
||||||
}
|
}
|
||||||
return commasInt(v.min)
|
return commas(uint64(v.min))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Averaging the two directions cancels the phy asymmetry between them, which is
|
// 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...), ",")
|
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
|
// 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
|
// on the label. Below a thousand no letter is left dangling, since a trailing
|
||||||
// space would push the figure off centre.
|
// 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{
|
d.stats(d.gridB, x, w, d.sinceYs[0], []statCell{
|
||||||
{scaleTime(elapsed), "elapsed", uiFg},
|
{scaleTime(elapsed), "elapsed", uiFg},
|
||||||
{scaleCount(v.rxFrames), "packets", uiFg},
|
{scaleCount(v.rxFrames), "packets", uiFg},
|
||||||
{scaleCount(v.rxGot), "bytes", uiFg},
|
{scaleCount(v.rxBytes), "bytes", uiFg},
|
||||||
{cable, "m", uiFg},
|
{cable, "m", uiFg},
|
||||||
})
|
})
|
||||||
d.errCounts(x, w, d.sinceYs[1], v.since)
|
d.errCounts(x, w, d.sinceYs[1], v.since)
|
||||||
|
|||||||
Reference in New Issue
Block a user