From 75576ef8dd88ce9b144c874308f494ef93fb04a3 Mon Sep 17 00:00:00 2001 From: Alex Aizman Date: Thu, 23 Jan 2025 09:40:12 -0500 Subject: [PATCH] CLI 'performance throughput': fix cluster totals Signed-off-by: Alex Aizman --- cmd/cli/cli/daeclu.go | 5 +++-- cmd/cli/cli/performance.go | 30 +++++++++++++++++++++--------- stats/api.go | 17 +++++++++++++++-- stats/common.go | 2 +- 4 files changed, 40 insertions(+), 14 deletions(-) diff --git a/cmd/cli/cli/daeclu.go b/cmd/cli/cli/daeclu.go index 58bda43b947..010c07bfd5e 100644 --- a/cmd/cli/cli/daeclu.go +++ b/cmd/cli/cli/daeclu.go @@ -104,8 +104,9 @@ outer: avail += int64(cdf.Avail) num += len(cdf.Disks) - // TODO: a simplifying local-playground assumption and shortcut - won't work with loop devices, etc. - // (ref: 152408) + // [TODO] + // - simplifying local-playground assumption and shortcut - won't work with loop devices, etc. + // - ref: 152408 if ds.DeploymentType == apc.DeploymentDev { break outer } diff --git a/cmd/cli/cli/performance.go b/cmd/cli/cli/performance.go index 821a866a46a..8e301532256 100644 --- a/cmd/cli/cli/performance.go +++ b/cmd/cli/cli/performance.go @@ -169,12 +169,12 @@ func showCountersHandler(c *cli.Context) error { selected[name] = kind } } - return showPerfTab(c, selected, nil, cmdShowCounters, nil, false) + return showPerfTab(c, selected, nil, cmdShowCounters, nil /*totals*/, false) } func showThroughputHandler(c *cli.Context) error { var ( - totals = make(map[string]int64, 4) // throughput metrics ("columns") to tally up + totals = make(map[string]int64, 12) // throughput metrics ("columns") to tally up verbose = flagIsSet(c, verboseFlag) metrics, err = getMetricNames(c) ) @@ -223,6 +223,7 @@ func showThroughputHandler(c *cli.Context) error { if bpsName := stats.SizeToThroughput(name, stats.KindSize); bpsName != "" { selected[bpsName] = stats.KindThroughput + totals[bpsName] = 0 } } } @@ -231,6 +232,11 @@ func showThroughputHandler(c *cli.Context) error { return showPerfTab(c, selected, _throughput /*cb*/, cmdShowThroughput, totals, true) } +// TODO -- FIXME: move +func _sizeToCount(name string) string { + return strings.TrimSuffix(name, ".size") + ".n" +} + // update mapBegin <= (size/s) func _throughput(c *cli.Context, metrics cos.StrKVs, mapBegin, mapEnd teb.StstMap, elapsed time.Duration) (idle bool) { var ( @@ -253,18 +259,24 @@ func _throughput(c *cli.Context, metrics cos.StrKVs, mapBegin, mapEnd teb.StstMa if bpsName == "" { continue } - vend := end.Tracker[name] - if vend.Value <= v.Value { - // no changes, nothing to show + // - check (begin, end) counters + // - zero-out resulting throughput when no change + var ( + cntName = _sizeToCount(name) + cntBegin, okb = begin.Tracker[cntName] + cntEnd, oke = end.Tracker[cntName] + ) + if okb && oke && cntBegin.Value >= cntEnd.Value { v.Value = 0 - begin.Tracker[name] = v + begin.Tracker[bpsName] = v continue } // // given this (KindSize) metric change and elapsed time, add computed throughput: // + vend := end.Tracker[name] v.Value = (vend.Value - v.Value) / seconds begin.Tracker[bpsName] = v num++ @@ -334,7 +346,7 @@ func showLatencyHandler(c *cli.Context) error { } // `true` to show (and put request latency numbers in perspective) - return showPerfTab(c, selected, _latency, cmdShowLatency, nil, true) + return showPerfTab(c, selected, _latency, cmdShowLatency, nil /*totals*/, true) } // update mapBegin <= (elapsed/num-samples) @@ -499,12 +511,12 @@ func showPerfTab(c *cli.Context, metrics cos.StrKVs, cb perfcb, tag string, tota totalsHdr := teb.ClusterTotal if totals != nil { for _, begin := range mapBegin { + _ = begin.DeploymentType for name, v := range begin.Tracker { if _, ok := totals[name]; ok { - totals[name] += v.Value + totals[name] += v.Value // (each target separately reporting; compare ref 152408) } } - // TODO: avoid summing up with oneself - check Tcdf mountpaths } } diff --git a/stats/api.go b/stats/api.go index ebb2c0e0820..8505152eb4b 100644 --- a/stats/api.go +++ b/stats/api.go @@ -157,7 +157,7 @@ func IsIOErrMetric(name string) bool { // // name translations, to recompute latency and throughput over client-controlled intervals -// see "Naming conventions" +// see stats/common for "Naming conventions" // // compare with base.init() at ais/backend/common @@ -196,13 +196,26 @@ func LatencyToCounter(latName string) string { return "" } +// TODO -- FIXME: remove func SizeToThroughput(name, kind string) string { if kind != KindSize { return "" } - if !strings.HasSuffix(name, ".size") { // see "Naming conventions" + if !strings.HasSuffix(name, ".size") { // see stats/common for "Naming conventions" debug.Assert(false, name) return "" } return strings.TrimSuffix(name, ".size") + ".bps" } + +func SizeToThroughputCount(name, kind string) (string, string) { + if kind != KindSize { + return "", "" + } + if !strings.HasSuffix(name, ".size") { // see stats/common for "Naming conventions" + debug.Assert(false, name) + return "", "" + } + root := strings.TrimSuffix(name, ".size") + return root + ".bps", root + ".n" +} diff --git a/stats/common.go b/stats/common.go index eb7738813da..49c4a369fae 100644 --- a/stats/common.go +++ b/stats/common.go @@ -67,7 +67,7 @@ const ( lshiftGorHigh = 8 // max expressed as left shift of the num CPUs ) -// [naming convention] error counter prefixes +// Naming conventions: error counters' prefixes const ( errPrefix = "err." // all error metric names (see `IsErrMetric` below) ioErrPrefix = "err.io." // excluding connection-reset-by-peer and similar (see ioErrNames)