From patchwork Fri May 8 05:36:17 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ian Rogers X-Patchwork-Id: 219642 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-17.4 required=3.0 tests=DKIMWL_WL_MED, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH, MAILING_LIST_MULTI, SIGNED_OFF_BY, SPF_HELO_NONE, SPF_PASS, USER_AGENT_GIT, USER_IN_DEF_DKIM_WL autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 0D09BC38A2A for ; Fri, 8 May 2020 05:38:10 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id D815E208D6 for ; Fri, 8 May 2020 05:38:09 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="qRFdoz0o" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1725897AbgEHFiI (ORCPT ); Fri, 8 May 2020 01:38:08 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:49294 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726815AbgEHFgi (ORCPT ); Fri, 8 May 2020 01:36:38 -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 C7064C05BD0C for ; Thu, 7 May 2020 22:36:37 -0700 (PDT) Received: by mail-qv1-xf4a.google.com with SMTP id w9so665731qvs.22 for ; Thu, 07 May 2020 22:36:37 -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=JjOXEdThPrX0ZqK5ziVYe2R9lvfX0D5b1eKQZ5WMkmg=; b=qRFdoz0oViVdbSdesJ3uOeuhDDOQyvokV4ju81NN6O+S1uHObHDF91I90PuVuFQgd7 KwioLoJmPgoXyy0yyOOiaWRTg8i5QTFA1figp4DmzWUR4OblfDzxzDDygMv5lEcKHNqt a+PFpq6LnOTFsYjiNyCTl/r94BKPcG4G3f9id/nYN9hUComV20GXljR0SRIVt1DBdtkI Jz2fBOqYxLVdpVZqFBDJ+JLPDpFdnHZaFp27mXJx+BpM4kN9Q/xsomKcgGJCgdy6Eeqc 3GQDBDuGMKrfUaor2heUfaiY7zeu6nIwtMauja5FrlQlCPUw+whJtTSWcd5fDBWCKfRH 2dIw== 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=JjOXEdThPrX0ZqK5ziVYe2R9lvfX0D5b1eKQZ5WMkmg=; b=gTK/1UKotWsrVZltsbM2XNBFyY3Z1xPX8OzEYuMNJPW6zh3SCKTbKn67G2H4Bq6VJ6 a70hpF71oIzpjCqyCuzigZHk234m7kB1f4OL4A0vIMLo1XtCxLwblFV0YW5CH+v5McUX kommbxkOZTuEDBfnMrFMOtHM8REJ90MWzMlLHke3Ik/ytuhEAuiHrCuALfbm2lO7YllK P4Wn5Mbg0jjbvuCC709JHB4f28n5c9Mfqbs3oKeOhscdkAxczLwpmhOlW48oiTqbipXZ xvRiGZhiltq67xk06CB5EJu76WVVHXsdfeNjZb8O0t2b8riqmcTUpaDjMm8iIx3QRKq0 8TRQ== X-Gm-Message-State: AGi0PuafeDA+64MiR32l9PiHwVS5ouwd7W3jFT+mBTOb7Y/Il/oNKChM hDNSbaP13CM0qt3F18wUplPs277qlX+X X-Google-Smtp-Source: APiQypKvMFNt25xIWeK6xJSZCn3nl+Bg72nqAKczepbICMLXbkiJMtJn0uOTEu5BJdnjYtBxaxEFzB1VYPzq X-Received: by 2002:ad4:4a8b:: with SMTP id h11mr1008735qvx.210.1588916196931; Thu, 07 May 2020 22:36:36 -0700 (PDT) Date: Thu, 7 May 2020 22:36:17 -0700 In-Reply-To: <20200508053629.210324-1-irogers@google.com> Message-Id: <20200508053629.210324-3-irogers@google.com> Mime-Version: 1.0 References: <20200508053629.210324-1-irogers@google.com> X-Mailer: git-send-email 2.26.2.645.ge9eca65c58-goog Subject: [RFC PATCH v3 02/14] perf test: improve pmu event metric testing 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, Vince Weaver , Stephane Eranian , Ian Rogers Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org Add a basic floating point number test to expr. Break pmu-events test into 2 and add a test to verify that all pmu metric expressions simply parse. Try to parse all metric ids/events, failing if metrics for the current architecture fail to parse. Tested on skylakex with the patch set in place. May fail on other architectures if metrics are invalid. Signed-off-by: Ian Rogers --- tools/perf/tests/builtin-test.c | 5 + tools/perf/tests/expr.c | 1 + tools/perf/tests/pmu-events.c | 158 ++++++++++++++++++++++++++++++-- tools/perf/tests/tests.h | 2 + 4 files changed, 160 insertions(+), 6 deletions(-) diff --git a/tools/perf/tests/builtin-test.c b/tools/perf/tests/builtin-test.c index 3471ec52ea11..8147c17c71ab 100644 --- a/tools/perf/tests/builtin-test.c +++ b/tools/perf/tests/builtin-test.c @@ -75,6 +75,11 @@ static struct test generic_tests[] = { { .desc = "PMU events", .func = test__pmu_events, + .subtest = { + .get_nr = test__pmu_events_subtest_get_nr, + .get_desc = test__pmu_events_subtest_get_desc, + }, + }, { .desc = "DSO data read", diff --git a/tools/perf/tests/expr.c b/tools/perf/tests/expr.c index f9e8e5628836..3f742612776a 100644 --- a/tools/perf/tests/expr.c +++ b/tools/perf/tests/expr.c @@ -39,6 +39,7 @@ int test__expr(struct test *t __maybe_unused, int subtest __maybe_unused) ret |= test(&ctx, "min(1,2) + 1", 2); ret |= test(&ctx, "max(1,2) + 1", 3); ret |= test(&ctx, "1+1 if 3*4 else 0", 2); + ret |= test(&ctx, "1.1 + 2.1", 3.2); if (ret) return ret; diff --git a/tools/perf/tests/pmu-events.c b/tools/perf/tests/pmu-events.c index d64261da8bf7..c18b9ce8cace 100644 --- a/tools/perf/tests/pmu-events.c +++ b/tools/perf/tests/pmu-events.c @@ -8,6 +8,10 @@ #include #include "debug.h" #include "../pmu-events/pmu-events.h" +#include "util/evlist.h" +#include "util/expr.h" +#include "util/parse-events.h" +#include struct perf_pmu_test_event { struct pmu_event event; @@ -144,7 +148,7 @@ static struct pmu_events_map *__test_pmu_get_events_map(void) } /* Verify generated events from pmu-events.c is as expected */ -static int __test_pmu_event_table(void) +static int test_pmu_event_table(void) { struct pmu_events_map *map = __test_pmu_get_events_map(); struct pmu_event *table; @@ -347,14 +351,11 @@ static int __test__pmu_event_aliases(char *pmu_name, int *count) return res; } -int test__pmu_events(struct test *test __maybe_unused, - int subtest __maybe_unused) + +static int test_aliases(void) { struct perf_pmu *pmu = NULL; - if (__test_pmu_event_table()) - return -1; - while ((pmu = perf_pmu__scan(pmu)) != NULL) { int count = 0; @@ -377,3 +378,148 @@ int test__pmu_events(struct test *test __maybe_unused, return 0; } + +static bool is_number(const char *str) +{ + size_t i; + + for (i = 0; i < strlen(str); i++) { + if (!isdigit(str[i]) && str[i] != '.') + return false; + } + return true; +} + +static int check_parse_id(const char *id, bool same_cpu, struct pmu_event *pe) +{ + struct parse_events_error error; + struct evlist *evlist; + int ret; + + /* Numbers are always valid. */ + if (is_number(id)) + return 0; + + evlist = evlist__new(); + memset(&error, 0, sizeof(error)); + ret = parse_events(evlist, id, &error); + if (ret && same_cpu) { + fprintf(stderr, + "\nWARNING: Parse event failed metric '%s' id '%s' expr '%s'\n", + pe->metric_name, id, pe->metric_expr); + fprintf(stderr, "Error string '%s' help '%s'\n", + error.str, error.help); + } else if (ret) { + pr_debug3("Parse event failed, but for an event that may not be supported by this CPU.\nid '%s' metric '%s' expr '%s'\n", + id, pe->metric_name, pe->metric_expr); + } + evlist__delete(evlist); + free(error.str); + free(error.help); + free(error.first_str); + free(error.first_help); + /* TODO: too many metrics are broken to fail on this test currently. */ + return 0; +} + +static int test_parsing(void) +{ + struct pmu_events_map *cpus_map = perf_pmu__find_map(NULL); + 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; + + i = 0; + for (;;) { + map = &pmu_events_map[i++]; + if (!map->table) { + map = NULL; + break; + } + j = 0; + for (;;) { + 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) { + 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); + pr_debug("On expression %s\n", pe->metric_expr); + ret++; + continue; + } + expr__ctx_init(&ctx); + + /* + * Add all ids with a made up value. The value may + * 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); + + for (k = 0; k < idnum; k++) { + if (check_parse_id(ids[k], map == cpus_map, pe)) + ret++; + } + + if (expr__parse(&result, &ctx, pe->metric_expr, 0)) { + pr_debug("Parse failed for map %s %s %s\n", + map->cpuid, map->version, map->type); + pr_debug("On metric %s\n", pe->metric_name); + pr_debug("On expression %s\n", pe->metric_expr); + ret++; + } + for (k = 0; k < idnum; k++) + zfree(&ids[k]); + free(ids); + } + } + return ret; +} + +static const struct { + int (*func)(void); + const char *desc; +} pmu_events_testcase_table[] = { + { + .func = test_pmu_event_table, + .desc = "PMU event table sanity", + }, + { + .func = test_aliases, + .desc = "PMU event map aliases", + }, + { + .func = test_parsing, + .desc = "Parsing of PMU event table metrics", + }, +}; + +const char *test__pmu_events_subtest_get_desc(int i) +{ + if (i < 0 || i >= (int)ARRAY_SIZE(pmu_events_testcase_table)) + return NULL; + return pmu_events_testcase_table[i].desc; +} + +int test__pmu_events_subtest_get_nr(void) +{ + return (int)ARRAY_SIZE(pmu_events_testcase_table); +} + +int test__pmu_events(struct test *test __maybe_unused, int i) +{ + if (i < 0 || i >= (int)ARRAY_SIZE(pmu_events_testcase_table)) + return TEST_FAIL; + return pmu_events_testcase_table[i].func(); +} diff --git a/tools/perf/tests/tests.h b/tools/perf/tests/tests.h index d6d4ac34eeb7..8e316c30ed3c 100644 --- a/tools/perf/tests/tests.h +++ b/tools/perf/tests/tests.h @@ -50,6 +50,8 @@ int test__perf_evsel__tp_sched_test(struct test *test, int subtest); int test__syscall_openat_tp_fields(struct test *test, int subtest); int test__pmu(struct test *test, int subtest); int test__pmu_events(struct test *test, int subtest); +const char *test__pmu_events_subtest_get_desc(int subtest); +int test__pmu_events_subtest_get_nr(void); int test__attr(struct test *test, int subtest); int test__dso_data(struct test *test, int subtest); int test__dso_data_cache(struct test *test, int subtest); From patchwork Fri May 8 05:36:19 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ian Rogers X-Patchwork-Id: 219643 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-17.4 required=3.0 tests=DKIMWL_WL_MED, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH, MAILING_LIST_MULTI, SIGNED_OFF_BY, SPF_HELO_NONE, SPF_PASS, USER_AGENT_GIT, USER_IN_DEF_DKIM_WL autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 4E111C4724C for ; Fri, 8 May 2020 05:37:57 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 2FFD9208CA for ; Fri, 8 May 2020 05:37:57 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="jZ8/3BzU" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727971AbgEHFh4 (ORCPT ); Fri, 8 May 2020 01:37:56 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:49312 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726948AbgEHFgl (ORCPT ); Fri, 8 May 2020 01:36:41 -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 74C84C05BD0D for ; Thu, 7 May 2020 22:36:41 -0700 (PDT) Received: by mail-yb1-xb49.google.com with SMTP id y7so750349ybj.15 for ; Thu, 07 May 2020 22:36:41 -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=EMaoPBnsp496f8fnle4PLwTyhTwnaVEb2fZ0BoIlE/s=; b=jZ8/3BzUau6j8ZEvbsjxAuGI7hb6DTIvN/+4pZeSwdomRiSNh85BVtF9D8gUSNVzGW 0eWncZr8l/llXRWz7VqOOZykXeBtJ3SKKEDwFOtudoKFQnaFGvJxJmPF2nVefWSW6T1N ujEs8CCMrw76bYxjsNxUwbOVzos4CsPvDRMCd5/PW/oSuWhkpIA3lRzQjco0kInXDbPm 8LmrpY+BMC3pKeUMPrR8rm5su1lRDsLumbV0h+zp0IpapZChomkqsjjuZcY5Cf2QXSOm iDcH2pbz97F5r2NX7V3MQ5S2ooUU3tb01J5+66RrtZtTIz6KF+NJhOkHR6wRY5hgklGo l52A== 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=EMaoPBnsp496f8fnle4PLwTyhTwnaVEb2fZ0BoIlE/s=; b=jY8mnsORxBySYtmMN/MRXFVBge73P+QAyS7Fm4CnKnXzTasNeWmwgd0nq5Zq1xW/Bn TSxtfDlYDwZGG8AAq2KeWuR3wNHaAkBDEpGvrz7d6Wub/sDMAGF2LQ4BStdCYKbt8wFR Li3+xe8y9eCFmhBrW6Ebb0/08hJZ633NbtjjDSGVc++PlMENOUamwEyD6OgvB2V1eEBd zeTJT9ydlB2zxou8mY6fw289yEZD24OvkXSCH4kLXpfQj/wTiojKyq8VudUEpVqtzxJ+ QQ0J/tJh11UKe8FVqJ/nvgZK0PSygYqbf5TZDohjQYItsMN0SchHR3odVie6gp9ghiYv izAA== X-Gm-Message-State: AGi0PuYX2mgTbMNG/+ws5/py9RJ1l5wpqMO3k0xqmhINw6Ob0QZUSqO4 97vuV502nJyU6zUzc5SZQdFSOIN2lVy0 X-Google-Smtp-Source: APiQypLQw6jwdcVMaZFQOy5PNutRW9zCylVfFgkKjPKR5hivKEFBHzRJZKkDf50HqYjqdKRWSm4C4Wle3tYc X-Received: by 2002:a25:51c1:: with SMTP id f184mr1837043ybb.448.1588916200664; Thu, 07 May 2020 22:36:40 -0700 (PDT) Date: Thu, 7 May 2020 22:36:19 -0700 In-Reply-To: <20200508053629.210324-1-irogers@google.com> Message-Id: <20200508053629.210324-5-irogers@google.com> Mime-Version: 1.0 References: <20200508053629.210324-1-irogers@google.com> X-Mailer: git-send-email 2.26.2.645.ge9eca65c58-goog Subject: [RFC PATCH v3 04/14] libbpf: Fix memory leak and possible double-free in hashmap__clear 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, Vince Weaver , Stephane Eranian , Alston Tang , Ian Rogers Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org From: Andrii Nakryiko Fix memory leak in hashmap_clear() not freeing hashmap_entry structs for each of the remaining entries. Also NULL-out bucket list to prevent possible double-free between hashmap__clear() and hashmap__free(). Running test_progs-asan flavor clearly showed this problem. Reported-by: Alston Tang Signed-off-by: Andrii Nakryiko Signed-off-by: Alexei Starovoitov Link: https://lore.kernel.org/bpf/20200429012111.277390-5-andriin@fb.com Signed-off-by: Ian Rogers --- tools/lib/bpf/hashmap.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/tools/lib/bpf/hashmap.c b/tools/lib/bpf/hashmap.c index 54c30c802070..cffb96202e0d 100644 --- a/tools/lib/bpf/hashmap.c +++ b/tools/lib/bpf/hashmap.c @@ -59,7 +59,14 @@ struct hashmap *hashmap__new(hashmap_hash_fn hash_fn, void hashmap__clear(struct hashmap *map) { + struct hashmap_entry *cur, *tmp; + int bkt; + + hashmap__for_each_entry_safe(map, cur, tmp, bkt) { + free(cur); + } free(map->buckets); + map->buckets = NULL; map->cap = map->cap_bits = map->sz = 0; } From patchwork Fri May 8 05:36:20 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ian Rogers X-Patchwork-Id: 219644 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-17.4 required=3.0 tests=DKIMWL_WL_MED, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH, MAILING_LIST_MULTI, SIGNED_OFF_BY, SPF_HELO_NONE, SPF_PASS, USER_AGENT_GIT, USER_IN_DEF_DKIM_WL autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id F15E8C47247 for ; Fri, 8 May 2020 05:37:52 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id D296D208CA for ; Fri, 8 May 2020 05:37:52 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="s3XhVoaJ" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727777AbgEHFht (ORCPT ); Fri, 8 May 2020 01:37:49 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:49304 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727067AbgEHFgn (ORCPT ); Fri, 8 May 2020 01:36:43 -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 297A3C05BD0A for ; Thu, 7 May 2020 22:36:43 -0700 (PDT) Received: by mail-yb1-xb4a.google.com with SMTP id h185so774465ybg.6 for ; Thu, 07 May 2020 22:36:43 -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=kf/Nl54LdD1Myd4Q2ihfierbY9Agfscu2MTKHIAamr0=; b=s3XhVoaJuVP7bfI29XP+1KV8iq/zlxEkxZpwETde6utnftcO1DZWav49uNhLe9yLot +5/BdgyKr/VjJ3NqNKoK+eh6gBwyC3Oa7xXwAXVvKgWiZxGCTrBsX0PWDwuZFt0LALxS W88zJ02aK0yyrAQaCPjn2L6BbibphSG3vz7GsueuTLhoYcdhPiz8nEzV/5ntVLYPHUSR Wyy7zFsHLy5pXaIkJvbLXXRvpynpq8+VYRCoy8O1Kppx1y2azcHzoMe6RCGLINLMBrbL fvGBdGFk+cDjvAo7kCUIID/P2Z5ZFqkjEKrZGP8BBeYhQ4u4+ELHUH0kaMTwORFRbnSK SULg== 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=kf/Nl54LdD1Myd4Q2ihfierbY9Agfscu2MTKHIAamr0=; b=MeXLzdZ+sVUvluE6vramsaltzqLlgKl0/g3AYYXTOlZn27AtOhwxQGtKBwS+R/zavK d80g+7+7X6k1FkrefMCRlOd9wpn0kCydKBdwFO670cZkBrjJcRUHKakflXHzRHNz31Ns MENCj4VhbOt4zSKw7CBSkKVbVit/+xYMM1vMe7d2MSAR/OzxS5klN2X3gRqkCJ9FWqlI blofU0riiO6Uwt9zuyTcl6l+h23OZVfZ2gQSzBfk6h0lwqR8OcAKThcKMPKWZRsa29xi 01fztllYveoHo/vcHdpv2UHVTaL8XeNbBlcCEJrjrXuaC0V1Kex/iI97k3rFEOPjDsZi JGGQ== X-Gm-Message-State: AGi0PuZL5wdWrrSSrt2gq8k8eXrII+EbJ9aNv+AOLUfF4LRW3m4MpFtO lJDu/V1aVe32lVGOVfvFHJkZIWenqzMR X-Google-Smtp-Source: APiQypKOjaO6fI6votAtJkqNtpxhTPzscSvTlH8sv81/G65sdjlnWRsXh9hMb8MSR2pcQmAAjFHFfSeqH1EV X-Received: by 2002:a25:cf50:: with SMTP id f77mr1986942ybg.19.1588916202354; Thu, 07 May 2020 22:36:42 -0700 (PDT) Date: Thu, 7 May 2020 22:36:20 -0700 In-Reply-To: <20200508053629.210324-1-irogers@google.com> Message-Id: <20200508053629.210324-6-irogers@google.com> Mime-Version: 1.0 References: <20200508053629.210324-1-irogers@google.com> X-Mailer: git-send-email 2.26.2.645.ge9eca65c58-goog Subject: [RFC PATCH v3 05/14] perf expr: fix memory leaks in bison 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, Vince Weaver , Stephane Eranian , Ian Rogers Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org Add a destructor for strings to reclaim memory in the event of errors. Free the ID given for a lookup. Signed-off-by: Ian Rogers --- tools/perf/util/expr.y | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tools/perf/util/expr.y b/tools/perf/util/expr.y index 21e82a1e11a2..3b49b230b111 100644 --- a/tools/perf/util/expr.y +++ b/tools/perf/util/expr.y @@ -27,6 +27,7 @@ %token EXPR_PARSE EXPR_OTHER EXPR_ERROR %token NUMBER %token ID +%destructor { free ($$); } %token MIN MAX IF ELSE SMT_ON %left MIN MAX IF %left '|' @@ -94,8 +95,10 @@ if_expr: expr: NUMBER | ID { if (lookup_id(ctx, $1, &$$) < 0) { pr_debug("%s not found\n", $1); + free($1); YYABORT; } + free($1); } | expr '|' expr { $$ = (long)$1 | (long)$3; } | expr '&' expr { $$ = (long)$1 & (long)$3; } From patchwork Fri May 8 05:36:22 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ian Rogers X-Patchwork-Id: 219648 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-17.4 required=3.0 tests=DKIMWL_WL_MED, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH, MAILING_LIST_MULTI, SIGNED_OFF_BY, SPF_HELO_NONE, SPF_PASS, USER_AGENT_GIT, USER_IN_DEF_DKIM_WL autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 4E80FC38A2A for ; Fri, 8 May 2020 05:36:51 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 07763208CA for ; Fri, 8 May 2020 05:36:51 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="fmP3MUBx" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727118AbgEHFgt (ORCPT ); Fri, 8 May 2020 01:36:49 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:49340 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727107AbgEHFgr (ORCPT ); Fri, 8 May 2020 01:36:47 -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 4576BC05BD09 for ; Thu, 7 May 2020 22:36:47 -0700 (PDT) Received: by mail-yb1-xb4a.google.com with SMTP id y189so755376ybc.14 for ; Thu, 07 May 2020 22:36:47 -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=jUtNc5VuiSSf4v5M7uiQ4wMAqQTfgQdTth2yiGp5mbo=; b=fmP3MUBxMXT9npUORuVNHbVGcvLN7Vz6boneXg8TgkhtVcPxBa85TarpQmC18LvdSJ xY01VDEz0YIlO8tRPk8CXSzbSDofEW7YB0rob242P8UpgCfi4epveME8fxEhjGMdOAxd SZu8qm5T2QvLj53xXzPag8Uf0J2DDz+bJTqXvPMdQke1BAKGWTG0cUGGyBnZfJ1geNT8 +29NT4veMmr3PNPi572Mx+coGUwBtVAL6V3EhLe0ssbxLvO/F6CT+zlQ25pvRCMIWJV8 5EmmtHfZn5gZNtw4z6zrwpZeJrQV42oUvOncHIs4wWiw8ddkYesAqp0whUhfKm3CFWAu w0zQ== 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=jUtNc5VuiSSf4v5M7uiQ4wMAqQTfgQdTth2yiGp5mbo=; b=J0xegdKDxrctmAkLE7fYoyq+KRbYhrKdGOVy0tC4WDIsGxYiTJpwM3zpPcm1NtbAoN P/YByClVjdB8R8fw5dMjDTqhHSxPuCM0cEmxCIv0AhUtkMJlKmfuTK5lJzeiAXssG0u+ +q9hWAKD9s9GF23sFFZ+tdO5wEGz1gLSv29hMZ4IvU2Fdre19Zt92DlRXi/yCkZKnV0V yFqGAAv6OCIHP+mDT5QjPlFGrMuK/s/6swJqeF4A5cPQ0xovBOO40vcocp/uxu5P3ilF 7X46futyyxqanfAZhs5P/AdxV1XJaJcZmlo2ffq1GzM6t8vDZ1EWGny83CWZ2WPnEu6e 9P5g== X-Gm-Message-State: AGi0Puascf1dK9t34Z9tTZzTVjvH1ngNCpS4NCSXLJK0o/RpiK6FQkx6 WJVf84aa237edlPVirgxP1UAPcPltcMd X-Google-Smtp-Source: APiQypIkyrnH6H/vbpqPw716qbcLGXp/Vbv0rbCQvSRjw3Ra7/DVaiKu1d2QS7kSvIRxE6+gvKNfsp3jD9+A X-Received: by 2002:a25:6f86:: with SMTP id k128mr1982940ybc.305.1588916206358; Thu, 07 May 2020 22:36:46 -0700 (PDT) Date: Thu, 7 May 2020 22:36:22 -0700 In-Reply-To: <20200508053629.210324-1-irogers@google.com> Message-Id: <20200508053629.210324-8-irogers@google.com> Mime-Version: 1.0 References: <20200508053629.210324-1-irogers@google.com> X-Mailer: git-send-email 2.26.2.645.ge9eca65c58-goog Subject: [RFC PATCH v3 07/14] 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, Vince Weaver , 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 | 40 ++++++----- tools/perf/tests/pmu-events.c | 25 +++---- tools/perf/util/expr.c | 129 +++++++++++++++++++--------------- tools/perf/util/expr.h | 22 +++--- tools/perf/util/expr.y | 22 +----- tools/perf/util/metricgroup.c | 87 +++++++++++------------ tools/perf/util/stat-shadow.c | 49 ++++++++----- 7 files changed, 193 insertions(+), 181 deletions(-) diff --git a/tools/perf/tests/expr.c b/tools/perf/tests/expr.c index 3f742612776a..5e606fd5a2c6 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,29 @@ 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); + expr__find_other("EVENT1\\,param\\=?@ + EVENT2\\,param\\=?@", + 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..054550ee811c 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,17 @@ 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) { + expr__ctx_init(&ctx); + 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); @@ -457,18 +459,19 @@ static int test_parsing(void) ret++; continue; } - expr__ctx_init(&ctx); /* * Add all ids with a made up value. The value may * 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, strdup(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 +482,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..f64ab91c432b 100644 --- a/tools/perf/util/expr.c +++ b/tools/perf/util/expr.c @@ -4,25 +4,76 @@ #include "expr.h" #include "expr-bison.h" #include "expr-flex.h" +#include #ifdef PARSER_DEBUG extern int expr_debug; #endif +static size_t key_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 key_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; + + 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; - assert(ctx->num_ids < MAX_PARSE_ID); - idx = ctx->num_ids++; - ctx->ids[idx].name = name; - ctx->ids[idx].val = val; + 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, key_hash, key_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 +107,25 @@ __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 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 expr__find_other(const char *expr, const char *one, + struct expr_parse_ctx *ctx, 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..37be5a368d6e 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,8 @@ 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 +177,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 +418,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 +440,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 +499,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 +607,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 9bd7a8d2a858..c44dc814b377 100644 --- a/tools/perf/util/stat-shadow.c +++ b/tools/perf/util/stat-shadow.c @@ -323,35 +323,46 @@ 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 +371,8 @@ 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 +385,28 @@ 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 +751,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 +830,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 Fri May 8 05:36:25 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ian Rogers X-Patchwork-Id: 219645 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-17.4 required=3.0 tests=DKIMWL_WL_MED, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH, MAILING_LIST_MULTI, SIGNED_OFF_BY, SPF_HELO_NONE, SPF_PASS, USER_AGENT_GIT, USER_IN_DEF_DKIM_WL autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id C3F4FC38A2A for ; Fri, 8 May 2020 05:37:33 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id A435621582 for ; Fri, 8 May 2020 05:37:33 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="WdaMO2k2" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727924AbgEHFhc (ORCPT ); Fri, 8 May 2020 01:37:32 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:49380 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1725897AbgEHFgx (ORCPT ); Fri, 8 May 2020 01:36:53 -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 F2326C05BD0B for ; Thu, 7 May 2020 22:36:52 -0700 (PDT) Received: by mail-yb1-xb4a.google.com with SMTP id h185so774884ybg.6 for ; Thu, 07 May 2020 22:36: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=0QS1YqAYu664zYAVy5D9As+p1Vggn2+qgtokmxG8BMQ=; b=WdaMO2k2Y5pTljLKBJ0d+Y2TyM+fRid8W+wbZXFfMKUEmpNUE66nlFIgfWEtFPAr7L CqOKVwmwFYYlMF56xmSj5qCNhwYVnaRoUBy4pQUNYdHJsWcs8c3JahIOuVgpIz2UcSQb 82foWpW+AbFOOZpv2wCDJ0VZ6yWEgeoa3MDgb0c75ADt33hDUr2YKSlALKJCG4viXCoC AsR+VbfVak6o1lcWU78xIIR+SoOKJ7RM6N6ma5tNRUfR43R9WF+1LC/RSIMZIEdDWlGO TMOBH3b/anKG9yG4krGWerI0oEC9haNtALFX4AWIw+/B+DhKdCYovPJTGDGCXOM59qz8 WENQ== 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=0QS1YqAYu664zYAVy5D9As+p1Vggn2+qgtokmxG8BMQ=; b=WC+8eOwaHMuTcMJLR6/5tUsNe9XqhrBlk/vDzKAz6Zmadth8dthe3a3SW0aYVM94qG UhP/FIO0rcaCRAi6+PfW2qRduAOBXVZ+myTXAlPHbeSKnuSTtGIjXRDMNDJyFRAB9WKh HvA4TQg5Fu3DA1oPjoyxILiG04VNLFsCidXhMY8S1Y6nGx64HWhyhhmAaaiL+LR2RLpo Z3XbBdOo2mojxIcufFW+HHiBohxF02UFkKtTbm8JCY+e1hOaHY5F5FzcBzmbUA1fOScs 8zdFHDJ6z6ALQKKcpCOGSXQ2hZ5gofgwSDqWktaQca4vPPwhmcv2x60tXckIuDl9qcO/ JXRw== X-Gm-Message-State: AGi0PuZYvvaY5rnGMWXN0WldOCFt1xmEddxBJJlDYDokAQjO6Ify4jMi LY9JtzybvrelAgrKvaU6RS1fQmIzCcqn X-Google-Smtp-Source: APiQypJZ1+AqbfI+DjYgGYUs8urHT8j/MAgFPXvDoBMlgIUUiGiZxajQ4j6lYMcy7FGwHS6i6iEAD8GBx66/ X-Received: by 2002:a25:cb17:: with SMTP id b23mr1959004ybg.515.1588916212125; Thu, 07 May 2020 22:36:52 -0700 (PDT) Date: Thu, 7 May 2020 22:36:25 -0700 In-Reply-To: <20200508053629.210324-1-irogers@google.com> Message-Id: <20200508053629.210324-11-irogers@google.com> Mime-Version: 1.0 References: <20200508053629.210324-1-irogers@google.com> X-Mailer: git-send-email 2.26.2.645.ge9eca65c58-goog Subject: [RFC PATCH v3 10/14] 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, Vince Weaver , 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 | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/tools/perf/util/metricgroup.c b/tools/perf/util/metricgroup.c index 7e1725d61c39..2c684fd3c4e3 100644 --- a/tools/perf/util/metricgroup.c +++ b/tools/perf/util/metricgroup.c @@ -422,8 +422,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); @@ -433,20 +433,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) + 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 Fri May 8 05:36:26 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ian Rogers X-Patchwork-Id: 219646 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-17.4 required=3.0 tests=DKIMWL_WL_MED, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH, MAILING_LIST_MULTI, SIGNED_OFF_BY, SPF_HELO_NONE, SPF_PASS, USER_AGENT_GIT, USER_IN_DEF_DKIM_WL autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 02BAEC47247 for ; Fri, 8 May 2020 05:37:22 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id D293421655 for ; Fri, 8 May 2020 05:37:21 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="Lc+D+jRW" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727114AbgEHFg4 (ORCPT ); Fri, 8 May 2020 01:36:56 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:49394 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727801AbgEHFgz (ORCPT ); Fri, 8 May 2020 01:36:55 -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 0459FC05BD0A for ; Thu, 7 May 2020 22:36:55 -0700 (PDT) Received: by mail-qt1-x84a.google.com with SMTP id g55so629138qtk.14 for ; Thu, 07 May 2020 22:36: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=Nctu/+daGFSzTSwQhLTKLSNlu5IFhHkllWDjdeI4leQ=; b=Lc+D+jRWNuHK6kbY+a3EZSsBSkaZvdmcY0LS9V8TH4ctxNRf4DdrAGxPvNWHQ5CVpK FtlMI4ZZiU49toz/iF8K+aMytXHdlOPTKJWIS1/1NjALeg+fGWQ+wko9JTmDmbZvGgXQ QzPI2mmW/6Jm8Hfr0y23sbcLRr726ouqNXfXO6E7TlpJbVWwhCXACmhbZfCZ/V907GN9 a36/72deZ6+4rFc7aMDSWXo2u45hDfMkzbZ8DWPgLLF3Z5PZqJJjsDlMOBtNhpBQe6HS pLt9nHBJMwSpSzl377fL2Wa1lTtKV9IJpCIASa1yxbuBxiAdXLesWXLS8xthtN7DPjWJ T1Vw== 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=Nctu/+daGFSzTSwQhLTKLSNlu5IFhHkllWDjdeI4leQ=; b=lUNt5Mp9LvLTvNAZ5MdbGHDN2dGwBt/tgbbca0FTLo1HBMW1191xispbxOjVUABLio 4XfWd9wKnnvgZX11jSjDlL6eoA/wsHrKfbFs7EnpelgPLX/bq9egmZMaILLPDpDpttD2 htAo8kD7hQWBPkpnoWGjhWm9M7HPCRrDCZrG5jEfgn5flMKl6Zb0UzvE8frm6WIVd/rV UXvmcykR9nD/WS+mM7Uw/KJQ/h5hmgMii29HpvVQ10Fw4gh8ePWB7Y/8LBXgNpd+xsgf J/NAqQM0x+7arN2Ak55sEabBtOQ2plggfTn/MpkVHCDtDxRP4Woqt3IaSkPBkCs93YVz +xzw== X-Gm-Message-State: AGi0PubnCkjaGoh9U1jkzwUZWuP915I5Bjv3fYpRztj+QyNfC3XNJRZ1 gqIfhY+EJGnX7QQdY3WaVxgIUVIeqn/F X-Google-Smtp-Source: APiQypL1uvkQ72iK2J8WqG7nY7Hx2FBx6+zfvWI1PN3zCRzvT53dMH1hlsiZU1cCTp5d3kZxJYvsH9OSD+VR X-Received: by 2002:a0c:efc3:: with SMTP id a3mr1071972qvt.223.1588916214070; Thu, 07 May 2020 22:36:54 -0700 (PDT) Date: Thu, 7 May 2020 22:36:26 -0700 In-Reply-To: <20200508053629.210324-1-irogers@google.com> Message-Id: <20200508053629.210324-12-irogers@google.com> Mime-Version: 1.0 References: <20200508053629.210324-1-irogers@google.com> X-Mailer: git-send-email 2.26.2.645.ge9eca65c58-goog Subject: [RFC PATCH v3 11/14] 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, Vince Weaver , 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 2c684fd3c4e3..2a6456fa178b 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, @@ -497,8 +498,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; @@ -511,6 +512,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); @@ -518,14 +520,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; @@ -536,6 +530,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) @@ -554,7 +549,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; @@ -565,13 +561,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 Fri May 8 05:36:27 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ian Rogers X-Patchwork-Id: 219647 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-17.4 required=3.0 tests=DKIMWL_WL_MED, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH, MAILING_LIST_MULTI, SIGNED_OFF_BY, SPF_HELO_NONE, SPF_PASS, USER_AGENT_GIT, USER_IN_DEF_DKIM_WL autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id E6763C47257 for ; Fri, 8 May 2020 05:37:12 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id C7C8221655 for ; Fri, 8 May 2020 05:37:12 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="CbDfIOxV" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727835AbgEHFg7 (ORCPT ); Fri, 8 May 2020 01:36:59 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:49404 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727819AbgEHFg5 (ORCPT ); Fri, 8 May 2020 01:36:57 -0400 Received: from mail-qt1-x849.google.com (mail-qt1-x849.google.com [IPv6:2607:f8b0:4864:20::849]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id D693EC05BD43 for ; Thu, 7 May 2020 22:36:56 -0700 (PDT) Received: by mail-qt1-x849.google.com with SMTP id v18so598716qtq.22 for ; Thu, 07 May 2020 22:36: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=Qye1SVonTjqMOsVJuQeCBVCNLKV3+4pjVh0/bspBuQI=; b=CbDfIOxVT2dx5RZ83D4pkiUFNFhJ1sVAiBjizdkmRAvy0BO+EEXFy/kOCH2+kOlyzC 2HkZMRFi8zBHJVdpkv5SmTDm4wXrXSakYtZCKlFJy6GE9FCbZQS6v/BiCflmUiUKit5Q DtUESQzY5X6tgPPinxek9XaFvK95W5b2w1Vcxd4THyaoSj/8IfeWeMHFwOQ4niq6AI0h W1U0ZFn+S7qzVA6xC1h2trc43J0goe2fQ1PUJQwoPCsepiASp2TgeMIOv73mkynRu/mX T7oFZtsStM9SlRg7yw7whM1bd5C03VhGgYbFMoKesas0wrfRbgzNS2BNLzIJgkL0jl0I /xng== 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=Qye1SVonTjqMOsVJuQeCBVCNLKV3+4pjVh0/bspBuQI=; b=Bnw+iIwrz49huSHMO83f62WzyrfOZVw0S//92hDf3tn8MQLzmA0TkzNEftNfFdPMgq 4/wFjygJqOWmNAMpU+t1w0csfMrE7G1oJa0duhgwpHsAKlVJhSvMy/jUEv56yJu9Kgdj eGZU4ASHZSqiT4uxpuKeQpVedshj1rALHmE4FMgk28VDhDTbsKbOrC0EEnZhYZjsOm7i UiT2Qk7iFrZuMj15xOHBJBE/VJf6n4qOlnM3xEY2iEaSmyyyGWXIat3Kkk3kdLjNe3HX WgAPAkV6uZmXIVflkM8vgB9hLKTpmnGXA4cRJ2TdZdh/n0DOp3bu1VybTy8p04AwU2DT n62A== X-Gm-Message-State: AGi0Pua4+kx1sI5UTtK4vFo6/CSCJjbJccoSr4jxB44tkJUODjKNfRaN BzrAZR6hAqB2xuPRe2jpewHPpcrw1Vvu X-Google-Smtp-Source: APiQypJ1fookbhjSVt29vq8vulwRv7GbvsjbjS5kIOZ8ULGRiQnYVCkmIhCpb3LShI5EaEMa3+PzanIRhgqz X-Received: by 2002:a05:6214:18c9:: with SMTP id cy9mr1066619qvb.35.1588916215992; Thu, 07 May 2020 22:36:55 -0700 (PDT) Date: Thu, 7 May 2020 22:36:27 -0700 In-Reply-To: <20200508053629.210324-1-irogers@google.com> Message-Id: <20200508053629.210324-13-irogers@google.com> Mime-Version: 1.0 References: <20200508053629.210324-1-irogers@google.com> X-Mailer: git-send-email 2.26.2.645.ge9eca65c58-goog Subject: [RFC PATCH v3 12/14] 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, Vince Weaver , 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 2a6456fa178b..69fbff47089f 100644 --- a/tools/perf/util/metricgroup.c +++ b/tools/perf/util/metricgroup.c @@ -520,7 +520,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; }