Skip to content

Commit 2a939c8

Browse files
captain5050acmel
authored andcommitted
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 <[email protected]> Tested-by: Kan Liang <[email protected]> Cc: Adrian Hunter <[email protected]> Cc: Ahmad Yasin <[email protected]> Cc: Alexander Shishkin <[email protected]> Cc: Andi Kleen <[email protected]> Cc: Athira Rajeev <[email protected]> Cc: Caleb Biggers <[email protected]> Cc: Edward Baker <[email protected]> Cc: Florian Fischer <[email protected]> Cc: Ingo Molnar <[email protected]> Cc: James Clark <[email protected]> Cc: Jiri Olsa <[email protected]> Cc: John Garry <[email protected]> Cc: Kajol Jain <[email protected]> Cc: Kang Minchul <[email protected]> Cc: Leo Yan <[email protected]> Cc: Mark Rutland <[email protected]> Cc: Namhyung Kim <[email protected]> Cc: Perry Taylor <[email protected]> Cc: Peter Zijlstra <[email protected]> Cc: Ravi Bangoria <[email protected]> Cc: Rob Herring <[email protected]> Cc: Samantha Alt <[email protected]> Cc: Stephane Eranian <[email protected]> Cc: Sumanth Korikkar <[email protected]> Cc: Suzuki Poulouse <[email protected]> Cc: Thomas Richter <[email protected]> Cc: Tiezhu Yang <[email protected]> Cc: Weilin Wang <[email protected]> Cc: Xing Zhengjun <[email protected]> Cc: Yang Jihong <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
1 parent ad2fd53 commit 2a939c8

File tree

5 files changed

+28
-9
lines changed

5 files changed

+28
-9
lines changed

tools/perf/tests/expr.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,8 @@ static int test__expr(struct test_suite *t __maybe_unused, int subtest __maybe_u
120120

121121
p = "FOO/0";
122122
ret = expr__parse(&val, ctx, p);
123-
TEST_ASSERT_VAL("division by zero", ret == -1);
123+
TEST_ASSERT_VAL("division by zero", ret == 0);
124+
TEST_ASSERT_VAL("division by zero", isnan(val));
124125

125126
p = "BAR/";
126127
ret = expr__parse(&val, ctx, p);

tools/perf/tests/parse-metric.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ static void load_runtime_stat(struct evlist *evlist, struct value *vals)
3838
evlist__alloc_aggr_stats(evlist, 1);
3939
evlist__for_each_entry(evlist, evsel) {
4040
count = find_value(evsel->name, vals);
41+
evsel->supported = true;
4142
evsel->stats->aggr->counts.val = count;
4243
if (evsel__name_is(evsel, "duration_time"))
4344
update_stats(&walltime_nsecs_stats, count);

tools/perf/util/expr.y

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -225,7 +225,11 @@ expr: NUMBER
225225
{
226226
if (fpclassify($3.val) == FP_ZERO) {
227227
pr_debug("division by zero\n");
228-
YYABORT;
228+
assert($3.ids == NULL);
229+
if (compute_ids)
230+
ids__free($1.ids);
231+
$$.val = NAN;
232+
$$.ids = NULL;
229233
} else if (!compute_ids || (is_const($1.val) && is_const($3.val))) {
230234
assert($1.ids == NULL);
231235
assert($3.ids == NULL);

tools/perf/util/stat-display.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -431,7 +431,7 @@ static void print_metric_json(struct perf_stat_config *config __maybe_unused,
431431
struct outstate *os = ctx;
432432
FILE *out = os->fh;
433433

434-
fprintf(out, "\"metric-value\" : %f, ", val);
434+
fprintf(out, "\"metric-value\" : \"%f\", ", val);
435435
fprintf(out, "\"metric-unit\" : \"%s\"", unit);
436436
if (!config->metric_only)
437437
fprintf(out, "}");

tools/perf/util/stat-shadow.c

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -403,12 +403,25 @@ static int prepare_metric(struct evsel **metric_events,
403403
if (!aggr)
404404
break;
405405

406-
/*
407-
* If an event was scaled during stat gathering, reverse
408-
* the scale before computing the metric.
409-
*/
410-
val = aggr->counts.val * (1.0 / metric_events[i]->scale);
411-
source_count = evsel__source_count(metric_events[i]);
406+
if (!metric_events[i]->supported) {
407+
/*
408+
* Not supported events will have a count of 0,
409+
* which can be confusing in a
410+
* metric. Explicitly set the value to NAN. Not
411+
* counted events (enable time of 0) are read as
412+
* 0.
413+
*/
414+
val = NAN;
415+
source_count = 0;
416+
} else {
417+
/*
418+
* If an event was scaled during stat gathering,
419+
* reverse the scale before computing the
420+
* metric.
421+
*/
422+
val = aggr->counts.val * (1.0 / metric_events[i]->scale);
423+
source_count = evsel__source_count(metric_events[i]);
424+
}
412425
}
413426
n = strdup(evsel__metric_id(metric_events[i]));
414427
if (!n)

0 commit comments

Comments
 (0)