From nobody Thu Dec 18 22:15:26 2025 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 7B576C77B75 for ; Tue, 2 May 2023 22:39:20 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229915AbjEBWjT (ORCPT ); Tue, 2 May 2023 18:39:19 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:55326 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229911AbjEBWjQ (ORCPT ); Tue, 2 May 2023 18:39:16 -0400 Received: from mail-pl1-x649.google.com (mail-pl1-x649.google.com [IPv6:2607:f8b0:4864:20::649]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id A27F12D74 for ; Tue, 2 May 2023 15:39:14 -0700 (PDT) Received: by mail-pl1-x649.google.com with SMTP id d9443c01a7336-1ab07423559so9575915ad.3 for ; Tue, 02 May 2023 15:39:14 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20221208; t=1683067154; x=1685659154; h=cc:to:from:subject:references:mime-version:message-id:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=h10TGNBRB+swYQLldhqIixkznDBQsILm/HEqOr0YFfQ=; b=yYeNw6rrDXtRTtstKxgcQ/8z/3UzTNAFcKVoOAyBjspBXMBO0280ONt3OEZQqCcqjn Uwz14ZbYkRZ8poP7bXJm/CQtUujNMn0OQ3hQS4OPRhGIVV0kKDMNTF2IybxRnraKTv4N i/VWPPJaKm8JaWLKANQMq3foxEYe11qfksY81IxJrTwSXT/FN6JZffVFUa+Acwg95bva VQpdyjMTNTkRCowm1pbWH2ay14pPe974KC0ZNstH45sYtJjLIBZoDIOh0A4hnPtZzmlL lREJuzVfQQt6j0+JJn9/5P3WH/TbbWwUTcYK54VpD9pNbXJTAQFwo293BzYxwMF7kscE MBeg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1683067154; x=1685659154; h=cc:to:from:subject:references:mime-version:message-id:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=h10TGNBRB+swYQLldhqIixkznDBQsILm/HEqOr0YFfQ=; b=VZ3FVkJ9HojUIUclHVr808Z7JEJ3NKg13oCPDzJxp/NokMqXg4qO8DEBLlk7w6wUE3 xNZSkUJWPKur5Y22gDfZ5gnhoiCRsGq9DRn0yXZklH7GlDh1jN5OWE4x7ii8/BUnRMMX v+xJPE5mMDPmsWB1S4FXkoYOfQH0zEil6Nrmb68fdO2+oUOpCTs5+D/4VR56/yosj2om awMrUliswnhWhCDPK1UMncpJbQqGacrNbOmlzNplf/DtRx6j6NNkmCLoRarLicUNgoaS QC5SYkiUQMbbDceH1fZCtoj9TYqDtEQIRH+g3i0E7deLr7xt8yCaN44PJ2pgQNPYobAV pqPg== X-Gm-Message-State: AC+VfDyuxSfDBuNE5LIsSzgo8+P0BUMEyw6daHM1kowluTrfvBBASYhe uTh1XyOXxmY7KnKF+8JUa8G0XjlwDgpe X-Google-Smtp-Source: ACHHUZ47hifw5kvjgdhe0rDUe3579g8BZgsdKW6Wmz2s+UmPoufmfiO1wLZGgHZDvdlaI0qZZVy319SeCR1h X-Received: from irogers.svl.corp.google.com ([2620:15c:2d4:203:e70c:446b:d23b:982e]) (user=irogers job=sendgmr) by 2002:a17:903:492:b0:1a2:8940:6db0 with SMTP id jj18-20020a170903049200b001a289406db0mr11798plb.13.1683067154077; Tue, 02 May 2023 15:39:14 -0700 (PDT) Date: Tue, 2 May 2023 15:38:08 -0700 In-Reply-To: <20230502223851.2234828-1-irogers@google.com> Message-Id: <20230502223851.2234828-2-irogers@google.com> Mime-Version: 1.0 References: <20230502223851.2234828-1-irogers@google.com> X-Mailer: git-send-email 2.40.1.495.gc816e09b53d-goog Subject: [PATCH v4 01/44] perf metric: Change divide by zero and !support events behavior From: Ian Rogers To: Arnaldo Carvalho de Melo , Kan Liang , Ahmad Yasin , Peter Zijlstra , Ingo Molnar , Stephane Eranian , Andi Kleen , Perry Taylor , Samantha Alt , Caleb Biggers , Weilin Wang , Edward Baker , Mark Rutland , Alexander Shishkin , Jiri Olsa , Namhyung Kim , Adrian Hunter , Florian Fischer , Rob Herring , Zhengjun Xing , John Garry , Kajol Jain , Sumanth Korikkar , Thomas Richter , Tiezhu Yang , Ravi Bangoria , Leo Yan , Yang Jihong , James Clark , Suzuki Poulouse , Kang Minchul , Athira Rajeev , linux-perf-users@vger.kernel.org, linux-kernel@vger.kernel.org Cc: Ian Rogers Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" 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_o= perations # nan % tma_light_o= perations 29,304 CPU_CLK_UNHALTED.REF_XCLK # nan % tma_= fetch_latency # nan % tma_branch_= mispredicts # nan % tma_machine= _clears # nan % tma_core_bo= und # 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 BR_MISP_RETIRED.ALL_BRANCHES = (0.00%) INT_MISC.RECOVERY_CYCLES_ANY = (0.00%) CPU_CLK_UNHALTED.ONE_THREAD_ACTIVE = (0.00%) CPU_CLK_UNHALTED.THREAD = (0.00%) UOPS_RETIRED.RETIRE_SLOTS = (0.00%) CYCLE_ACTIVITY.STALLS_MEM_ANY = (0.00%) UOPS_RETIRED.MACRO_FUSED = (0.00%) IDQ_UOPS_NOT_DELIVERED.CYCLES_0_UOPS_DELIV.CORE = (0.00%) EXE_ACTIVITY.2_PORTS_UTIL = (0.00%) CYCLE_ACTIVITY.STALLS_TOTAL = (0.00%) MACHINE_CLEARS.COUNT = (0.00%) 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 ut= ilized 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 pe= r 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_fronten= d_bound # nan % tma_retiring # nan % tma_backend= _bound # nan % tma_bad_spe= culation 344,855 IDQ_UOPS_NOT_DELIVERED.CORE:u # 275.147 M/sec INT_MISC.RECOVERY_CYCLES_ANY:u CPU_CLK_UNHALTED.ONE_THREAD_ACTIVE:u = (0.00%) CPU_CLK_UNHALTED.THREAD:u = (0.00%) UOPS_RETIRED.RETIRE_SLOTS:u = (0.00%) 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 Tested-by: Kan Liang --- tools/perf/tests/expr.c | 3 ++- tools/perf/tests/parse-metric.c | 1 + tools/perf/util/expr.y | 6 +++++- tools/perf/util/stat-display.c | 2 +- tools/perf/util/stat-shadow.c | 25 +++++++++++++++++++------ 5 files changed, 28 insertions(+), 9 deletions(-) diff --git a/tools/perf/tests/expr.c b/tools/perf/tests/expr.c index cbf0e0c74906..733ead151c63 100644 --- a/tools/perf/tests/expr.c +++ b/tools/perf/tests/expr.c @@ -120,7 +120,8 @@ static int test__expr(struct test_suite *t __maybe_unus= ed, int subtest __maybe_u =20 p =3D "FOO/0"; ret =3D expr__parse(&val, ctx, p); - TEST_ASSERT_VAL("division by zero", ret =3D=3D -1); + TEST_ASSERT_VAL("division by zero", ret =3D=3D 0); + TEST_ASSERT_VAL("division by zero", isnan(val)); =20 p =3D "BAR/"; ret =3D expr__parse(&val, ctx, p); diff --git a/tools/perf/tests/parse-metric.c b/tools/perf/tests/parse-metri= c.c index 1185b79e6274..c05148ea400c 100644 --- a/tools/perf/tests/parse-metric.c +++ b/tools/perf/tests/parse-metric.c @@ -38,6 +38,7 @@ static void load_runtime_stat(struct evlist *evlist, stru= ct value *vals) evlist__alloc_aggr_stats(evlist, 1); evlist__for_each_entry(evlist, evsel) { count =3D find_value(evsel->name, vals); + evsel->supported =3D true; evsel->stats->aggr->counts.val =3D count; if (evsel__name_is(evsel, "duration_time")) update_stats(&walltime_nsecs_stats, count); diff --git a/tools/perf/util/expr.y b/tools/perf/util/expr.y index 250e444bf032..4ce931cccb63 100644 --- a/tools/perf/util/expr.y +++ b/tools/perf/util/expr.y @@ -225,7 +225,11 @@ expr: NUMBER { if (fpclassify($3.val) =3D=3D FP_ZERO) { pr_debug("division by zero\n"); - YYABORT; + assert($3.ids =3D=3D NULL); + if (compute_ids) + ids__free($1.ids); + $$.val =3D NAN; + $$.ids =3D NULL; } else if (!compute_ids || (is_const($1.val) && is_const($3.val))) { assert($1.ids =3D=3D NULL); assert($3.ids =3D=3D NULL); diff --git a/tools/perf/util/stat-display.c b/tools/perf/util/stat-display.c index 73b2ff2ddf29..bf5a6c14dfcd 100644 --- a/tools/perf/util/stat-display.c +++ b/tools/perf/util/stat-display.c @@ -431,7 +431,7 @@ static void print_metric_json(struct perf_stat_config *= config __maybe_unused, struct outstate *os =3D ctx; FILE *out =3D os->fh; =20 - fprintf(out, "\"metric-value\" : %f, ", val); + fprintf(out, "\"metric-value\" : \"%f\", ", val); fprintf(out, "\"metric-unit\" : \"%s\"", unit); if (!config->metric_only) fprintf(out, "}"); diff --git a/tools/perf/util/stat-shadow.c b/tools/perf/util/stat-shadow.c index eeccab6751d7..1566a206ba42 100644 --- a/tools/perf/util/stat-shadow.c +++ b/tools/perf/util/stat-shadow.c @@ -403,12 +403,25 @@ static int prepare_metric(struct evsel **metric_event= s, if (!aggr) break; =20 - /* - * If an event was scaled during stat gathering, reverse - * the scale before computing the metric. - */ - val =3D aggr->counts.val * (1.0 / metric_events[i]->scale); - source_count =3D 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 =3D NAN; + source_count =3D 0; + } else { + /* + * If an event was scaled during stat gathering, + * reverse the scale before computing the + * metric. + */ + val =3D aggr->counts.val * (1.0 / metric_events[i]->scale); + source_count =3D evsel__source_count(metric_events[i]); + } } n =3D strdup(evsel__metric_id(metric_events[i])); if (!n) --=20 2.40.1.495.gc816e09b53d-goog