Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

perf test: Hybrid improvements for metric value validation test

On my alderlake I currently see for the "perf metrics value validation" test:

```
Total Test Count: 142
Passed Test Count: 139
[
Metric Relationship Error: The collected value of metric ['tma_fetch_latency', 'tma_fetch_bandwidth', 'tma_frontend_bound']
is [31.137028] in workload(s): ['perf bench futex hash -r 2 -s']
but expected value range is [tma_frontend_bound, tma_frontend_bound]
Relationship rule description: 'Sum of the level 2 children should equal level 1 parent',
Metric Relationship Error: The collected value of metric ['tma_memory_bound', 'tma_core_bound', 'tma_backend_bound']
is [6.564442] in workload(s): ['perf bench futex hash -r 2 -s']
but expected value range is [tma_backend_bound, tma_backend_bound]
Relationship rule description: 'Sum of the level 2 children should equal level 1 parent',
Metric Relationship Error: The collected value of metric ['tma_light_operations', 'tma_heavy_operations', 'tma_retiring']
is [57.806179] in workload(s): ['perf bench futex hash -r 2 -s']
but expected value range is [tma_retiring, tma_retiring]
Relationship rule description: 'Sum of the level 2 children should equal level 1 parent']
Metric validation return with erros. Please check metrics reported with errors.
```

I suspect it is due to two metrics for different CPU types being
enabled. Add a -cputype option to avoid this. The test still fails with:

```
Total Test Count: 115
Passed Test Count: 114
[
Wrong Metric Value Error: The collected value of metric ['tma_l2_hit_latency']
is [117.947088] in workload(s): ['perf bench futex hash -r 2 -s']
but expected value range is [0, 100]]
Metric validation return with errors. Please check metrics reported with errors.
```

which is a reproducible genuine error and likely requires a metric fix.

Signed-off-by: Ian Rogers <irogers@google.com>
Tested-by: Thomas Falcon <thomas.falcon@intel.com>
Cc: Adrian Hunter <adrian.hunter@intel.com>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: James Clark <james.clark@linaro.org>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Kan Liang <kan.liang@linux.intel.com>
Cc: Mark Rutland <mark.rutland@arm.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Weilin Wang <weilin.wang@intel.com>
Link: https://lore.kernel.org/r/20250512184700.11691-2-irogers@google.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>

authored by

Ian Rogers and committed by
Arnaldo Carvalho de Melo
3eb5c49f 7f84f674

+20 -9
+9 -3
tools/perf/tests/shell/lib/perf_metric_validation.py
··· 35 35 36 36 37 37 class Validator: 38 - def __init__(self, rulefname, reportfname='', t=5, debug=False, datafname='', fullrulefname='', workload='true', metrics=''): 38 + def __init__(self, rulefname, reportfname='', t=5, debug=False, datafname='', fullrulefname='', 39 + workload='true', metrics='', cputype='cpu'): 39 40 self.rulefname = rulefname 40 41 self.reportfname = reportfname 41 42 self.rules = None ··· 44 43 self.metrics = self.__set_metrics(metrics) 45 44 self.skiplist = set() 46 45 self.tolerance = t 46 + self.cputype = cputype 47 47 48 48 self.workloads = [x for x in workload.split(",") if x] 49 49 self.wlidx = 0 # idx of current workloads ··· 379 377 380 378 def _run_perf(self, metric, workload: str): 381 379 tool = 'perf' 382 - command = [tool, 'stat', '-j', '-M', f"{metric}", "-a"] 380 + command = [tool, 'stat', '--cputype', self.cputype, '-j', '-M', f"{metric}", "-a"] 383 381 wl = workload.split() 384 382 command.extend(wl) 385 383 print(" ".join(command)) ··· 444 442 for m in data: 445 443 if 'MetricName' not in m: 446 444 print("Warning: no metric name") 445 + continue 446 + if 'Unit' in m and m['Unit'] != self.cputype: 447 447 continue 448 448 name = m['MetricName'].lower() 449 449 self.metrics.add(name) ··· 582 578 parser.add_argument( 583 579 "-wl", help="Workload to run while data collection", default="true") 584 580 parser.add_argument("-m", help="Metric list to validate", default="") 581 + parser.add_argument("-cputype", help="Only test metrics for the given CPU/PMU type", 582 + default="cpu") 585 583 args = parser.parse_args() 586 584 outpath = Path(args.output_dir) 587 585 reportf = Path.joinpath(outpath, 'perf_report.json') ··· 592 586 593 587 validator = Validator(args.rule, reportf, debug=args.debug, 594 588 datafname=datafile, fullrulefname=fullrule, workload=args.wl, 595 - metrics=args.m) 589 + metrics=args.m, cputype=args.cputype) 596 590 ret = validator.test() 597 591 598 592 return ret
+11 -6
tools/perf/tests/shell/stat_metrics_values.sh
··· 16 16 # Add -debug, save data file and full rule file 17 17 echo "Launch python validation script $pythonvalidator" 18 18 echo "Output will be stored in: $tmpdir" 19 - $PYTHON $pythonvalidator -rule $rulefile -output_dir $tmpdir -wl "${workload}" 20 - ret=$? 21 - rm -rf $tmpdir 22 - if [ $ret -ne 0 ]; then 23 - echo "Metric validation return with erros. Please check metrics reported with errors." 24 - fi 19 + for cputype in /sys/bus/event_source/devices/cpu_*; do 20 + cputype=$(basename "$cputype") 21 + echo "Testing metrics for: $cputype" 22 + $PYTHON $pythonvalidator -rule $rulefile -output_dir $tmpdir -wl "${workload}" \ 23 + -cputype "${cputype}" 24 + ret=$? 25 + rm -rf $tmpdir 26 + if [ $ret -ne 0 ]; then 27 + echo "Metric validation return with errors. Please check metrics reported with errors." 28 + fi 29 + done 25 30 exit $ret 26 31