perf metric: Change divide by zero and !support events behavior
Division by zero causes expression parsing to fail and no metric to be generated. This can mean for short running benchmarks metrics are not shown. Change the behavior to make the value nan, which gets shown like: ''' $ perf stat -M TopdownL2 true Performance counter stats for 'true': 1,031,492 INST_RETIRED.ANY # nan % tma_fetch_bandwidth # nan % tma_heavy_operations # nan % tma_light_operations 29,304 CPU_CLK_UNHALTED.REF_XCLK # nan % tma_fetch_latency # nan % tma_branch_mispredicts # nan % tma_machine_clears # nan % tma_core_bound # nan % tma_memory_bound 2,658,319 IDQ_UOPS_NOT_DELIVERED.CORE 11,167 EXE_ACTIVITY.BOUND_ON_STORES 262,058 EXE_ACTIVITY.1_PORTS_UTIL <not counted> BR_MISP_RETIRED.ALL_BRANCHES (0.00%) <not counted> INT_MISC.RECOVERY_CYCLES_ANY (0.00%) <not counted> CPU_CLK_UNHALTED.ONE_THREAD_ACTIVE (0.00%) <not counted> CPU_CLK_UNHALTED.THREAD (0.00%) <not counted> UOPS_RETIRED.RETIRE_SLOTS (0.00%) <not counted> CYCLE_ACTIVITY.STALLS_MEM_ANY (0.00%) <not counted> UOPS_RETIRED.MACRO_FUSED (0.00%) <not counted> IDQ_UOPS_NOT_DELIVERED.CYCLES_0_UOPS_DELIV.CORE (0.00%) <not counted> EXE_ACTIVITY.2_PORTS_UTIL (0.00%) <not counted> CYCLE_ACTIVITY.STALLS_TOTAL (0.00%) <not counted> MACHINE_CLEARS.COUNT (0.00%) <not counted> UOPS_ISSUED.ANY (0.00%) 0.002864879 seconds time elapsed 0.003012000 seconds user 0.000000000 seconds sys ''' When events aren't supported a count of 0 can be confusing and make metrics look meaningful. Change these to be nan also which, with the next change, gets shown like: ''' $ perf stat true Performance counter stats for 'true': 1.25 msec task-clock:u # 0.387 CPUs utilized 0 context-switches:u # 0.000 /sec 0 cpu-migrations:u # 0.000 /sec 46 page-faults:u # 36.702 K/sec 255,942 cycles:u # 0.204 GHz (88.66%) 123,046 instructions:u # 0.48 insn per cycle 28,301 branches:u # 22.580 M/sec 2,489 branch-misses:u # 8.79% of all branches 4,719 CPU_CLK_UNHALTED.REF_XCLK:u # 3.765 M/sec # nan % tma_frontend_bound # nan % tma_retiring # nan % tma_backend_bound # nan % tma_bad_speculation 344,855 IDQ_UOPS_NOT_DELIVERED.CORE:u # 275.147 M/sec <not supported> INT_MISC.RECOVERY_CYCLES_ANY:u <not counted> CPU_CLK_UNHALTED.ONE_THREAD_ACTIVE:u (0.00%) <not counted> CPU_CLK_UNHALTED.THREAD:u (0.00%) <not counted> UOPS_RETIRED.RETIRE_SLOTS:u (0.00%) <not counted> UOPS_ISSUED.ANY:u (0.00%) 0.003238142 seconds time elapsed 0.000000000 seconds user 0.003434000 seconds sys ''' Ensure that nan metric values are quoted as nan isn't a valid number in JSON. Signed-off-by: Ian Rogers <irogers@google.com> Tested-by: Kan Liang <kan.liang@linux.intel.com> Cc: Adrian Hunter <adrian.hunter@intel.com> Cc: Ahmad Yasin <ahmad.yasin@intel.com> Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com> Cc: Andi Kleen <ak@linux.intel.com> Cc: Athira Rajeev <atrajeev@linux.vnet.ibm.com> Cc: Caleb Biggers <caleb.biggers@intel.com> Cc: Edward Baker <edward.baker@intel.com> Cc: Florian Fischer <florian.fischer@muhq.space> Cc: Ingo Molnar <mingo@redhat.com> Cc: James Clark <james.clark@arm.com> Cc: Jiri Olsa <jolsa@kernel.org> Cc: John Garry <john.g.garry@oracle.com> Cc: Kajol Jain <kjain@linux.ibm.com> Cc: Kang Minchul <tegongkang@gmail.com> Cc: Leo Yan <leo.yan@linaro.org> Cc: Mark Rutland <mark.rutland@arm.com> Cc: Namhyung Kim <namhyung@kernel.org> Cc: Perry Taylor <perry.taylor@intel.com> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Ravi Bangoria <ravi.bangoria@amd.com> Cc: Rob Herring <robh@kernel.org> Cc: Samantha Alt <samantha.alt@intel.com> Cc: Stephane Eranian <eranian@google.com> Cc: Sumanth Korikkar <sumanthk@linux.ibm.com> Cc: Suzuki Poulouse <suzuki.poulose@arm.com> Cc: Thomas Richter <tmricht@linux.ibm.com> Cc: Tiezhu Yang <yangtiezhu@loongson.cn> Cc: Weilin Wang <weilin.wang@intel.com> Cc: Xing Zhengjun <zhengjun.xing@linux.intel.com> Cc: Yang Jihong <yangjihong1@huawei.com> Link: https://lore.kernel.org/r/20230502223851.2234828-2-irogers@google.com Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
This commit is contained in:
Родитель
ad2fd53a78
Коммит
2a939c8695
|
@ -120,7 +120,8 @@ static int test__expr(struct test_suite *t __maybe_unused, int subtest __maybe_u
|
|||
|
||||
p = "FOO/0";
|
||||
ret = expr__parse(&val, ctx, p);
|
||||
TEST_ASSERT_VAL("division by zero", ret == -1);
|
||||
TEST_ASSERT_VAL("division by zero", ret == 0);
|
||||
TEST_ASSERT_VAL("division by zero", isnan(val));
|
||||
|
||||
p = "BAR/";
|
||||
ret = expr__parse(&val, ctx, p);
|
||||
|
|
|
@ -38,6 +38,7 @@ static void load_runtime_stat(struct evlist *evlist, struct value *vals)
|
|||
evlist__alloc_aggr_stats(evlist, 1);
|
||||
evlist__for_each_entry(evlist, evsel) {
|
||||
count = find_value(evsel->name, vals);
|
||||
evsel->supported = true;
|
||||
evsel->stats->aggr->counts.val = count;
|
||||
if (evsel__name_is(evsel, "duration_time"))
|
||||
update_stats(&walltime_nsecs_stats, count);
|
||||
|
|
|
@ -225,7 +225,11 @@ expr: NUMBER
|
|||
{
|
||||
if (fpclassify($3.val) == FP_ZERO) {
|
||||
pr_debug("division by zero\n");
|
||||
YYABORT;
|
||||
assert($3.ids == NULL);
|
||||
if (compute_ids)
|
||||
ids__free($1.ids);
|
||||
$$.val = NAN;
|
||||
$$.ids = NULL;
|
||||
} else if (!compute_ids || (is_const($1.val) && is_const($3.val))) {
|
||||
assert($1.ids == NULL);
|
||||
assert($3.ids == NULL);
|
||||
|
|
|
@ -431,7 +431,7 @@ static void print_metric_json(struct perf_stat_config *config __maybe_unused,
|
|||
struct outstate *os = ctx;
|
||||
FILE *out = os->fh;
|
||||
|
||||
fprintf(out, "\"metric-value\" : %f, ", val);
|
||||
fprintf(out, "\"metric-value\" : \"%f\", ", val);
|
||||
fprintf(out, "\"metric-unit\" : \"%s\"", unit);
|
||||
if (!config->metric_only)
|
||||
fprintf(out, "}");
|
||||
|
|
|
@ -403,12 +403,25 @@ static int prepare_metric(struct evsel **metric_events,
|
|||
if (!aggr)
|
||||
break;
|
||||
|
||||
/*
|
||||
* If an event was scaled during stat gathering, reverse
|
||||
* the scale before computing the metric.
|
||||
*/
|
||||
val = aggr->counts.val * (1.0 / metric_events[i]->scale);
|
||||
source_count = evsel__source_count(metric_events[i]);
|
||||
if (!metric_events[i]->supported) {
|
||||
/*
|
||||
* Not supported events will have a count of 0,
|
||||
* which can be confusing in a
|
||||
* metric. Explicitly set the value to NAN. Not
|
||||
* counted events (enable time of 0) are read as
|
||||
* 0.
|
||||
*/
|
||||
val = NAN;
|
||||
source_count = 0;
|
||||
} else {
|
||||
/*
|
||||
* If an event was scaled during stat gathering,
|
||||
* reverse the scale before computing the
|
||||
* metric.
|
||||
*/
|
||||
val = aggr->counts.val * (1.0 / metric_events[i]->scale);
|
||||
source_count = evsel__source_count(metric_events[i]);
|
||||
}
|
||||
}
|
||||
n = strdup(evsel__metric_id(metric_events[i]));
|
||||
if (!n)
|
||||
|
|
Загрузка…
Ссылка в новой задаче