From 34dd43bf1ba890add8b1de191f886dd443d783b6 Mon Sep 17 00:00:00 2001 From: Sebastiaan van Stijn Date: Mon, 28 Mar 2022 11:26:39 +0200 Subject: [PATCH] cli/command/container: some small performance optimizations for formatting stats MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Formatting stats runs in a loop to refresh the stats for each container. This patch makes some small performance improvments by reducing the use of Sprintf in favor of concatenating strings, and using strconv directly where possible. Benchmark can be run with: GO111MODULE=off go test -test.v -test.bench '^BenchmarkStatsFormat' -test.run '^$' ./cli/command/container/ Before/after: BenchmarkStatsFormatOld-8 2655 428064 ns/op 62432 B/op 5600 allocs/op BenchmarkStatsFormat-8 3338 335822 ns/op 52832 B/op 4700 allocs/op Average of 5 runs; benchstat old.txt new.txt name old time/op new time/op delta StatsFormat-8 432µs ± 1% 344µs ± 5% -20.42% (p=0.008 n=5+5) name old alloc/op new alloc/op delta StatsFormat-8 62.4kB ± 0% 52.8kB ± 0% -15.38% (p=0.000 n=5+4) name old allocs/op new allocs/op delta StatsFormat-8 5.60k ± 0% 4.70k ± 0% -16.07% (p=0.008 n=5+5) Signed-off-by: Sebastiaan van Stijn --- cli/command/container/formatter_stats.go | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/cli/command/container/formatter_stats.go b/cli/command/container/formatter_stats.go index 4909405cf3..1b5055ea17 100644 --- a/cli/command/container/formatter_stats.go +++ b/cli/command/container/formatter_stats.go @@ -1,7 +1,7 @@ package container import ( - "fmt" + "strconv" "sync" "github.com/docker/cli/cli/command/formatter" @@ -183,7 +183,7 @@ func (c *statsContext) CPUPerc() string { if c.s.IsInvalid { return "--" } - return fmt.Sprintf("%.2f%%", c.s.CPUPercentage) + return formatPercentage(c.s.CPUPercentage) } func (c *statsContext) MemUsage() string { @@ -193,33 +193,37 @@ func (c *statsContext) MemUsage() string { if c.os == winOSType { return units.BytesSize(c.s.Memory) } - return fmt.Sprintf("%s / %s", units.BytesSize(c.s.Memory), units.BytesSize(c.s.MemoryLimit)) + return units.BytesSize(c.s.Memory) + " / " + units.BytesSize(c.s.MemoryLimit) } func (c *statsContext) MemPerc() string { if c.s.IsInvalid || c.os == winOSType { return "--" } - return fmt.Sprintf("%.2f%%", c.s.MemoryPercentage) + return formatPercentage(c.s.MemoryPercentage) } func (c *statsContext) NetIO() string { if c.s.IsInvalid { return "--" } - return fmt.Sprintf("%s / %s", units.HumanSizeWithPrecision(c.s.NetworkRx, 3), units.HumanSizeWithPrecision(c.s.NetworkTx, 3)) + return units.HumanSizeWithPrecision(c.s.NetworkRx, 3) + " / " + units.HumanSizeWithPrecision(c.s.NetworkTx, 3) } func (c *statsContext) BlockIO() string { if c.s.IsInvalid { return "--" } - return fmt.Sprintf("%s / %s", units.HumanSizeWithPrecision(c.s.BlockRead, 3), units.HumanSizeWithPrecision(c.s.BlockWrite, 3)) + return units.HumanSizeWithPrecision(c.s.BlockRead, 3) + " / " + units.HumanSizeWithPrecision(c.s.BlockWrite, 3) } func (c *statsContext) PIDs() string { if c.s.IsInvalid || c.os == winOSType { return "--" } - return fmt.Sprintf("%d", c.s.PidsCurrent) + return strconv.FormatUint(c.s.PidsCurrent, 10) +} + +func formatPercentage(val float64) string { + return strconv.FormatFloat(val, 'f', 2, 64) + "%" }