From patchwork Thu May 7 08:14:30 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ian Rogers X-Patchwork-Id: 1285019 X-Patchwork-Delegate: bpf@iogearbox.net Return-Path: X-Original-To: patchwork-incoming-netdev@ozlabs.org Delivered-To: patchwork-incoming-netdev@ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=vger.kernel.org (client-ip=23.128.96.18; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=google.com header.i=@google.com header.a=rsa-sha256 header.s=20161025 header.b=bVMuCOks; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by ozlabs.org (Postfix) with ESMTP id 49HmWB3fChz9sSr for ; Thu, 7 May 2020 18:16:06 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726807AbgEGIOx (ORCPT ); Thu, 7 May 2020 04:14:53 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:46932 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-FAIL-OK-FAIL) by vger.kernel.org with ESMTP id S1725809AbgEGIOw (ORCPT ); Thu, 7 May 2020 04:14:52 -0400 Received: from mail-yb1-xb4a.google.com (mail-yb1-xb4a.google.com [IPv6:2607:f8b0:4864:20::b4a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 5BAC6C0610D5 for ; Thu, 7 May 2020 01:14:50 -0700 (PDT) Received: by mail-yb1-xb4a.google.com with SMTP id n205so6110683ybf.14 for ; Thu, 07 May 2020 01:14:50 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20161025; h=date:in-reply-to:message-id:mime-version:references:subject:from:to :cc; bh=dPBMxmwFrR2yn2friu6HNEPQaLNnBOVs6YYMybyFANo=; b=bVMuCOksAbO7MTCJ3gLBkb460Sk9t/7nA9Q2hrZDDwx1UnoLJ84oqEK93Lt1ceDOA3 500yOlwrgxcYdA5mboaqEEmBto9rm+vUpaFoz9P1YVFAJIyGDz7Dbe5DxWCITbmEzy1I X52Lyn88BCy9+PQSA0edwlH+DDr3mkznjvY7nY3CqRRldHD1w7iaKfgdzSPAQMaiP+fN pS+imWKvTNagOYXGt6+DpWg4dO7CQq38tq654cii3zLNW93tYlQ9ZBi9Lkwsadt18hTb 7UgFPAuYWDZ2rlktEG0aLeu+CVTICrEPgLAjpPeeWPqj1fUY5SZ3lwOPiJsFmGHw9g0j 7X/w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc; bh=dPBMxmwFrR2yn2friu6HNEPQaLNnBOVs6YYMybyFANo=; b=t5Olqb0n9n4UNmA1vzjO0A4PW0RNIsnZUzamE7XLTmnC1c5VeW2m7/rkvJNi+k8km1 Kk+mbNAoI0WmCnwl0eB4IWDh0ScCTrYclyEexapxCPANilgOVy+mrYZxgOYZBQRvO8sl hAm7oVOPIm6EHAc3/Gf2jeSLLQlFFn9NlhtyUqNUUob1FHY6rNByM9SEGp7QjYUqNiKT 6CtK/ECQjYSomSuwrXMCn/Um1zgQwYaj0NSCNyYGgaexM2y8Pz+Sc5lxBuHTsqEec5qH rjcWtu176yTX0nxfYJfqKafcr/GT/gfbDEdICV2WAVSA1rCtqaZbiXGpqeogaSlMgmQW 74vQ== X-Gm-Message-State: AGi0PuYDaLX1FqaFjE+BNtTZV7SBWNBHv/Q/F7fpApGd7isOR4epaX9a bdRttW6qgMn/ltGBKF3dz1ZzrCzl77WU X-Google-Smtp-Source: APiQypI0lrEs+six5c8QQW/5Y5d5ULCkrOd+4nYVm4SdjGxNEAfuOGx0X0VcIOfhDZ56ksGTeh2MreEav4ec X-Received: by 2002:a5b:390:: with SMTP id k16mr20726804ybp.175.1588839289381; Thu, 07 May 2020 01:14:49 -0700 (PDT) Date: Thu, 7 May 2020 01:14:30 -0700 In-Reply-To: <20200507081436.49071-1-irogers@google.com> Message-Id: <20200507081436.49071-2-irogers@google.com> Mime-Version: 1.0 References: <20200507081436.49071-1-irogers@google.com> X-Mailer: git-send-email 2.26.2.526.g744177e7f7-goog Subject: [RFC PATCH 1/7] perf expr: migrate expr ids table to libbpf's hashmap From: Ian Rogers To: Peter Zijlstra , Ingo Molnar , Arnaldo Carvalho de Melo , Mark Rutland , Alexander Shishkin , Jiri Olsa , Namhyung Kim , Alexei Starovoitov , Daniel Borkmann , Martin KaFai Lau , Song Liu , Yonghong Song , Andrii Nakryiko , John Fastabend , KP Singh , Kajol Jain , Andi Kleen , John Garry , Jin Yao , Kan Liang , Cong Wang , Kim Phillips , linux-kernel@vger.kernel.org Cc: netdev@vger.kernel.org, bpf@vger.kernel.org, linux-perf-users@vger.kernel.org, Stephane Eranian , Ian Rogers Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org Use a hashmap between a char* string and a double* value. While bpf's hashmap entries are size_t in size, we can't guarantee sizeof(size_t) >= sizeof(double). Avoid a memory allocation when gathering ids by making 0.0 a special value encoded as NULL. Suggested by Andi Kleen: https://lore.kernel.org/lkml/20200224210308.GQ160988@tassilo.jf.intel.com/ and seconded by Jiri Olsa: https://lore.kernel.org/lkml/20200423112915.GH1136647@krava/ Signed-off-by: Ian Rogers --- tools/perf/tests/expr.c | 32 ++++----- tools/perf/tests/pmu-events.c | 22 +++--- tools/perf/util/expr.c | 125 ++++++++++++++++++---------------- tools/perf/util/expr.h | 22 +++--- tools/perf/util/expr.y | 22 +----- tools/perf/util/metricgroup.c | 86 +++++++++++------------ tools/perf/util/stat-shadow.c | 46 ++++++++----- 7 files changed, 176 insertions(+), 179 deletions(-) diff --git a/tools/perf/tests/expr.c b/tools/perf/tests/expr.c index 3f742612776a..bb948226be1d 100644 --- a/tools/perf/tests/expr.c +++ b/tools/perf/tests/expr.c @@ -19,11 +19,9 @@ static int test(struct expr_parse_ctx *ctx, const char *e, double val2) int test__expr(struct test *t __maybe_unused, int subtest __maybe_unused) { const char *p; - const char **other; - double val; - int i, ret; + double val, *val_ptr; + int ret; struct expr_parse_ctx ctx; - int num_other; expr__ctx_init(&ctx); expr__add_id(&ctx, "FOO", 1); @@ -52,25 +50,23 @@ int test__expr(struct test *t __maybe_unused, int subtest __maybe_unused) ret = expr__parse(&val, &ctx, p, 1); TEST_ASSERT_VAL("missing operand", ret == -1); + hashmap__clear(&ctx.ids); TEST_ASSERT_VAL("find other", - expr__find_other("FOO + BAR + BAZ + BOZO", "FOO", &other, &num_other, 1) == 0); - TEST_ASSERT_VAL("find other", num_other == 3); - TEST_ASSERT_VAL("find other", !strcmp(other[0], "BAR")); - TEST_ASSERT_VAL("find other", !strcmp(other[1], "BAZ")); - TEST_ASSERT_VAL("find other", !strcmp(other[2], "BOZO")); - TEST_ASSERT_VAL("find other", other[3] == NULL); + expr__find_other("FOO + BAR + BAZ + BOZO", "FOO", &ctx, 1) == 0); + TEST_ASSERT_VAL("find other", hashmap__size(&ctx.ids) == 3); + TEST_ASSERT_VAL("find other", hashmap__find(&ctx.ids, "BAR", (void**)&val_ptr)); + TEST_ASSERT_VAL("find other", hashmap__find(&ctx.ids, "BAZ", (void**)&val_ptr)); + TEST_ASSERT_VAL("find other", hashmap__find(&ctx.ids, "BOZO", (void**)&val_ptr)); + hashmap__clear(&ctx.ids); TEST_ASSERT_VAL("find other", expr__find_other("EVENT1\\,param\\=?@ + EVENT2\\,param\\=?@", NULL, - &other, &num_other, 3) == 0); - TEST_ASSERT_VAL("find other", num_other == 2); - TEST_ASSERT_VAL("find other", !strcmp(other[0], "EVENT1,param=3/")); - TEST_ASSERT_VAL("find other", !strcmp(other[1], "EVENT2,param=3/")); - TEST_ASSERT_VAL("find other", other[2] == NULL); + &ctx, 3) == 0); + TEST_ASSERT_VAL("find other", hashmap__size(&ctx.ids) == 2); + TEST_ASSERT_VAL("find other", hashmap__find(&ctx.ids, "EVENT1,param=3/", (void**)&val_ptr)); + TEST_ASSERT_VAL("find other", hashmap__find(&ctx.ids, "EVENT2,param=3/", (void**)&val_ptr)); - for (i = 0; i < num_other; i++) - zfree(&other[i]); - free((void *)other); + expr__ctx_clear(&ctx); return 0; } diff --git a/tools/perf/tests/pmu-events.c b/tools/perf/tests/pmu-events.c index c18b9ce8cace..6ce6b8a31e1f 100644 --- a/tools/perf/tests/pmu-events.c +++ b/tools/perf/tests/pmu-events.c @@ -428,8 +428,6 @@ static int test_parsing(void) struct pmu_events_map *map; struct pmu_event *pe; int i, j, k; - const char **ids; - int idnum; int ret = 0; struct expr_parse_ctx ctx; double result; @@ -443,13 +441,16 @@ static int test_parsing(void) } j = 0; for (;;) { + struct hashmap_entry *cur; + size_t bkt; + pe = &map->table[j++]; if (!pe->name && !pe->metric_group && !pe->metric_name) break; if (!pe->metric_expr) continue; - if (expr__find_other(pe->metric_expr, NULL, - &ids, &idnum, 0) < 0) { + if (expr__find_other(pe->metric_expr, NULL, &ctx, 0) + < 0) { pr_debug("Parse other failed for map %s %s %s\n", map->cpuid, map->version, map->type); pr_debug("On metric %s\n", pe->metric_name); @@ -464,11 +465,12 @@ static int test_parsing(void) * trigger divide by zero when subtracted and so try to * make them unique. */ - for (k = 0; k < idnum; k++) - expr__add_id(&ctx, ids[k], k + 1); + k = 1; + hashmap__for_each_entry((&ctx.ids), cur, bkt) + expr__add_id(&ctx, cur->key, k++); - for (k = 0; k < idnum; k++) { - if (check_parse_id(ids[k], map == cpus_map, pe)) + hashmap__for_each_entry((&ctx.ids), cur, bkt) { + if (check_parse_id(cur->key, map == cpus_map, pe)) ret++; } @@ -479,9 +481,7 @@ static int test_parsing(void) pr_debug("On expression %s\n", pe->metric_expr); ret++; } - for (k = 0; k < idnum; k++) - zfree(&ids[k]); - free(ids); + expr__ctx_clear(&ctx); } } return ret; diff --git a/tools/perf/util/expr.c b/tools/perf/util/expr.c index 8b4ce704a68d..70e4e468d7c7 100644 --- a/tools/perf/util/expr.c +++ b/tools/perf/util/expr.c @@ -4,25 +4,73 @@ #include "expr.h" #include "expr-bison.h" #include "expr-flex.h" +#include #ifdef PARSER_DEBUG extern int expr_debug; #endif +static size_t double_hash(const void *key, void *ctx __maybe_unused) +{ + const char *str = (const char*)key; + size_t hash = 0; + while (*str != '\0') { + hash <<= 31; + hash += *str; + str++; + } + return hash; +} + +static bool double_equal(const void *key1, const void *key2, + void *ctx __maybe_unused) +{ + return !strcmp((const char*)key1, (const char*)key2); +} + /* Caller must make sure id is allocated */ -void expr__add_id(struct expr_parse_ctx *ctx, const char *name, double val) +int expr__add_id(struct expr_parse_ctx *ctx, const char *name, double val) { - int idx; + double *val_ptr = NULL, *old_val = NULL; + char *old_key = NULL; + int ret; - assert(ctx->num_ids < MAX_PARSE_ID); - idx = ctx->num_ids++; - ctx->ids[idx].name = name; - ctx->ids[idx].val = val; + if (val != 0.0) { + val_ptr = malloc(sizeof(double)); + if (!val_ptr) + return -ENOMEM; + *val_ptr = val; + } + ret = hashmap__set(&ctx->ids, name, val_ptr, (const void**)&old_key, (void**)&old_val); + free(old_key); + free(old_val); + return ret; +} + +int expr__get_id(struct expr_parse_ctx *ctx, const char *id, double *val_ptr) +{ + double *data; + if (!hashmap__find(&ctx->ids, id, (void**)&data)) + return -1; + *val_ptr = (data == NULL) ? 0.0 : *data; + return 0; } void expr__ctx_init(struct expr_parse_ctx *ctx) { - ctx->num_ids = 0; + hashmap__init(&ctx->ids, double_hash, double_equal, NULL); +} + +void expr__ctx_clear(struct expr_parse_ctx *ctx) +{ + struct hashmap_entry *cur; + size_t bkt; + + hashmap__for_each_entry((&ctx->ids), cur, bkt) { + free((char*)cur->key); + free(cur->value); + } + hashmap__clear(&ctx->ids); } static int @@ -56,61 +104,24 @@ __expr__parse(double *val, struct expr_parse_ctx *ctx, const char *expr, return ret; } -int expr__parse(double *final_val, struct expr_parse_ctx *ctx, const char *expr, int runtime) +int expr__parse(double *final_val, struct expr_parse_ctx *ctx, + const char *expr, int runtime) { return __expr__parse(final_val, ctx, expr, EXPR_PARSE, runtime) ? -1 : 0; } -static bool -already_seen(const char *val, const char *one, const char **other, - int num_other) +int expr__find_other(const char *expr, const char *one, + struct expr_parse_ctx *ctx, int runtime) { - int i; - - if (one && !strcasecmp(one, val)) - return true; - for (i = 0; i < num_other; i++) - if (!strcasecmp(other[i], val)) - return true; - return false; -} - -int expr__find_other(const char *expr, const char *one, const char ***other, - int *num_other, int runtime) -{ - int err, i = 0, j = 0; - struct expr_parse_ctx ctx; - - expr__ctx_init(&ctx); - err = __expr__parse(NULL, &ctx, expr, EXPR_OTHER, runtime); - if (err) - return -1; - - *other = malloc((ctx.num_ids + 1) * sizeof(char *)); - if (!*other) - return -ENOMEM; - - for (i = 0, j = 0; i < ctx.num_ids; i++) { - const char *str = ctx.ids[i].name; - - if (already_seen(str, one, *other, j)) - continue; - - str = strdup(str); - if (!str) - goto out; - (*other)[j++] = str; - } - (*other)[j] = NULL; - -out: - if (i != ctx.num_ids) { - while (--j) - free((char *) (*other)[i]); - free(*other); - err = -1; + double *old_val = NULL; + char *old_key = NULL; + int ret = __expr__parse(NULL, ctx, expr, EXPR_OTHER, runtime); + + if (one) { + hashmap__delete(&ctx->ids, one, (const void**)&old_key, (void**)&old_val); + free(old_key); + free(old_val); } - *num_other = j; - return err; + return ret; } diff --git a/tools/perf/util/expr.h b/tools/perf/util/expr.h index 40fc452b0f2b..f01bd5ecb09d 100644 --- a/tools/perf/util/expr.h +++ b/tools/perf/util/expr.h @@ -2,17 +2,10 @@ #ifndef PARSE_CTX_H #define PARSE_CTX_H 1 -#define EXPR_MAX_OTHER 64 -#define MAX_PARSE_ID EXPR_MAX_OTHER - -struct expr_parse_id { - const char *name; - double val; -}; +#include struct expr_parse_ctx { - int num_ids; - struct expr_parse_id ids[MAX_PARSE_ID]; + struct hashmap ids; }; struct expr_scanner_ctx { @@ -21,9 +14,12 @@ struct expr_scanner_ctx { }; void expr__ctx_init(struct expr_parse_ctx *ctx); -void expr__add_id(struct expr_parse_ctx *ctx, const char *id, double val); -int expr__parse(double *final_val, struct expr_parse_ctx *ctx, const char *expr, int runtime); -int expr__find_other(const char *expr, const char *one, const char ***other, - int *num_other, int runtime); +void expr__ctx_clear(struct expr_parse_ctx *ctx); +int expr__add_id(struct expr_parse_ctx *ctx, const char *id, double val); +int expr__get_id(struct expr_parse_ctx *ctx, const char *id, double *val_ptr); +int expr__parse(double *final_val, struct expr_parse_ctx *ctx, + const char *expr, int runtime); +int expr__find_other(const char *expr, const char *one, + struct expr_parse_ctx *ids, int runtime); #endif diff --git a/tools/perf/util/expr.y b/tools/perf/util/expr.y index 3b49b230b111..bf3e898e3055 100644 --- a/tools/perf/util/expr.y +++ b/tools/perf/util/expr.y @@ -47,19 +47,6 @@ static void expr_error(double *final_val __maybe_unused, pr_debug("%s\n", s); } -static int lookup_id(struct expr_parse_ctx *ctx, char *id, double *val) -{ - int i; - - for (i = 0; i < ctx->num_ids; i++) { - if (!strcasecmp(ctx->ids[i].name, id)) { - *val = ctx->ids[i].val; - return 0; - } - } - return -1; -} - %} %% @@ -73,12 +60,7 @@ all_other: all_other other other: ID { - if (ctx->num_ids + 1 >= EXPR_MAX_OTHER) { - pr_err("failed: way too many variables"); - YYABORT; - } - - ctx->ids[ctx->num_ids++].name = $1; + expr__add_id(ctx, $1, 0.0); } | MIN | MAX | IF | ELSE | SMT_ON | NUMBER | '|' | '^' | '&' | '-' | '+' | '*' | '/' | '%' | '(' | ')' | ',' @@ -93,7 +75,7 @@ if_expr: ; expr: NUMBER - | ID { if (lookup_id(ctx, $1, &$$) < 0) { + | ID { if (expr__get_id(ctx, $1, &$$)) { pr_debug("%s not found\n", $1); free($1); YYABORT; diff --git a/tools/perf/util/metricgroup.c b/tools/perf/util/metricgroup.c index b071df373f8b..2f92dbc05226 100644 --- a/tools/perf/util/metricgroup.c +++ b/tools/perf/util/metricgroup.c @@ -85,8 +85,7 @@ static void metricgroup__rblist_init(struct rblist *metric_events) struct egroup { struct list_head nd; - int idnum; - const char **ids; + struct expr_parse_ctx pctx; const char *metric_name; const char *metric_expr; const char *metric_unit; @@ -94,19 +93,21 @@ struct egroup { }; static struct evsel *find_evsel_group(struct evlist *perf_evlist, - const char **ids, - int idnum, + struct expr_parse_ctx *pctx, struct evsel **metric_events, bool *evlist_used) { struct evsel *ev; - int i = 0, j = 0; bool leader_found; + const size_t idnum = hashmap__size(&pctx->ids); + size_t i = 0; + int j = 0; + double *val_ptr; evlist__for_each_entry (perf_evlist, ev) { if (evlist_used[j++]) continue; - if (!strcmp(ev->name, ids[i])) { + if (hashmap__find(&pctx->ids, ev->name, (void**)&val_ptr)) { if (!metric_events[i]) metric_events[i] = ev; i++; @@ -118,7 +119,7 @@ static struct evsel *find_evsel_group(struct evlist *perf_evlist, memset(metric_events, 0, sizeof(struct evsel *) * idnum); - if (!strcmp(ev->name, ids[i])) { + if (hashmap__find(&pctx->ids, ev->name, (void**)&val_ptr)) { if (!metric_events[i]) metric_events[i] = ev; i++; @@ -175,19 +176,20 @@ static int metricgroup__setup_events(struct list_head *groups, list_for_each_entry (eg, groups, nd) { struct evsel **metric_events; - metric_events = calloc(sizeof(void *), eg->idnum + 1); + metric_events = calloc(sizeof(void *), + hashmap__size(&eg->pctx.ids) + 1); if (!metric_events) { ret = -ENOMEM; break; } - evsel = find_evsel_group(perf_evlist, eg->ids, eg->idnum, - metric_events, evlist_used); + evsel = find_evsel_group(perf_evlist, &eg->pctx, metric_events, + evlist_used); if (!evsel) { pr_debug("Cannot resolve %s: %s\n", eg->metric_name, eg->metric_expr); continue; } - for (i = 0; i < eg->idnum; i++) + for (i = 0; metric_events[i]; i++) metric_events[i]->collect_stat = true; me = metricgroup__lookup(metric_events_list, evsel, true); if (!me) { @@ -415,20 +417,20 @@ void metricgroup__print(bool metrics, bool metricgroups, char *filter, } static void metricgroup__add_metric_weak_group(struct strbuf *events, - const char **ids, - int idnum) + struct expr_parse_ctx *ctx) { + struct hashmap_entry *cur; + size_t bkt, i = 0; bool no_group = false; - int i; - for (i = 0; i < idnum; i++) { - pr_debug("found event %s\n", ids[i]); + hashmap__for_each_entry((&ctx->ids), cur, bkt) { + pr_debug("found event %s\n", (const char*)cur->key); /* * Duration time maps to a software event and can make * groups not count. Always use it outside a * group. */ - if (!strcmp(ids[i], "duration_time")) { + if (!strcmp(cur->key, "duration_time")) { if (i > 0) strbuf_addf(events, "}:W,"); strbuf_addf(events, "duration_time"); @@ -437,21 +439,22 @@ static void metricgroup__add_metric_weak_group(struct strbuf *events, } strbuf_addf(events, "%s%s", i == 0 || no_group ? "{" : ",", - ids[i]); + (const char*)cur->key); no_group = false; + i++; } if (!no_group) strbuf_addf(events, "}:W"); } static void metricgroup__add_metric_non_group(struct strbuf *events, - const char **ids, - int idnum) + struct expr_parse_ctx *ctx) { - int i; + struct hashmap_entry *cur; + size_t bkt; - for (i = 0; i < idnum; i++) - strbuf_addf(events, ",%s", ids[i]); + hashmap__for_each_entry((&ctx->ids), cur, bkt) + strbuf_addf(events, ",%s", (const char*)cur->key); } static void metricgroup___watchdog_constraint_hint(const char *name, bool foot) @@ -495,32 +498,32 @@ int __weak arch_get_runtimeparam(void) static int __metricgroup__add_metric(struct strbuf *events, struct list_head *group_list, struct pmu_event *pe, int runtime) { - - const char **ids; - int idnum; struct egroup *eg; - if (expr__find_other(pe->metric_expr, NULL, &ids, &idnum, runtime) < 0) - return -EINVAL; - - if (events->len > 0) - strbuf_addf(events, ","); - - if (metricgroup__has_constraint(pe)) - metricgroup__add_metric_non_group(events, ids, idnum); - else - metricgroup__add_metric_weak_group(events, ids, idnum); - eg = malloc(sizeof(*eg)); if (!eg) return -ENOMEM; - eg->ids = ids; - eg->idnum = idnum; + expr__ctx_init(&eg->pctx); eg->metric_name = pe->metric_name; eg->metric_expr = pe->metric_expr; eg->metric_unit = pe->unit; eg->runtime = runtime; + + if (expr__find_other(pe->metric_expr, NULL, &eg->pctx, runtime) < 0) { + expr__ctx_clear(&eg->pctx); + free(eg); + return -EINVAL; + } + + if (events->len > 0) + strbuf_addf(events, ","); + + if (metricgroup__has_constraint(pe)) + metricgroup__add_metric_non_group(events, &eg->pctx); + else + metricgroup__add_metric_weak_group(events, &eg->pctx); + list_add_tail(&eg->nd, group_list); return 0; @@ -603,12 +606,9 @@ static int metricgroup__add_metric_list(const char *list, struct strbuf *events, static void metricgroup__free_egroups(struct list_head *group_list) { struct egroup *eg, *egtmp; - int i; list_for_each_entry_safe (eg, egtmp, group_list, nd) { - for (i = 0; i < eg->idnum; i++) - zfree(&eg->ids[i]); - zfree(&eg->ids); + expr__ctx_clear(&eg->pctx); list_del_init(&eg->nd); free(eg); } diff --git a/tools/perf/util/stat-shadow.c b/tools/perf/util/stat-shadow.c index 129b8c5f2538..f8ba66c305f5 100644 --- a/tools/perf/util/stat-shadow.c +++ b/tools/perf/util/stat-shadow.c @@ -323,35 +323,45 @@ void perf_stat__collect_metric_expr(struct evlist *evsel_list) { struct evsel *counter, *leader, **metric_events, *oc; bool found; - const char **metric_names; + struct expr_parse_ctx ctx; + struct hashmap_entry *cur; + size_t bkt; int i; - int num_metric_names; + expr__ctx_init(&ctx); evlist__for_each_entry(evsel_list, counter) { bool invalid = false; leader = counter->leader; if (!counter->metric_expr) continue; + + expr__ctx_clear(&ctx); metric_events = counter->metric_events; if (!metric_events) { - if (expr__find_other(counter->metric_expr, counter->name, - &metric_names, &num_metric_names, 1) < 0) + if (expr__find_other(counter->metric_expr, + counter->name, + &ctx, 1) < 0) continue; metric_events = calloc(sizeof(struct evsel *), - num_metric_names + 1); - if (!metric_events) + hashmap__size(&ctx.ids) + 1); + if (!metric_events) { + expr__ctx_clear(&ctx); return; + } counter->metric_events = metric_events; } - for (i = 0; i < num_metric_names; i++) { + i = 0; + hashmap__for_each_entry((&ctx.ids), cur, bkt) { + const char* metric_name = (const char*)cur->key; + found = false; if (leader) { /* Search in group */ for_each_group_member (oc, leader) { - if (!strcasecmp(oc->name, metric_names[i]) && + if (!strcasecmp(oc->name, metric_name) && !oc->collect_stat) { found = true; break; @@ -360,7 +370,7 @@ void perf_stat__collect_metric_expr(struct evlist *evsel_list) } if (!found) { /* Search ignoring groups */ - oc = perf_stat__find_event(evsel_list, metric_names[i]); + oc = perf_stat__find_event(evsel_list, metric_name); } if (!oc) { /* Deduping one is good enough to handle duplicated PMUs. */ @@ -373,27 +383,27 @@ void perf_stat__collect_metric_expr(struct evlist *evsel_list) * of events. So we ask the user instead to add the missing * events. */ - if (!printed || strcasecmp(printed, metric_names[i])) { + if (!printed || strcasecmp(printed, metric_name)) { fprintf(stderr, "Add %s event to groups to get metric expression for %s\n", - metric_names[i], + metric_name, counter->name); - printed = strdup(metric_names[i]); + printed = strdup(metric_name); } invalid = true; continue; } - metric_events[i] = oc; + metric_events[i++] = oc; oc->collect_stat = true; } metric_events[i] = NULL; - free(metric_names); if (invalid) { free(metric_events); counter->metric_events = NULL; counter->metric_expr = NULL; } } + expr__ctx_clear(&ctx); } static double runtime_stat_avg(struct runtime_stat *st, @@ -738,7 +748,10 @@ static void generic_metric(struct perf_stat_config *config, expr__ctx_init(&pctx); /* Must be first id entry */ - expr__add_id(&pctx, name, avg); + n = strdup(name); + if (!n) + return; + expr__add_id(&pctx, n, avg); for (i = 0; metric_events[i]; i++) { struct saved_value *v; struct stats *stats; @@ -814,8 +827,7 @@ static void generic_metric(struct perf_stat_config *config, (metric_name ? metric_name : name) : "", 0); } - for (i = 1; i < pctx.num_ids; i++) - zfree(&pctx.ids[i].name); + expr__ctx_clear(&pctx); } void perf_stat__print_shadow_stats(struct perf_stat_config *config, From patchwork Thu May 7 08:14:31 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ian Rogers X-Patchwork-Id: 1285002 X-Patchwork-Delegate: bpf@iogearbox.net Return-Path: X-Original-To: patchwork-incoming-netdev@ozlabs.org Delivered-To: patchwork-incoming-netdev@ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=vger.kernel.org (client-ip=23.128.96.18; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=google.com header.i=@google.com header.a=rsa-sha256 header.s=20161025 header.b=U7wRbdfz; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by ozlabs.org (Postfix) with ESMTP id 49HmTq2MKkz9sSc for ; Thu, 7 May 2020 18:14:55 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726907AbgEGIOy (ORCPT ); Thu, 7 May 2020 04:14:54 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:46946 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-FAIL-OK-FAIL) by vger.kernel.org with ESMTP id S1726701AbgEGIOw (ORCPT ); Thu, 7 May 2020 04:14:52 -0400 Received: from mail-yb1-xb49.google.com (mail-yb1-xb49.google.com [IPv6:2607:f8b0:4864:20::b49]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 57FFBC061A41 for ; Thu, 7 May 2020 01:14:52 -0700 (PDT) Received: by mail-yb1-xb49.google.com with SMTP id h129so6031387ybc.3 for ; Thu, 07 May 2020 01:14:52 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20161025; h=date:in-reply-to:message-id:mime-version:references:subject:from:to :cc; bh=4jAiujVPIH0XWZpTZgSL+DGkUTq2TxINaqAiEYunye0=; b=U7wRbdfzR+TPabVXRkSFeJE9tthG2dbucEQJlAe7mIkrJqQjNyRHem0kHXtghq8bnr D5W15KCkFJS8JPclkWuahr8m2Or7W3s1CRJK6fwG+ha+JsvVJK6oHhAhhaQ+53kgckBX jo0+hIoMrvB++vfIC/LRimiKx41T5K6kdLlQi0AWa4ykCIJCFJGXa2NhsIC7LoB8wikT jx/5iUJ6bIJ/75C1HiSa2uzwXOvqkOW/tLz/fSHRtA0uk/PJ/11XwFNOGH3bgv3gXs3n B+2rSOwVUo+gQoTo/Rh8zPvAp6P9EVr9PTU9s/+KCG4AAgfUVIvxV30NhAkerMPUB5+/ 02Fg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc; bh=4jAiujVPIH0XWZpTZgSL+DGkUTq2TxINaqAiEYunye0=; b=I9MdsMGLSGYiZ6zTvCM4ANhcZwClAsaTBl1N4fYguoCxZF4dtpMAAMyXqO9GL9wvmE t6pdwaUCZPtwfhkDlC8dyJ8cMyuwfzKpwOrN1RtZTbaQewFxMLDkZ6/4k8YWeAvVA/TB RcEuHcbEhLdkqcOKiflhqiK1bshPBKQwRC+izMvxrW9pSw74fjmcl6DzzC29WTRVGLZj cj2S8RRlNovAMYr9dLVIm4HnFoqi7U81ra/L9C4wiJXvAvOwpNRJgnswSYxyFK9+jO7p 4W/vHtrclcZy7JK6PZ5IqyReHHjXTb+WCDipWiWqA4hONQhXvF6HnXenWgaiIi8ri10z fBVQ== X-Gm-Message-State: AGi0PuY8FTV7/LssqC/8xaoSUPv+FR/5hmzfMTdiJP4Qe/+R930c80y8 q24LXBn2KGqnr+HndIPMUZTf87w9QzvL X-Google-Smtp-Source: APiQypKwLkD+uB2It9ZWT/f91/xVIyTeXDlbilbCRc/Jf9xhtrEOmeGyY8IG713wAfAF70bC8hWyMwFCX2YI X-Received: by 2002:a25:6f56:: with SMTP id k83mr20697937ybc.248.1588839291471; Thu, 07 May 2020 01:14:51 -0700 (PDT) Date: Thu, 7 May 2020 01:14:31 -0700 In-Reply-To: <20200507081436.49071-1-irogers@google.com> Message-Id: <20200507081436.49071-3-irogers@google.com> Mime-Version: 1.0 References: <20200507081436.49071-1-irogers@google.com> X-Mailer: git-send-email 2.26.2.526.g744177e7f7-goog Subject: [RFC PATCH 2/7] perf metricgroup: change evlist_used to a bitmap From: Ian Rogers To: Peter Zijlstra , Ingo Molnar , Arnaldo Carvalho de Melo , Mark Rutland , Alexander Shishkin , Jiri Olsa , Namhyung Kim , Alexei Starovoitov , Daniel Borkmann , Martin KaFai Lau , Song Liu , Yonghong Song , Andrii Nakryiko , John Fastabend , KP Singh , Kajol Jain , Andi Kleen , John Garry , Jin Yao , Kan Liang , Cong Wang , Kim Phillips , linux-kernel@vger.kernel.org Cc: netdev@vger.kernel.org, bpf@vger.kernel.org, linux-perf-users@vger.kernel.org, Stephane Eranian , Ian Rogers Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org Use a bitmap rather than an array of bools. Signed-off-by: Ian Rogers --- tools/perf/util/metricgroup.c | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/tools/perf/util/metricgroup.c b/tools/perf/util/metricgroup.c index 2f92dbc05226..dcd175c05872 100644 --- a/tools/perf/util/metricgroup.c +++ b/tools/perf/util/metricgroup.c @@ -95,7 +95,7 @@ struct egroup { static struct evsel *find_evsel_group(struct evlist *perf_evlist, struct expr_parse_ctx *pctx, struct evsel **metric_events, - bool *evlist_used) + unsigned long *evlist_used) { struct evsel *ev; bool leader_found; @@ -105,7 +105,7 @@ static struct evsel *find_evsel_group(struct evlist *perf_evlist, double *val_ptr; evlist__for_each_entry (perf_evlist, ev) { - if (evlist_used[j++]) + if (test_bit(j++, evlist_used)) continue; if (hashmap__find(&pctx->ids, ev->name, (void**)&val_ptr)) { if (!metric_events[i]) @@ -149,7 +149,7 @@ static struct evsel *find_evsel_group(struct evlist *perf_evlist, j++; } ev = metric_events[i]; - evlist_used[ev->idx] = true; + set_bit(ev->idx, evlist_used); } return metric_events[0]; @@ -165,13 +165,11 @@ static int metricgroup__setup_events(struct list_head *groups, int ret = 0; struct egroup *eg; struct evsel *evsel; - bool *evlist_used; + unsigned long *evlist_used; - evlist_used = calloc(perf_evlist->core.nr_entries, sizeof(bool)); - if (!evlist_used) { - ret = -ENOMEM; - return ret; - } + evlist_used = bitmap_alloc(perf_evlist->core.nr_entries); + if (!evlist_used) + return -ENOMEM; list_for_each_entry (eg, groups, nd) { struct evsel **metric_events; @@ -209,7 +207,7 @@ static int metricgroup__setup_events(struct list_head *groups, list_add(&expr->nd, &me->head); } - free(evlist_used); + bitmap_free(evlist_used); return ret; } From patchwork Thu May 7 08:14:32 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ian Rogers X-Patchwork-Id: 1285010 X-Patchwork-Delegate: bpf@iogearbox.net Return-Path: X-Original-To: patchwork-incoming-netdev@ozlabs.org Delivered-To: patchwork-incoming-netdev@ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=vger.kernel.org (client-ip=23.128.96.18; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=google.com header.i=@google.com header.a=rsa-sha256 header.s=20161025 header.b=Koz8yhPr; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by ozlabs.org (Postfix) with ESMTP id 49HmVW1rXyz9sSW for ; Thu, 7 May 2020 18:15:31 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727810AbgEGIPa (ORCPT ); Thu, 7 May 2020 04:15:30 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:46954 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-FAIL-OK-FAIL) by vger.kernel.org with ESMTP id S1726942AbgEGIOz (ORCPT ); Thu, 7 May 2020 04:14:55 -0400 Received: from mail-yb1-xb4a.google.com (mail-yb1-xb4a.google.com [IPv6:2607:f8b0:4864:20::b4a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 4394FC061A10 for ; Thu, 7 May 2020 01:14:54 -0700 (PDT) Received: by mail-yb1-xb4a.google.com with SMTP id r14so6005277ybk.21 for ; Thu, 07 May 2020 01:14:54 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20161025; h=date:in-reply-to:message-id:mime-version:references:subject:from:to :cc; bh=laqIw2e8BtvC1AZBZIJa3w6PXohYXYOFdU6fqXlT6Ys=; b=Koz8yhPrUge2qVVcAlXS3xyTi6AXWgzlfI0d/AGJIRthsuF8fw+v2Ec78xvYT1vOlR kEr+40q4sqVBX2wHSELJg/ziCcyodqffvKB8cPN3wNTjlV6wa4O2bY/SrAuIct2lInpT jK7ZTZQwfp8xM4w1f59/gu1d6VSLBWgPWsuWz7YKC+dPriJw4tMIwIc6XhMjtUe7OZXU GtvOIuWm3IX4nSFjVVpokhNFSTVvIpatY3gOP40uSJbWKHDv5/mSbK+j+fDMdFJjpw5W YRoGylIfifN6N++4ritkfMUA/OFQaHaOyelTbptoqRdfKQ9CfYVCOlOYx/e9SqoD7/jn OgAQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc; bh=laqIw2e8BtvC1AZBZIJa3w6PXohYXYOFdU6fqXlT6Ys=; b=DecDPKzMc+npDkuhppWR9UvvtZw4Qu9dcyU91nioxbg3HCaaj1Fn/Z4HMs2mmahN0s HKPJWEWoXLc38PjfK9Hmg3yStaVQ8Cw9uYNTSk0niWGoSLvvs5wIX98uhpZWyq0FbzUM tJlcpko2QpEOxEliTP1nX/gzsdOhtf2f3oN1PZqlNt4WB617u0od0PCfh+QcKdJQIECV VJxD1uPBmFj0bwMs/GleQoikP5LuHFmBrM7fDVP83A2gOZkK0u7Ofp/RWsJHNmhoLWA5 YE4JyyOhsJBqTow0IfCJpwOHuMAafhLy94FPIEmAxHmkH3lHxIdLsr8ZBP5eZY65PiZu VOYg== X-Gm-Message-State: AGi0Puam0kZsTMybZ2SRf6gFi75C/RCwYxshHZyuzhBDYN+djUaqUFt/ 9Dm8CZ4l125y8WvltaLupMl90CeT6vGs X-Google-Smtp-Source: APiQypLaC9JqxCmf6Bc+54GwEgoHzPXMW94TycpXOg7SlZklfTr4XBRhXJ0pzY3K1F7ZAs3iNOA7yPXtwrAv X-Received: by 2002:a25:d1c1:: with SMTP id i184mr8537881ybg.165.1588839293414; Thu, 07 May 2020 01:14:53 -0700 (PDT) Date: Thu, 7 May 2020 01:14:32 -0700 In-Reply-To: <20200507081436.49071-1-irogers@google.com> Message-Id: <20200507081436.49071-4-irogers@google.com> Mime-Version: 1.0 References: <20200507081436.49071-1-irogers@google.com> X-Mailer: git-send-email 2.26.2.526.g744177e7f7-goog Subject: [RFC PATCH 3/7] perf metricgroup: free metric_events on error From: Ian Rogers To: Peter Zijlstra , Ingo Molnar , Arnaldo Carvalho de Melo , Mark Rutland , Alexander Shishkin , Jiri Olsa , Namhyung Kim , Alexei Starovoitov , Daniel Borkmann , Martin KaFai Lau , Song Liu , Yonghong Song , Andrii Nakryiko , John Fastabend , KP Singh , Kajol Jain , Andi Kleen , John Garry , Jin Yao , Kan Liang , Cong Wang , Kim Phillips , linux-kernel@vger.kernel.org Cc: netdev@vger.kernel.org, bpf@vger.kernel.org, linux-perf-users@vger.kernel.org, Stephane Eranian , Ian Rogers Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org Avoid a simple memory leak. Signed-off-by: Ian Rogers --- tools/perf/util/metricgroup.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tools/perf/util/metricgroup.c b/tools/perf/util/metricgroup.c index dcd175c05872..2356dda92a07 100644 --- a/tools/perf/util/metricgroup.c +++ b/tools/perf/util/metricgroup.c @@ -185,6 +185,7 @@ static int metricgroup__setup_events(struct list_head *groups, if (!evsel) { pr_debug("Cannot resolve %s: %s\n", eg->metric_name, eg->metric_expr); + free(metric_events); continue; } for (i = 0; metric_events[i]; i++) @@ -192,11 +193,13 @@ static int metricgroup__setup_events(struct list_head *groups, me = metricgroup__lookup(metric_events_list, evsel, true); if (!me) { ret = -ENOMEM; + free(metric_events); break; } expr = malloc(sizeof(struct metric_expr)); if (!expr) { ret = -ENOMEM; + free(metric_events); break; } expr->metric_expr = eg->metric_expr; From patchwork Thu May 7 08:14:33 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ian Rogers X-Patchwork-Id: 1285009 X-Patchwork-Delegate: bpf@iogearbox.net Return-Path: X-Original-To: patchwork-incoming-netdev@ozlabs.org Delivered-To: patchwork-incoming-netdev@ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=vger.kernel.org (client-ip=23.128.96.18; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=google.com header.i=@google.com header.a=rsa-sha256 header.s=20161025 header.b=C0QKxnSq; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by ozlabs.org (Postfix) with ESMTP id 49HmVQ5k41z9sSk for ; Thu, 7 May 2020 18:15:26 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727794AbgEGIPZ (ORCPT ); Thu, 7 May 2020 04:15:25 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:46974 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-FAIL-OK-FAIL) by vger.kernel.org with ESMTP id S1727030AbgEGIO5 (ORCPT ); Thu, 7 May 2020 04:14:57 -0400 Received: from mail-yb1-xb49.google.com (mail-yb1-xb49.google.com [IPv6:2607:f8b0:4864:20::b49]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 4EE32C061BD3 for ; Thu, 7 May 2020 01:14:56 -0700 (PDT) Received: by mail-yb1-xb49.google.com with SMTP id 186so6119983ybq.1 for ; Thu, 07 May 2020 01:14:56 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20161025; h=date:in-reply-to:message-id:mime-version:references:subject:from:to :cc; bh=sCS1jCtEUZLDql23q/lHeTg7GUDYj0iuw701FY6e4C0=; b=C0QKxnSqdHFtz+CRo7QjFhWvM+7DIxxGWsQCgCGoSuiM3h1SDPz51ol74GRCagamPW qAchUF2n+Y/Hkowd9VnNJrdCr4lG4ojkGNIwq/Eey7FH7rxTKFP0AYXo5KfGknbp7inX 2GGmmJTDE+IgTwAANhMOTeEN50LnMXxDa5hDg5V9DtZ6natb6jRn7PO6iL+gdflLUMvj coH6tmWUtDoXULSlSCANtWXnFkWCYHftdAErvKRFp9/BD65Qzd1AQvyt0W+mnxsWe6Ni d/DRWZ/xg5XvpPK+vI7kpbPa0uKyFXuUt6XNTND4u90+Dpziz50xA2VvjFTHoaeO/syH d8xg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc; bh=sCS1jCtEUZLDql23q/lHeTg7GUDYj0iuw701FY6e4C0=; b=E8hbs82cTIhzqop4D8uCQ1QohArHRpoUp76BS18WUmb/X6alGMGuzFDy0YIXFxyGlm YHvHT+/PlVxteKLQrVPPZkSHrvR5VX8drWnjb4bBkOCedl/6bTDAgdvm5Z/DBpCrZTWw K3g3InRndj6f5/38spmgoTH8+jGYjK4aIz8xfjLLOhXEjekUxUZGhVAvIW7yDqxD34cM KcFNX/DronvXSs4F5G2f0BAjt0BZ6SvTXYGWfPitlqKVgONvKXNeMxWLwm4Vnt9BtTjz goeCvS0qPm38kZUMopJEBlVZnhlbUu1Ag2j4rNOpNSJ+qUzJjvoUQoOSg3FDbOkM+TUI BiFw== X-Gm-Message-State: AGi0PubgSHjxIUbakaJLkMZZjeREzdLk5QtHjVTgiLHf3v8+33Kz8nEu nc71mUrw6PBR8IXDgs6cCyF35o+JupbU X-Google-Smtp-Source: APiQypLicba0n1ZdHNM4nUUa5fD9wGJNUt+gST4Snsmj66XJ33XVpsWiBgB9Bu5FTvpXabk08ynYTGT40AjW X-Received: by 2002:a25:2544:: with SMTP id l65mr18343110ybl.155.1588839295435; Thu, 07 May 2020 01:14:55 -0700 (PDT) Date: Thu, 7 May 2020 01:14:33 -0700 In-Reply-To: <20200507081436.49071-1-irogers@google.com> Message-Id: <20200507081436.49071-5-irogers@google.com> Mime-Version: 1.0 References: <20200507081436.49071-1-irogers@google.com> X-Mailer: git-send-email 2.26.2.526.g744177e7f7-goog Subject: [RFC PATCH 4/7] perf metricgroup: always place duration_time last From: Ian Rogers To: Peter Zijlstra , Ingo Molnar , Arnaldo Carvalho de Melo , Mark Rutland , Alexander Shishkin , Jiri Olsa , Namhyung Kim , Alexei Starovoitov , Daniel Borkmann , Martin KaFai Lau , Song Liu , Yonghong Song , Andrii Nakryiko , John Fastabend , KP Singh , Kajol Jain , Andi Kleen , John Garry , Jin Yao , Kan Liang , Cong Wang , Kim Phillips , linux-kernel@vger.kernel.org Cc: netdev@vger.kernel.org, bpf@vger.kernel.org, linux-perf-users@vger.kernel.org, Stephane Eranian , Ian Rogers Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org If a metric contains the duration_time event then the event is placed outside of the metric's group of events. Rather than split the group, make it so the duration_time is immediately after the group. Signed-off-by: Ian Rogers --- tools/perf/util/metricgroup.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/tools/perf/util/metricgroup.c b/tools/perf/util/metricgroup.c index 2356dda92a07..48d0143b4b0c 100644 --- a/tools/perf/util/metricgroup.c +++ b/tools/perf/util/metricgroup.c @@ -421,8 +421,8 @@ static void metricgroup__add_metric_weak_group(struct strbuf *events, struct expr_parse_ctx *ctx) { struct hashmap_entry *cur; - size_t bkt, i = 0; - bool no_group = false; + size_t bkt; + bool no_group = true, has_duration = false; hashmap__for_each_entry((&ctx->ids), cur, bkt) { pr_debug("found event %s\n", (const char*)cur->key); @@ -432,20 +432,20 @@ static void metricgroup__add_metric_weak_group(struct strbuf *events, * group. */ if (!strcmp(cur->key, "duration_time")) { - if (i > 0) - strbuf_addf(events, "}:W,"); - strbuf_addf(events, "duration_time"); - no_group = true; + has_duration = true; continue; } strbuf_addf(events, "%s%s", - i == 0 || no_group ? "{" : ",", + no_group ? "{" : ",", (const char*)cur->key); no_group = false; - i++; } - if (!no_group) - strbuf_addf(events, "}:W"); + if (!no_group) { + strbuf_addf(events, "}:W"); + if (has_duration) + strbuf_addf(events, ",duration_time"); + } else if (has_duration) + strbuf_addf(events, "duration_time"); } static void metricgroup__add_metric_non_group(struct strbuf *events, From patchwork Thu May 7 08:14:34 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ian Rogers X-Patchwork-Id: 1285007 X-Patchwork-Delegate: bpf@iogearbox.net Return-Path: X-Original-To: patchwork-incoming-netdev@ozlabs.org Delivered-To: patchwork-incoming-netdev@ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=vger.kernel.org (client-ip=23.128.96.18; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=google.com header.i=@google.com header.a=rsa-sha256 header.s=20161025 header.b=NBD8jR8Z; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by ozlabs.org (Postfix) with ESMTP id 49HmVH1b3kz9sT0 for ; Thu, 7 May 2020 18:15:19 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727783AbgEGIPP (ORCPT ); Thu, 7 May 2020 04:15:15 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:46988 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-FAIL-OK-FAIL) by vger.kernel.org with ESMTP id S1727093AbgEGIO7 (ORCPT ); Thu, 7 May 2020 04:14:59 -0400 Received: from mail-qt1-x84a.google.com (mail-qt1-x84a.google.com [IPv6:2607:f8b0:4864:20::84a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 43FB5C03C1A8 for ; Thu, 7 May 2020 01:14:58 -0700 (PDT) Received: by mail-qt1-x84a.google.com with SMTP id z8so5795433qtu.17 for ; Thu, 07 May 2020 01:14:58 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20161025; h=date:in-reply-to:message-id:mime-version:references:subject:from:to :cc; bh=37IhcnJ8/vjmrEBEbWQ5EKKAlYXyNL6TpEjB8zoBU+I=; b=NBD8jR8Z4jCqufCDci5gSr0lwIjSz+GUfkc0vsxzwut7aRab5J7mNCxjsLZQ6yKYfc HHnwGhftKE4MPP+AbDy+KaEZeGzptD/T1FYOC7gDAuKMplFBhoGv2jN4Re5qTEebjfUT bnsHBrE7McUl9bl2HtqJc9jjBJniEKl+lUJqSY+MwNbF7uW5Eant9SvWS783nM7COBBb KjlYpbL3pan5IedueHdBoLhiIqnQHiLM/zf9Bxy6wacUCeqtVBR4C71Kt5N6MYqYejEu sdCyVaCPupL8mJyfbOvSYAVHl0JwWw6DxhNAOsL+UdSjXOqi351ZGKdQXBGom3Ta/qxi OtxQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc; bh=37IhcnJ8/vjmrEBEbWQ5EKKAlYXyNL6TpEjB8zoBU+I=; b=UOTGpRxBnOZTZoRJiXiiqtv0W/iA6k83qeAHed7J7qPkUXUR00Z+dtxEHgScsmuPrO vedfe0APcAYBssUdNOHWAKmv2x0bvc+gUytH13eloedc3ZK8UJnVtquT6xZ9Gi+eOmks 2a2GEVWsYRdznVT7ArbkPvRy3Btx+SXEKIZJE4hI8DTcKb51U3yzoTyAO3Es77D4WNMx J4qewCywaNAMG2Z6C3YW1GvH8ddxJ7XGlmdfaAEddHWdyHhDfaZ3xZYD9rfhtEcljgRW FtgokHdiTfxJMfbO8QypFkALc8tmG797vWj5TuZyU1g50uTJRBJjA9hmnp8rxA4ohbjJ qdYQ== X-Gm-Message-State: AGi0PuaRx73sd8eYbInHLZ0T/HuhiX+P+cDuazazXqQYOArstu0CNaKy jLEcIcXQ/G8NdW5blv3LH8UFrMH7FDDx X-Google-Smtp-Source: APiQypIXqLy5n+p2wBYTxOYoVY+coeUGgLYdh1PlgWGFG7WUqsWYfBI7sc++z6s7SsrCpu/pXjLhU1eMBgW7 X-Received: by 2002:a05:6214:7a7:: with SMTP id v7mr12232693qvz.27.1588839297231; Thu, 07 May 2020 01:14:57 -0700 (PDT) Date: Thu, 7 May 2020 01:14:34 -0700 In-Reply-To: <20200507081436.49071-1-irogers@google.com> Message-Id: <20200507081436.49071-6-irogers@google.com> Mime-Version: 1.0 References: <20200507081436.49071-1-irogers@google.com> X-Mailer: git-send-email 2.26.2.526.g744177e7f7-goog Subject: [RFC PATCH 5/7] perf metricgroup: delay events string creation From: Ian Rogers To: Peter Zijlstra , Ingo Molnar , Arnaldo Carvalho de Melo , Mark Rutland , Alexander Shishkin , Jiri Olsa , Namhyung Kim , Alexei Starovoitov , Daniel Borkmann , Martin KaFai Lau , Song Liu , Yonghong Song , Andrii Nakryiko , John Fastabend , KP Singh , Kajol Jain , Andi Kleen , John Garry , Jin Yao , Kan Liang , Cong Wang , Kim Phillips , linux-kernel@vger.kernel.org Cc: netdev@vger.kernel.org, bpf@vger.kernel.org, linux-perf-users@vger.kernel.org, Stephane Eranian , Ian Rogers Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org Currently event groups are placed into groups_list at the same time as the events string containing the events is built. Separate these two operations and build the groups_list first, then the event string from the groups_list. This adds an ability to reorder the groups_list that will be used in a later patch. Signed-off-by: Ian Rogers --- tools/perf/util/metricgroup.c | 38 +++++++++++++++++++++++------------ 1 file changed, 25 insertions(+), 13 deletions(-) diff --git a/tools/perf/util/metricgroup.c b/tools/perf/util/metricgroup.c index 48d0143b4b0c..0a00c0f87872 100644 --- a/tools/perf/util/metricgroup.c +++ b/tools/perf/util/metricgroup.c @@ -90,6 +90,7 @@ struct egroup { const char *metric_expr; const char *metric_unit; int runtime; + bool has_constraint; }; static struct evsel *find_evsel_group(struct evlist *perf_evlist, @@ -496,8 +497,8 @@ int __weak arch_get_runtimeparam(void) return 1; } -static int __metricgroup__add_metric(struct strbuf *events, - struct list_head *group_list, struct pmu_event *pe, int runtime) +static int __metricgroup__add_metric(struct list_head *group_list, + struct pmu_event *pe, int runtime) { struct egroup *eg; @@ -510,6 +511,7 @@ static int __metricgroup__add_metric(struct strbuf *events, eg->metric_expr = pe->metric_expr; eg->metric_unit = pe->unit; eg->runtime = runtime; + eg->has_constraint = metricgroup__has_constraint(pe); if (expr__find_other(pe->metric_expr, NULL, &eg->pctx, runtime) < 0) { expr__ctx_clear(&eg->pctx); @@ -517,14 +519,6 @@ static int __metricgroup__add_metric(struct strbuf *events, return -EINVAL; } - if (events->len > 0) - strbuf_addf(events, ","); - - if (metricgroup__has_constraint(pe)) - metricgroup__add_metric_non_group(events, &eg->pctx); - else - metricgroup__add_metric_weak_group(events, &eg->pctx); - list_add_tail(&eg->nd, group_list); return 0; @@ -535,6 +529,7 @@ static int metricgroup__add_metric(const char *metric, struct strbuf *events, { struct pmu_events_map *map = perf_pmu__find_map(NULL); struct pmu_event *pe; + struct egroup *eg; int i, ret = -EINVAL; if (!map) @@ -553,7 +548,8 @@ static int metricgroup__add_metric(const char *metric, struct strbuf *events, pr_debug("metric expr %s for %s\n", pe->metric_expr, pe->metric_name); if (!strstr(pe->metric_expr, "?")) { - ret = __metricgroup__add_metric(events, group_list, pe, 1); + ret = __metricgroup__add_metric(group_list, + pe, 1); } else { int j, count; @@ -564,13 +560,29 @@ static int metricgroup__add_metric(const char *metric, struct strbuf *events, * those events to group_list. */ - for (j = 0; j < count; j++) - ret = __metricgroup__add_metric(events, group_list, pe, j); + for (j = 0; j < count; j++) { + ret = __metricgroup__add_metric( + group_list, pe, j); + } } if (ret == -ENOMEM) break; } } + if (!ret) { + list_for_each_entry (eg, group_list, nd) { + if (events->len > 0) + strbuf_addf(events, ","); + + if (eg->has_constraint) { + metricgroup__add_metric_non_group(events, + &eg->pctx); + } else { + metricgroup__add_metric_weak_group(events, + &eg->pctx); + } + } + } return ret; } From patchwork Thu May 7 08:14:35 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ian Rogers X-Patchwork-Id: 1285003 X-Patchwork-Delegate: bpf@iogearbox.net Return-Path: X-Original-To: patchwork-incoming-netdev@ozlabs.org Delivered-To: patchwork-incoming-netdev@ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=vger.kernel.org (client-ip=23.128.96.18; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=google.com header.i=@google.com header.a=rsa-sha256 header.s=20161025 header.b=a1D0g4qg; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by ozlabs.org (Postfix) with ESMTP id 49HmV15YkYz9sSs for ; Thu, 7 May 2020 18:15:05 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727123AbgEGIPC (ORCPT ); Thu, 7 May 2020 04:15:02 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:47002 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-FAIL-OK-FAIL) by vger.kernel.org with ESMTP id S1727105AbgEGIPA (ORCPT ); Thu, 7 May 2020 04:15:00 -0400 Received: from mail-qv1-xf4a.google.com (mail-qv1-xf4a.google.com [IPv6:2607:f8b0:4864:20::f4a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 3EB04C0610D6 for ; Thu, 7 May 2020 01:15:00 -0700 (PDT) Received: by mail-qv1-xf4a.google.com with SMTP id dh14so5158374qvb.4 for ; Thu, 07 May 2020 01:15:00 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20161025; h=date:in-reply-to:message-id:mime-version:references:subject:from:to :cc; bh=wdUpgcjdyvRHeAuiwINZJwatakpGlpcmPaMYucAxya4=; b=a1D0g4qgq2DeZVYxZXmwzJvFe80E+NY6Bl81ZXr1D2+xAl8ZNsS0+tJz9pxiOODZQE 6pJFFiDn3fEWNQQ5lrrjMYapn6poOSYZtu6PN0DoTmMrD4O2LkXxmyYf4XoZdMLy2FDP kEmpHV/MX3b6DZcKXWZYgy29uupIcAuwPc/RJzfEZ/Rn1SypACWfGKtvagqouxnMc+Se fJp0uZhkxRe7LTOnqHzqpSKdGKl375V2yIAzJ1aw5aG8/v7YD4el/AuJZKSYXHgff9PO 9695v/gBHe1pjJ7KY1yMmDhcIQNhKpQUkImim277Mw6mGWUzKGp3FctFIkMGsnx6HxE4 2FcA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc; bh=wdUpgcjdyvRHeAuiwINZJwatakpGlpcmPaMYucAxya4=; b=aw6GPkIXu2TwNng+8qPUPdqScrW1ul+g7sD6BqpSORH3ji4NZIOScJPfYYHai6Dxv4 wFkuUXtMLqrR1zaVcIsRPv6AoucGNJM2hn47lyNVcfEl2UHjXSv83fDECQrQ16KxSf77 jJKIBxhGEw712s/+46DYEQFt16jCMM4py2RqUGHuj9+Y3LXfkBYf7tf/57YCjYHZRIlN iC8xL2Ni0u+aOiZqR1wsGIJHxvTL0VpQe3yNMcOIgYuyBgtmJbjGJm4K+JpU521N+9df LB4Fz9tI8ndZx8dzqtpVOdkymk+khUa+itzB3NxNSl+FQM3IpiMX4IT0DlZu8zDRuTLe Uhvg== X-Gm-Message-State: AGi0PubfsEMirNA1KaYsIALfc6MLkGvB6R/XGwJfGKEHayxm1esyRlTB 9QSnuDkgVKyWLy85jG94f48JE2mG2GfX X-Google-Smtp-Source: APiQypKfY5bUdzcKD5EFsOUTDzmIo6WlYY0MBP0ESNMa+3S6spMM1XtYeHvtMwk6ZY1SEl8iBwSWx7hYrFlz X-Received: by 2002:ad4:4f01:: with SMTP id fb1mr12775550qvb.162.1588839299303; Thu, 07 May 2020 01:14:59 -0700 (PDT) Date: Thu, 7 May 2020 01:14:35 -0700 In-Reply-To: <20200507081436.49071-1-irogers@google.com> Message-Id: <20200507081436.49071-7-irogers@google.com> Mime-Version: 1.0 References: <20200507081436.49071-1-irogers@google.com> X-Mailer: git-send-email 2.26.2.526.g744177e7f7-goog Subject: [RFC PATCH 6/7] perf metricgroup: order event groups by size From: Ian Rogers To: Peter Zijlstra , Ingo Molnar , Arnaldo Carvalho de Melo , Mark Rutland , Alexander Shishkin , Jiri Olsa , Namhyung Kim , Alexei Starovoitov , Daniel Borkmann , Martin KaFai Lau , Song Liu , Yonghong Song , Andrii Nakryiko , John Fastabend , KP Singh , Kajol Jain , Andi Kleen , John Garry , Jin Yao , Kan Liang , Cong Wang , Kim Phillips , linux-kernel@vger.kernel.org Cc: netdev@vger.kernel.org, bpf@vger.kernel.org, linux-perf-users@vger.kernel.org, Stephane Eranian , Ian Rogers Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org When adding event groups to the group list, insert them in size order. This performs an insertion sort on the group list. By placing the largest groups at the front of the group list it is possible to see if a larger group contains the same events as a later group. This can make the later group redundant - it can reuse the events from the large group. A later patch will add this sharing. Signed-off-by: Ian Rogers --- tools/perf/util/metricgroup.c | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/tools/perf/util/metricgroup.c b/tools/perf/util/metricgroup.c index 0a00c0f87872..25e3e8df6b45 100644 --- a/tools/perf/util/metricgroup.c +++ b/tools/perf/util/metricgroup.c @@ -519,7 +519,21 @@ static int __metricgroup__add_metric(struct list_head *group_list, return -EINVAL; } - list_add_tail(&eg->nd, group_list); + if (list_empty(group_list)) + list_add(&eg->nd, group_list); + else { + struct list_head *pos; + + /* Place the largest groups at the front. */ + list_for_each_prev(pos, group_list) { + struct egroup *old = list_entry(pos, struct egroup, nd); + + if (hashmap__size(&eg->pctx.ids) <= + hashmap__size(&old->pctx.ids)) + break; + } + list_add(&eg->nd, pos); + } return 0; } From patchwork Thu May 7 08:14:36 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ian Rogers X-Patchwork-Id: 1285004 X-Patchwork-Delegate: bpf@iogearbox.net Return-Path: X-Original-To: incoming-bpf@patchwork.ozlabs.org Delivered-To: patchwork-incoming-bpf@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=vger.kernel.org (client-ip=23.128.96.18; helo=vger.kernel.org; envelope-from=bpf-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=google.com header.i=@google.com header.a=rsa-sha256 header.s=20161025 header.b=DnIDWylk; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by ozlabs.org (Postfix) with ESMTP id 49HmV24dbqz9sSx for ; Thu, 7 May 2020 18:15:06 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726093AbgEGIPF (ORCPT ); Thu, 7 May 2020 04:15:05 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:47012 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-FAIL-OK-FAIL) by vger.kernel.org with ESMTP id S1726579AbgEGIPD (ORCPT ); Thu, 7 May 2020 04:15:03 -0400 Received: from mail-yb1-xb49.google.com (mail-yb1-xb49.google.com [IPv6:2607:f8b0:4864:20::b49]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 0CAB5C061BD3 for ; Thu, 7 May 2020 01:15:02 -0700 (PDT) Received: by mail-yb1-xb49.google.com with SMTP id x13so6005835ybg.23 for ; Thu, 07 May 2020 01:15:02 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20161025; h=date:in-reply-to:message-id:mime-version:references:subject:from:to :cc; bh=x8VCoNbOxLZFLMlYxTaRHwkq1NLOLyg87hzu7d14hyY=; b=DnIDWylkv4QP0E/qzQWQUCOw7DqAcUr3dRnGPEmlynHVcgCTSSNtA34J5/WXyDy/aP ngFsSIAbn63mO9dCCMLqNc3lZvV1x6HE7yJHCH8kUOPz+osOzAkEMLoD85q/cvoCppbw WAkFdMs1zJurIznD2whL+nIGeLl4D3OjIh9edCTiXHsgxu1WKRpnKw7KWh8xRzsy/U9/ aZkK1eF48qBvbFmqvtFI9UkiW87sJD4lVGmj5AgzvrWz0P/0S2o60DvWmM5aw+hD0cCg PQTUYFUCFZRmmyYktlnTmLdcOxiks64/8k0cWu2D7wedXZNPmJqnnQN+zXCzl0eICorv D9pA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc; bh=x8VCoNbOxLZFLMlYxTaRHwkq1NLOLyg87hzu7d14hyY=; b=IFHx96rsSfGDmsX8kTcl6autUyYf93J7vNw80lKbZjp4wokU3W6pZy/bHcCz9mPuVb 5+oONjoucuCVCwezcps/fbHtrlH7XJbwQo+uaxztXyZpy6keULA/qdicgRcR3ExjGfV5 YYHlZhTU6TTYXH/tfWX8GfMW7149u8ngT7lsnDTKazPqobqR9inqZHSLNKsGinvWaqkc DpIJlbTCbLHjqUGl3BZXUSPZlglL4WsZQXuX5HugFI46mR+k+ui0bqMnsDG9cezfGrNP 4OK130SKwgmBi/OciAMXha+aKVUh8zW9rTE7Gjuzl5VwV1X3twByXtBwDE6gVdZinybL +NEQ== X-Gm-Message-State: AGi0PubQhgsExbQL+obh543w0H25F55CeXnpWGAacXXamlcIVA1/7ghy 0943QRwHe/byVc9reuCfVQl8reAeQ9ql X-Google-Smtp-Source: APiQypL08ol3QAGdJ7KqVpm246M96AzQ5bgXecR762VCaNSOfpazYEMEu4altrjVLdXdV0ZaiO5/RSEmHw81 X-Received: by 2002:a25:8b02:: with SMTP id i2mr20129800ybl.283.1588839301174; Thu, 07 May 2020 01:15:01 -0700 (PDT) Date: Thu, 7 May 2020 01:14:36 -0700 In-Reply-To: <20200507081436.49071-1-irogers@google.com> Message-Id: <20200507081436.49071-8-irogers@google.com> Mime-Version: 1.0 References: <20200507081436.49071-1-irogers@google.com> X-Mailer: git-send-email 2.26.2.526.g744177e7f7-goog Subject: [RFC PATCH 7/7] perf metricgroup: remove duped metric group events From: Ian Rogers To: Peter Zijlstra , Ingo Molnar , Arnaldo Carvalho de Melo , Mark Rutland , Alexander Shishkin , Jiri Olsa , Namhyung Kim , Alexei Starovoitov , Daniel Borkmann , Martin KaFai Lau , Song Liu , Yonghong Song , Andrii Nakryiko , John Fastabend , KP Singh , Kajol Jain , Andi Kleen , John Garry , Jin Yao , Kan Liang , Cong Wang , Kim Phillips , linux-kernel@vger.kernel.org Cc: netdev@vger.kernel.org, bpf@vger.kernel.org, linux-perf-users@vger.kernel.org, Stephane Eranian , Ian Rogers Sender: bpf-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: bpf@vger.kernel.org A metric group contains multiple metrics. These metrics may use the same events. If metrics use separate events then it leads to more multiplexing and overall metric counts fail to sum to 100%. Modify how metrics are associated with events so that if the events in an earlier group satisfy the current metric, the same events are used. A record of used events is kept and at the end of processing unnecessary events are eliminated. Before: $ perf stat -a -M TopDownL1 sleep 1 Performance counter stats for 'system wide': 920,211,343 uops_issued.any # 0.5 Backend_Bound (16.56%) 1,977,733,128 idq_uops_not_delivered.core (16.56%) 51,668,510 int_misc.recovery_cycles (16.56%) 732,305,692 uops_retired.retire_slots (16.56%) 1,497,621,849 cycles (16.56%) 721,098,274 uops_issued.any # 0.1 Bad_Speculation (16.79%) 1,332,681,791 cycles (16.79%) 552,475,482 uops_retired.retire_slots (16.79%) 47,708,340 int_misc.recovery_cycles (16.79%) 1,383,713,292 cycles # 0.4 Frontend_Bound (16.76%) 2,013,757,701 idq_uops_not_delivered.core (16.76%) 1,373,363,790 cycles # 0.1 Retiring (33.54%) 577,302,589 uops_retired.retire_slots (33.54%) 392,766,987 inst_retired.any # 0.3 IPC (50.24%) 1,351,873,350 cpu_clk_unhalted.thread (50.24%) 1,332,510,318 cycles # 5330041272.0 SLOTS (49.90%) 1.006336145 seconds time elapsed After: $ perf stat -a -M TopDownL1 sleep 1 Performance counter stats for 'system wide': 765,949,145 uops_issued.any # 0.1 Bad_Speculation # 0.5 Backend_Bound (50.09%) 1,883,830,591 idq_uops_not_delivered.core # 0.3 Frontend_Bound (50.09%) 48,237,080 int_misc.recovery_cycles (50.09%) 581,798,385 uops_retired.retire_slots # 0.1 Retiring (50.09%) 1,361,628,527 cycles # 5446514108.0 SLOTS (50.09%) 391,415,714 inst_retired.any # 0.3 IPC (49.91%) 1,336,486,781 cpu_clk_unhalted.thread (49.91%) 1.005469298 seconds time elapsed Note: Bad_Speculation + Backend_Bound + Frontend_Bound + Retiring = 100% after, where as before it is 110%. After there are 2 groups, whereas before there are 6. After the cycles event appears once, before it appeared 5 times. Signed-off-by: Ian Rogers --- tools/perf/util/metricgroup.c | 97 ++++++++++++++++++++++------------- 1 file changed, 61 insertions(+), 36 deletions(-) diff --git a/tools/perf/util/metricgroup.c b/tools/perf/util/metricgroup.c index 25e3e8df6b45..8bb2aeeb70ad 100644 --- a/tools/perf/util/metricgroup.c +++ b/tools/perf/util/metricgroup.c @@ -93,44 +93,72 @@ struct egroup { bool has_constraint; }; +/** + * Find a group of events in perf_evlist that correpond to those from a parsed + * metric expression. + * @perf_evlist: a list of events something like: {metric1 leader, metric1 + * sibling, metric1 sibling}:W,duration_time,{metric2 leader, metric2 sibling, + * metric2 sibling}:W,duration_time + * @pctx: the parse context for the metric expression. + * @has_constraint: is there a contraint on the group of events? In which case + * the events won't be grouped. + * @metric_events: out argument, null terminated array of evsel's associated + * with the metric. + * @evlist_used: in/out argument, bitmap tracking which evlist events are used. + * @return the first metric event or NULL on failure. + */ static struct evsel *find_evsel_group(struct evlist *perf_evlist, struct expr_parse_ctx *pctx, + bool has_constraint, struct evsel **metric_events, unsigned long *evlist_used) { - struct evsel *ev; - bool leader_found; - const size_t idnum = hashmap__size(&pctx->ids); - size_t i = 0; - int j = 0; - double *val_ptr; + struct evsel *ev, *current_leader = NULL; + double *val_ptr; + int i = 0, matched_events = 0, events_to_match; + const int idnum = (int)hashmap__size(&pctx->ids); + + /* duration_time is grouped separately. */ + if (!has_constraint && + hashmap__find(&pctx->ids, "duration_time", (void**)&val_ptr)) + events_to_match = idnum - 1; + else + events_to_match = idnum; evlist__for_each_entry (perf_evlist, ev) { - if (test_bit(j++, evlist_used)) + /* + * Events with a constraint aren't grouped and match the first + * events available. + */ + if (has_constraint && ev->weak_group) continue; - if (hashmap__find(&pctx->ids, ev->name, (void**)&val_ptr)) { - if (!metric_events[i]) - metric_events[i] = ev; - i++; - if (i == idnum) - break; - } else { - /* Discard the whole match and start again */ - i = 0; + if (!has_constraint && ev->leader != current_leader) { + /* + * Start of a new group, discard the whole match and + * start again. + */ + matched_events = 0; memset(metric_events, 0, sizeof(struct evsel *) * idnum); + current_leader = ev->leader; + } + if (hashmap__find(&pctx->ids, ev->name, (void**)&val_ptr)) + metric_events[matched_events++] = ev; + if (matched_events == events_to_match) + break; + } - if (hashmap__find(&pctx->ids, ev->name, (void**)&val_ptr)) { - if (!metric_events[i]) - metric_events[i] = ev; - i++; - if (i == idnum) - break; + if (events_to_match != idnum) { + /* Add the first duration_time. */ + evlist__for_each_entry (perf_evlist, ev) { + if (!strcmp(ev->name, "duration_time")) { + metric_events[matched_events++] = ev; + break; } } } - if (i != idnum) { + if (matched_events != idnum) { /* Not whole match */ return NULL; } @@ -138,18 +166,8 @@ static struct evsel *find_evsel_group(struct evlist *perf_evlist, metric_events[idnum] = NULL; for (i = 0; i < idnum; i++) { - leader_found = false; - evlist__for_each_entry(perf_evlist, ev) { - if (!leader_found && (ev == metric_events[i])) - leader_found = true; - - if (leader_found && - !strcmp(ev->name, metric_events[i]->name)) { - ev->metric_leader = metric_events[i]; - } - j++; - } ev = metric_events[i]; + ev->metric_leader = ev; set_bit(ev->idx, evlist_used); } @@ -165,7 +183,7 @@ static int metricgroup__setup_events(struct list_head *groups, int i = 0; int ret = 0; struct egroup *eg; - struct evsel *evsel; + struct evsel *evsel, *tmp; unsigned long *evlist_used; evlist_used = bitmap_alloc(perf_evlist->core.nr_entries); @@ -181,7 +199,8 @@ static int metricgroup__setup_events(struct list_head *groups, ret = -ENOMEM; break; } - evsel = find_evsel_group(perf_evlist, &eg->pctx, metric_events, + evsel = find_evsel_group(perf_evlist, &eg->pctx, + eg->has_constraint, metric_events, evlist_used); if (!evsel) { pr_debug("Cannot resolve %s: %s\n", @@ -211,6 +230,12 @@ static int metricgroup__setup_events(struct list_head *groups, list_add(&expr->nd, &me->head); } + evlist__for_each_entry_safe (perf_evlist, tmp, evsel) { + if (!test_bit(evsel->idx, evlist_used)) { + evlist__remove(perf_evlist, evsel); + evsel__delete(evsel); + } + } bitmap_free(evlist_used); return ret;