lkml.org 
[lkml]   [2019]   [Jul]   [15]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH AUTOSEL 5.2 219/249] perf stat: Fix group lookup for metric group
    Date
    From: Andi Kleen <ak@linux.intel.com>

    [ Upstream commit 2f87f33f4226523df9c9cc28f9874ea02fcc3d3f ]

    The metric group code tries to find a group it added earlier in the
    evlist. Fix the lookup to handle groups with partially overlaps
    correctly. When a sub string match fails and we reset the match, we have
    to compare the first element again.

    I also renamed the find_evsel function to find_evsel_group to make its
    purpose clearer.

    With the earlier changes this fixes:

    Before:

    % perf stat -M UPI,IPC sleep 1
    ...
    1,032,922 uops_retired.retire_slots # 1.1 UPI
    1,896,096 inst_retired.any
    1,896,096 inst_retired.any
    1,177,254 cpu_clk_unhalted.thread

    After:

    % perf stat -M UPI,IPC sleep 1
    ...
    1,013,193 uops_retired.retire_slots # 1.1 UPI
    932,033 inst_retired.any
    932,033 inst_retired.any # 0.9 IPC
    1,091,245 cpu_clk_unhalted.thread

    Signed-off-by: Andi Kleen <ak@linux.intel.com>
    Acked-by: Jiri Olsa <jolsa@kernel.org>
    Cc: Kan Liang <kan.liang@linux.intel.com>
    Fixes: b18f3e365019 ("perf stat: Support JSON metrics in perf stat")
    Link: http://lkml.kernel.org/r/20190624193711.35241-4-andi@firstfloor.org
    Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
    Signed-off-by: Sasha Levin <sashal@kernel.org>
    ---
    tools/perf/util/metricgroup.c | 47 ++++++++++++++++++++++++++---------
    1 file changed, 35 insertions(+), 12 deletions(-)

    diff --git a/tools/perf/util/metricgroup.c b/tools/perf/util/metricgroup.c
    index 699e020737d9..fabdb6dde88e 100644
    --- a/tools/perf/util/metricgroup.c
    +++ b/tools/perf/util/metricgroup.c
    @@ -85,26 +85,49 @@ struct egroup {
    const char *metric_expr;
    };

    -static struct perf_evsel *find_evsel(struct perf_evlist *perf_evlist,
    - const char **ids,
    - int idnum,
    - struct perf_evsel **metric_events)
    +static bool record_evsel(int *ind, struct perf_evsel **start,
    + int idnum,
    + struct perf_evsel **metric_events,
    + struct perf_evsel *ev)
    +{
    + metric_events[*ind] = ev;
    + if (*ind == 0)
    + *start = ev;
    + if (++*ind == idnum) {
    + metric_events[*ind] = NULL;
    + return true;
    + }
    + return false;
    +}
    +
    +static struct perf_evsel *find_evsel_group(struct perf_evlist *perf_evlist,
    + const char **ids,
    + int idnum,
    + struct perf_evsel **metric_events)
    {
    struct perf_evsel *ev, *start = NULL;
    int ind = 0;

    evlist__for_each_entry (perf_evlist, ev) {
    + if (ev->collect_stat)
    + continue;
    if (!strcmp(ev->name, ids[ind])) {
    - metric_events[ind] = ev;
    - if (ind == 0)
    - start = ev;
    - if (++ind == idnum) {
    - metric_events[ind] = NULL;
    + if (record_evsel(&ind, &start, idnum,
    + metric_events, ev))
    return start;
    - }
    } else {
    + /*
    + * We saw some other event that is not
    + * in our list of events. Discard
    + * the whole match and start again.
    + */
    ind = 0;
    start = NULL;
    + if (!strcmp(ev->name, ids[ind])) {
    + if (record_evsel(&ind, &start, idnum,
    + metric_events, ev))
    + return start;
    + }
    }
    }
    /*
    @@ -134,8 +157,8 @@ static int metricgroup__setup_events(struct list_head *groups,
    ret = -ENOMEM;
    break;
    }
    - evsel = find_evsel(perf_evlist, eg->ids, eg->idnum,
    - metric_events);
    + evsel = find_evsel_group(perf_evlist, eg->ids, eg->idnum,
    + metric_events);
    if (!evsel) {
    pr_debug("Cannot resolve %s: %s\n",
    eg->metric_name, eg->metric_expr);
    --
    2.20.1
    \
     
     \ /
      Last update: 2019-07-15 16:15    [W:2.114 / U:0.892 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site