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

perf metricgroup: Scale the metric result

Some metrics define the scale unit, such as

{
"BriefDescription": "Intel Optane DC persistent memory read latency (ns). Derived from unc_m_pmm_rpq_occupancy.all",
"Counter": "0,1,2,3",
"EventCode": "0xE0",
"EventName": "UNC_M_PMM_READ_LATENCY",
"MetricExpr": "UNC_M_PMM_RPQ_OCCUPANCY.ALL / UNC_M_PMM_RPQ_INSERTS / UNC_M_CLOCKTICKS",
"MetricName": "UNC_M_PMM_READ_LATENCY",
"PerPkg": "1",
"ScaleUnit": "6000000000ns",
"UMask": "0x1",
"Unit": "iMC"
},

For above example, the ratio should be,

ratio = (UNC_M_PMM_RPQ_OCCUPANCY.ALL / UNC_M_PMM_RPQ_INSERTS / UNC_M_CLOCKTICKS) * 6000000000

But in current code, the ratio is not scaled ( * 6000000000)

With this patch, the ratio is scaled and the unit (ns) is printed.

For example,
# 219.4 ns UNC_M_PMM_READ_LATENCY

Signed-off-by: Jin Yao <yao.jin@linux.intel.com>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: Andi Kleen <ak@linux.intel.com>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Kan Liang <kan.liang@linux.intel.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Link: http://lore.kernel.org/lkml/20190828055932.8269-4-yao.jin@linux.intel.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>

authored by

Jin Yao and committed by
Arnaldo Carvalho de Melo
287f2649 a55ab7c4

+31 -11
+3
tools/perf/util/metricgroup.c
··· 87 87 const char **ids; 88 88 const char *metric_name; 89 89 const char *metric_expr; 90 + const char *metric_unit; 90 91 }; 91 92 92 93 static bool record_evsel(int *ind, struct evsel **start, ··· 183 182 } 184 183 expr->metric_expr = eg->metric_expr; 185 184 expr->metric_name = eg->metric_name; 185 + expr->metric_unit = eg->metric_unit; 186 186 expr->metric_events = metric_events; 187 187 list_add(&expr->nd, &me->head); 188 188 } ··· 455 453 eg->idnum = idnum; 456 454 eg->metric_name = pe->metric_name; 457 455 eg->metric_expr = pe->metric_expr; 456 + eg->metric_unit = pe->unit; 458 457 list_add_tail(&eg->nd, group_list); 459 458 ret = 0; 460 459 }
+1
tools/perf/util/metricgroup.h
··· 20 20 struct list_head nd; 21 21 const char *metric_expr; 22 22 const char *metric_name; 23 + const char *metric_unit; 23 24 struct evsel **metric_events; 24 25 }; 25 26
+27 -11
tools/perf/util/stat-shadow.c
··· 715 715 struct evsel **metric_events, 716 716 char *name, 717 717 const char *metric_name, 718 + const char *metric_unit, 718 719 double avg, 719 720 int cpu, 720 721 struct perf_stat_output_ctx *out, ··· 723 722 { 724 723 print_metric_t print_metric = out->print_metric; 725 724 struct parse_ctx pctx; 726 - double ratio; 725 + double ratio, scale; 727 726 int i; 728 727 void *ctxp = out->ctx; 729 728 char *n, *pn; ··· 733 732 for (i = 0; metric_events[i]; i++) { 734 733 struct saved_value *v; 735 734 struct stats *stats; 736 - double scale; 737 735 738 736 if (!strcmp(metric_events[i]->name, "duration_time")) { 739 737 stats = &walltime_nsecs_stats; ··· 762 762 if (!metric_events[i]) { 763 763 const char *p = metric_expr; 764 764 765 - if (expr__parse(&ratio, &pctx, &p) == 0) 766 - print_metric(config, ctxp, NULL, "%8.1f", 767 - metric_name ? 768 - metric_name : 769 - out->force_header ? name : "", 770 - ratio); 771 - else 765 + if (expr__parse(&ratio, &pctx, &p) == 0) { 766 + char *unit; 767 + char metric_bf[64]; 768 + 769 + if (metric_unit && metric_name) { 770 + if (perf_pmu__convert_scale(metric_unit, 771 + &unit, &scale) >= 0) { 772 + ratio *= scale; 773 + } 774 + 775 + scnprintf(metric_bf, sizeof(metric_bf), 776 + "%s %s", unit, metric_name); 777 + print_metric(config, ctxp, NULL, "%8.1f", 778 + metric_bf, ratio); 779 + } else { 780 + print_metric(config, ctxp, NULL, "%8.1f", 781 + metric_name ? 782 + metric_name : 783 + out->force_header ? name : "", 784 + ratio); 785 + } 786 + } else { 772 787 print_metric(config, ctxp, NULL, NULL, 773 788 out->force_header ? 774 789 (metric_name ? metric_name : name) : "", 0); 790 + } 775 791 } else 776 792 print_metric(config, ctxp, NULL, NULL, "", 0); 777 793 ··· 1008 992 print_metric(config, ctxp, NULL, NULL, name, 0); 1009 993 } else if (evsel->metric_expr) { 1010 994 generic_metric(config, evsel->metric_expr, evsel->metric_events, evsel->name, 1011 - evsel->metric_name, avg, cpu, out, st); 995 + evsel->metric_name, NULL, avg, cpu, out, st); 1012 996 } else if (runtime_stat_n(st, STAT_NSECS, 0, cpu) != 0) { 1013 997 char unit = 'M'; 1014 998 char unit_buf[10]; ··· 1037 1021 out->new_line(config, ctxp); 1038 1022 generic_metric(config, mexp->metric_expr, mexp->metric_events, 1039 1023 evsel->name, mexp->metric_name, 1040 - avg, cpu, out, st); 1024 + mexp->metric_unit, avg, cpu, out, st); 1041 1025 } 1042 1026 } 1043 1027 if (num == 0)