lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [day] [month] [year] [list]
Message-ID: <CAP-5=fWDbpKzwSOo0rCHNLa6hBDjG4wMO3MKQt3wUQzVaVj6jA@mail.gmail.com>
Date: Wed, 3 Sep 2025 08:56:45 -0700
From: Ian Rogers <irogers@...gle.com>
To: Arnaldo Carvalho de Melo <acme@...nel.org>
Cc: Peter Zijlstra <peterz@...radead.org>, Ingo Molnar <mingo@...hat.com>, 
	Namhyung Kim <namhyung@...nel.org>, Mark Rutland <mark.rutland@....com>, 
	Alexander Shishkin <alexander.shishkin@...ux.intel.com>, Jiri Olsa <jolsa@...nel.org>, 
	Adrian Hunter <adrian.hunter@...el.com>, Kan Liang <kan.liang@...ux.intel.com>, 
	James Clark <james.clark@...aro.org>, Xu Yang <xu.yang_2@....com>, 
	"Masami Hiramatsu (Google)" <mhiramat@...nel.org>, Collin Funk <collin.funk1@...il.com>, 
	Howard Chu <howardchu95@...il.com>, Weilin Wang <weilin.wang@...el.com>, 
	Andi Kleen <ak@...ux.intel.com>, "Dr. David Alan Gilbert" <linux@...blig.org>, 
	Thomas Richter <tmricht@...ux.ibm.com>, Tiezhu Yang <yangtiezhu@...ngson.cn>, 
	Gautam Menghani <gautam@...ux.ibm.com>, Thomas Falcon <thomas.falcon@...el.com>, 
	Chun-Tse Shao <ctshao@...gle.com>, linux-kernel@...r.kernel.org, 
	linux-perf-users@...r.kernel.org, Arnaldo Carvalho de Melo <acme@...hat.com>
Subject: Re: [PATCH v10 08/11] perf python: Add evlist compute_metric

On Wed, Sep 3, 2025 at 6:36 AM Arnaldo Carvalho de Melo <acme@...nel.org> wrote:
>
> On Mon, Aug 18, 2025 at 06:39:38PM -0700, Ian Rogers wrote:
> > Add a compute_metric function that computes a metric double value for a
> > given evlist, metric name, CPU and thread. For example:
> > ```
> > >>> import perf
> > >>> x = perf.parse_metrics("TopdownL1")
> > >>> x.open()
> > >>> x.enable()
> > >>> x.disable()
> > >>> x.metrics()
> > ['tma_bad_speculation', 'tma_frontend_bound', 'tma_backend_bound', 'tma_retiring']
> > >>> x.compute_metric('tma_bad_speculation', 0, -1)
> > 0.08605342847131037
> > ```
>
> Added the following to fix the build on the still not EOLed OpenSUSE
> 15, ok?

Looks good to me!

Thanks,
Ian

> - Arnaldo
>
> diff --git a/tools/perf/util/python.c b/tools/perf/util/python.c
> index 56102034d5b8c469..47178404802f4069 100644
> --- a/tools/perf/util/python.c
> +++ b/tools/perf/util/python.c
> @@ -1386,7 +1386,7 @@ static int prepare_metric(const struct metric_expr *mexp,
>  static PyObject *pyrf_evlist__compute_metric(struct pyrf_evlist *pevlist,
>                                              PyObject *args, PyObject *kwargs)
>  {
> -       int ret, cpu = 0, cpu_idx, thread = 0, thread_idx;
> +       int ret, cpu = 0, cpu_idx = 0, thread = 0, thread_idx = 0;
>         const char *metric;
>         struct rb_node *node;
>         struct metric_expr *mexp = NULL;
>
> Committer notes:
>
> Initialize thread_idx and cpu_idx to zero as albeit them not possibly
> coming out unitialized from the loop as mexp would be not NULL only if
> they were initialized, some older compilers don't notice that and error
> with:
>
>     GEN     /tmp/build/perf/python/perf.cpython-36m-x86_64-linux-gnu.so
>   /git/perf-6.17.0-rc3/tools/perf/util/python.c: In function ‘pyrf_evlist__compute_metric’:
>   /git/perf-6.17.0-rc3/tools/perf/util/python.c:1363:3: error: ‘thread_idx’ may be used uninitialized in this function [-Werror=maybe-uninitialized]
>      evsel__read_counter(metric_events[i], cpu_idx, thread_idx);
>      ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
>   /git/perf-6.17.0-rc3/tools/perf/util/python.c:1389:41: note: ‘thread_idx’ was declared here
>     int ret, cpu = 0, cpu_idx, thread = 0, thread_idx;
>                                            ^~~~~~~~~~
>   /git/perf-6.17.0-rc3/tools/perf/util/python.c:1363:3: error: ‘cpu_idx’ may be used uninitialized in this function [-Werror=maybe-uninitialized]
>      evsel__read_counter(metric_events[i], cpu_idx, thread_idx);
>      ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
>   /git/perf-6.17.0-rc3/tools/perf/util/python.c:1389:20: note: ‘cpu_idx’ was declared here
>     int ret, cpu = 0, cpu_idx, thread = 0, thread_idx;
>                       ^~~~~~~
>   /git/perf-6.17.0-rc3/tools/perf/util/python.c: At top level:
>   cc1: error: unrecognized command line option ‘-Wno-cast-function-type’ [-Werror]
>   cc1: all warnings being treated as errors
>   error: command 'gcc' failed with exit status 1
>   cp: cannot stat '/tmp/build/perf/python_ext_build/lib/perf*.so': No such file or directory
>
> - Arnaldo
>
> > Signed-off-by: Ian Rogers <irogers@...gle.com>
> > Tested-by: Arnaldo Carvalho de Melo <acme@...hat.com>
> > Reviewed-by: Howard Chu <howardchu95@...il.com>
> > ---
> >  tools/perf/util/python.c | 125 +++++++++++++++++++++++++++++++++++++++
> >  1 file changed, 125 insertions(+)
> >
> > diff --git a/tools/perf/util/python.c b/tools/perf/util/python.c
> > index 31089f8e5519..e0769538b8d9 100644
> > --- a/tools/perf/util/python.c
> > +++ b/tools/perf/util/python.c
> > @@ -14,6 +14,7 @@
> >  #include "evlist.h"
> >  #include "evsel.h"
> >  #include "event.h"
> > +#include "expr.h"
> >  #include "print_binary.h"
> >  #include "record.h"
> >  #include "strbuf.h"
> > @@ -1330,6 +1331,124 @@ static PyObject *pyrf_evlist__metrics(struct pyrf_evlist *pevlist)
> >       return list;
> >  }
> >
> > +static int prepare_metric(const struct metric_expr *mexp,
> > +                       const struct evsel *evsel,
> > +                       struct expr_parse_ctx *pctx,
> > +                       int cpu_idx, int thread_idx)
> > +{
> > +     struct evsel * const *metric_events = mexp->metric_events;
> > +     struct metric_ref *metric_refs = mexp->metric_refs;
> > +
> > +     for (int i = 0; metric_events[i]; i++) {
> > +             char *n = strdup(evsel__metric_id(metric_events[i]));
> > +             double val, ena, run;
> > +             int source_count = evsel__source_count(metric_events[i]);
> > +             int ret;
> > +             struct perf_counts_values *old_count, *new_count;
> > +
> > +             if (!n)
> > +                     return -ENOMEM;
> > +
> > +             if (source_count == 0)
> > +                     source_count = 1;
> > +
> > +             ret = evsel__ensure_counts(metric_events[i]);
> > +             if (ret)
> > +                     return ret;
> > +
> > +             /* Set up pointers to the old and newly read counter values. */
> > +             old_count = perf_counts(metric_events[i]->prev_raw_counts, cpu_idx, thread_idx);
> > +             new_count = perf_counts(metric_events[i]->counts, cpu_idx, thread_idx);
> > +             /* Update the value in metric_events[i]->counts. */
> > +             evsel__read_counter(metric_events[i], cpu_idx, thread_idx);
> > +
> > +             val = new_count->val - old_count->val;
> > +             ena = new_count->ena - old_count->ena;
> > +             run = new_count->run - old_count->run;
> > +
> > +             if (ena != run && run != 0)
> > +                     val = val * ena / run;
> > +             ret = expr__add_id_val_source_count(pctx, n, val, source_count);
> > +             if (ret)
> > +                     return ret;
> > +     }
> > +
> > +     for (int i = 0; metric_refs && metric_refs[i].metric_name; i++) {
> > +             int ret = expr__add_ref(pctx, &metric_refs[i]);
> > +
> > +             if (ret)
> > +                     return ret;
> > +     }
> > +
> > +     return 0;
> > +}
> > +
> > +static PyObject *pyrf_evlist__compute_metric(struct pyrf_evlist *pevlist,
> > +                                          PyObject *args, PyObject *kwargs)
> > +{
> > +     int ret, cpu = 0, cpu_idx, thread = 0, thread_idx;
> > +     const char *metric;
> > +     struct rb_node *node;
> > +     struct metric_expr *mexp = NULL;
> > +     struct expr_parse_ctx *pctx;
> > +     double result = 0;
> > +
> > +     if (!PyArg_ParseTuple(args, "sii", &metric, &cpu, &thread))
> > +             return NULL;
> > +
> > +     for (node = rb_first_cached(&pevlist->evlist.metric_events.entries);
> > +          mexp == NULL && node;
> > +          node = rb_next(node)) {
> > +             struct metric_event *me = container_of(node, struct metric_event, nd);
> > +             struct list_head *pos;
> > +
> > +             list_for_each(pos, &me->head) {
> > +                     struct metric_expr *e = container_of(pos, struct metric_expr, nd);
> > +
> > +                     if (strcmp(e->metric_name, metric))
> > +                             continue;
> > +
> > +                     if (e->metric_events[0] == NULL)
> > +                             continue;
> > +
> > +                     cpu_idx = perf_cpu_map__idx(e->metric_events[0]->core.cpus,
> > +                                                 (struct perf_cpu){.cpu = cpu});
> > +                     if (cpu_idx < 0)
> > +                             continue;
> > +
> > +                     thread_idx = perf_thread_map__idx(e->metric_events[0]->core.threads,
> > +                                                       thread);
> > +                     if (thread_idx < 0)
> > +                             continue;
> > +
> > +                     mexp = e;
> > +                     break;
> > +             }
> > +     }
> > +     if (!mexp) {
> > +             PyErr_Format(PyExc_TypeError, "Unknown metric '%s' for CPU '%d' and thread '%d'",
> > +                          metric, cpu, thread);
> > +             return NULL;
> > +     }
> > +
> > +     pctx = expr__ctx_new();
> > +     if (!pctx)
> > +             return PyErr_NoMemory();
> > +
> > +     ret = prepare_metric(mexp, mexp->metric_events[0], pctx, cpu_idx, thread_idx);
> > +     if (ret) {
> > +             expr__ctx_free(pctx);
> > +             errno = -ret;
> > +             PyErr_SetFromErrno(PyExc_OSError);
> > +             return NULL;
> > +     }
> > +     if (expr__parse(&result, pctx, mexp->metric_expr))
> > +             result = 0.0;
> > +
> > +     expr__ctx_free(pctx);
> > +     return PyFloat_FromDouble(result);
> > +}
> > +
> >  static PyObject *pyrf_evlist__mmap(struct pyrf_evlist *pevlist,
> >                                  PyObject *args, PyObject *kwargs)
> >  {
> > @@ -1564,6 +1683,12 @@ static PyMethodDef pyrf_evlist__methods[] = {
> >               .ml_flags = METH_NOARGS,
> >               .ml_doc   = PyDoc_STR("List of metric names within the evlist.")
> >       },
> > +     {
> > +             .ml_name  = "compute_metric",
> > +             .ml_meth  = (PyCFunction)pyrf_evlist__compute_metric,
> > +             .ml_flags = METH_VARARGS | METH_KEYWORDS,
> > +             .ml_doc   = PyDoc_STR("compute metric for given name, cpu and thread")
> > +     },
> >       {
> >               .ml_name  = "mmap",
> >               .ml_meth  = (PyCFunction)pyrf_evlist__mmap,
> > --
> > 2.51.0.rc1.167.g924127e9c0-goog

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ