diff --git a/client.go b/client.go index 01e3237..c2ceb99 100644 --- a/client.go +++ b/client.go @@ -45,8 +45,8 @@ func RunClient(addr string, uploadBytes, downloadBytes uint64, keyLogFile io.Wri if err != nil { return err } - log.Printf("uploaded %s: %.2fs (%s/s)", formatBytes(uploadBytes), uploadTook.Seconds(), formatBytes(bandwidth(uploadBytes, uploadTook))) - log.Printf("downloaded %s: %.2fs (%s/s)", formatBytes(downloadBytes), downloadTook.Seconds(), formatBytes(bandwidth(downloadBytes, downloadTook))) + log.Printf("uploaded %s: %.2fs (%s)", formatBytes(uploadBytes), uploadTook.Seconds(), formatBandwidth(uploadBytes, uploadTook)) + log.Printf("downloaded %s: %.2fs (%s)", formatBytes(downloadBytes), downloadTook.Seconds(), formatBandwidth(downloadBytes, downloadTook)) json, err := json.Marshal(Result{ TimeSeconds: time.Since(start).Seconds(), Type: "final", diff --git a/util.go b/format.go similarity index 63% rename from util.go rename to format.go index 174aa65..b3a1337 100644 --- a/util.go +++ b/format.go @@ -9,10 +9,6 @@ import ( var kmgMap = map[string]uint64{"K": 1024, "M": 1024 * 1024, "G": 1024 * 1024 * 1024} -func bandwidth(b uint64, d time.Duration) uint64 { - return uint64(float64(b) / d.Seconds()) -} - func formatBytes(b uint64) string { const unit = 1024 if b < unit { @@ -23,7 +19,21 @@ func formatBytes(b uint64) string { div *= unit exp++ } - return fmt.Sprintf("%.1f %ciB", float64(b)/float64(div), "KMGTPE"[exp]) + return fmt.Sprintf("%.2f %ciB", float64(b)/float64(div), "KMGTPE"[exp]) +} + +func formatBandwidth(bytes uint64, d time.Duration) string { + b := float64(8*bytes) / d.Seconds() + const unit = 1000 + if b < unit { + return fmt.Sprintf("%.2f bps", b) + } + div, exp := int64(unit), 0 + for n := b / unit; n >= unit; n /= unit { + div *= unit + exp++ + } + return fmt.Sprintf("%.2f %cbps", float64(b)/float64(div), "kmgtpe"[exp]) } func ParseBytes(input string) uint64 { diff --git a/format_test.go b/format_test.go new file mode 100644 index 0000000..4d6298d --- /dev/null +++ b/format_test.go @@ -0,0 +1,26 @@ +package perf + +import ( + "testing" + "time" + + "github.com/stretchr/testify/require" +) + +func TestFormatBytes(t *testing.T) { + require.Equal(t, "999 B", formatBytes(999)) + require.Equal(t, "1.00 KiB", formatBytes(1024)) + require.Equal(t, "1.00 MiB", formatBytes(1024*1024)) + require.Equal(t, "1.00 GiB", formatBytes(1024*1024*1024)) + require.Equal(t, "1.00 TiB", formatBytes(1024*1024*1024*1024)) + require.Equal(t, "3.45 MiB", formatBytes(1024*1024*345/100)) +} + +func TestFormatBandwidth(t *testing.T) { + require.Equal(t, "800.00 bps", formatBandwidth(100, time.Second)) + require.Equal(t, "400.00 bps", formatBandwidth(100, 2*time.Second)) + require.Equal(t, "1.00 kbps", formatBandwidth(125, time.Second)) + require.Equal(t, "8.00 mbps", formatBandwidth(1e6, time.Second)) + require.Equal(t, "1.60 mbps", formatBandwidth(1e6, 5*time.Second)) + require.Equal(t, "9.87 kbps", formatBandwidth(1234, time.Second)) +} diff --git a/go.mod b/go.mod index 0f9a6ec..2ed6ce0 100644 --- a/go.mod +++ b/go.mod @@ -5,10 +5,13 @@ go 1.24 require ( github.com/jessevdk/go-flags v1.5.0 github.com/quic-go/quic-go v0.54.0 + github.com/stretchr/testify v1.11.1 ) require ( + github.com/davecgh/go-spew v1.1.1 // indirect github.com/francoispqt/gojay v1.2.13 // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect go.uber.org/mock v0.5.0 // indirect golang.org/x/crypto v0.26.0 // indirect golang.org/x/mod v0.18.0 // indirect @@ -16,4 +19,5 @@ require ( golang.org/x/sync v0.8.0 // indirect golang.org/x/sys v0.23.0 // indirect golang.org/x/tools v0.22.0 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/go.sum b/go.sum index a26e691..ee60e2b 100644 --- a/go.sum +++ b/go.sum @@ -97,8 +97,8 @@ github.com/shurcooL/webdavfs v0.0.0-20170829043945-18c3829fa133/go.mod h1:hKmq5k github.com/sourcegraph/annotate v0.0.0-20160123013949-f4cad6c6324d/go.mod h1:UdhH50NIW0fCiwBSr0co2m7BnFLdv4fQTgdqdJTHFeE= github.com/sourcegraph/syntaxhighlight v0.0.0-20170531221838-bd320f5d308e/go.mod h1:HuIsMU8RRBOtsCgI77wP899iHVBQpCmg4ErYMZB+2IA= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= -github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= -github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= +github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= github.com/tarm/serial v0.0.0-20180830185346-98f6abe2eb07/go.mod h1:kDXzergiv9cbyO7IOYJZWg1U88JhDg3PB6klq9Hg2pA= github.com/viant/assertly v0.4.8/go.mod h1:aGifi++jvCrUaklKEKT0BU95igDNaqkvz+49uaYMPRU= github.com/viant/toolbox v0.24.0/go.mod h1:OxMCG57V0PXuIP2HNQrtJf2CjqdmbrOx5EkMILuUhzM= @@ -173,6 +173,7 @@ google.golang.org/grpc v1.14.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmE google.golang.org/grpc v1.16.0/go.mod h1:0JHn/cJsOMiMfNA9+DeHDlAU7KAAB5GDlYFpa9MZMio= google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=