From nobody Fri Jan 31 00:17:31 2025 Received: from mail-ed1-f73.google.com (mail-ed1-f73.google.com [209.85.208.73]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 7D39A1FE46F for ; Mon, 27 Jan 2025 09:59:25 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.208.73 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1737971967; cv=none; b=neyuUjbIBtoDvghyEpUNEEDl2zFNHX31XPIMdyjw6QmdN6QMZ7QND8uVLMRDrLtprntNH5ZowVD09qEi8/G8fneYOr+BFi2IDQtTf9Tr2nngKsKRJ965S5TJNSqqIJeStMmsFqMjOUshx1UwYG5kY+NAwheGr4Y5MdxdCBla8DM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1737971967; c=relaxed/simple; bh=7O0m46F8ICV6OKRIzDTCptkWRUW9yw0QnAtK3wP7ZIc=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=n7+GEQRYZLR0kieK9AVlCHlIWtJCtXnz+k1bhfLY6ZV15Xf98yBa1MpOVIQhei7g39BGUqQSqD2HjCy1LX9QS8UWec7+HX+4Ntc/gerGztEYBRaz06/fBd5CogclBoIlaAkot+qy9yKw5hHq412IZ+vPDxRezvYiEw0GIoFl4cI= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--dvyukov.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=EccBemID; arc=none smtp.client-ip=209.85.208.73 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--dvyukov.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="EccBemID" Received: by mail-ed1-f73.google.com with SMTP id 4fb4d7f45d1cf-5d3fe991854so4630476a12.0 for ; Mon, 27 Jan 2025 01:59:25 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1737971964; x=1738576764; darn=vger.kernel.org; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=z+zT3If5T8XsGWOeao9G4Z2Kmp0udWdvd9bpIxyWibE=; b=EccBemIDIF5n0uFXg411SJ0wus+bjohEi/vTE1unXrpmY6SqNYIJOw8NX2EgMxBO2Y 1IfUpV5oZ2fz8YI5rXSOdPtmNSSh2jY/FE+PWNmMHNQvoAHSzwcMaPP0SWC7CnZKoMyy /Xga9/IZFQvSjgYcekUo1ciZOtGrou1Kjl0peL41Q/fgeWzkPJ8Sf/pAxKDDcfm46mMR bIn/hX4qvFdLVg4OtOpeGj+bGE32fBoSen7Pbd/cSy5PK06TlO/Fui4eiQK9NSQl9t8h HxpijB6GK6SzGmzsK6YyzkTnj2A3DunyoLvrr6Bw9EhCOpIS3U2QgUHobg3rNmEaXGO3 r+rg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1737971964; x=1738576764; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=z+zT3If5T8XsGWOeao9G4Z2Kmp0udWdvd9bpIxyWibE=; b=wiBBtovOrVklBGMJXkQYFkGv0vMYSRDsMz8PZw2knemw14+vrmUtR6+bRSjkFKMhBO SejJIePzExFrwKlWUj21TvdgOOCoIDUmefa72zogLVYI70ochqfGR3msA0eD8AZwGwEs JSUqdY1yVw4r9bdBi2Jz6JEERHvB+EDs3MyMqeecFbIRXZpBURCugCf1e95dTgk3US3U rDL4h6M7ACUwPlKGnho5vIt/0XZFrtgaXpGzAq7+K98dFSTa3RAERVySE99Y9E5OpPLd 1ZII+Hg+pHRC1C4L6Rzi0Wqhwq6AQJGl3poF/yRAErMVf9Fp4r/mujqkbCnxILS2YrHd SsJA== X-Forwarded-Encrypted: i=1; AJvYcCW9PP6xr/FfuEtMDbeH3JXALiFOrd0CajGDlNeJ7KGsW0QmjDk1WBBBkJmrGnxEpur57h6jQtFDX4oBTFk=@vger.kernel.org X-Gm-Message-State: AOJu0Yx7ojwX/jzB9cedeEMoWjNIOF7EBaPzHewfc3S1pQWZyNdxY/PP 29q/MKs0C5feJgRrDp/mwhkR1zuoYWEwmEJbXZgsS6UKazWrlZKx5RngymA86Y9xCZL60SsWwRw ikahosw== X-Google-Smtp-Source: AGHT+IGWwuLONGcTFBCVg7atwfx3Q4Hvv7KuI65+C7jlFWWoZSTmOnQdAjp/iRS25wwoAQJomnx1DJLMe7jI X-Received: from edben25.prod.google.com ([2002:a05:6402:5299:b0:5d0:ccd2:6689]) (user=dvyukov job=prod-delivery.src-stubby-dispatcher) by 2002:a05:6402:2813:b0:5db:731d:4456 with SMTP id 4fb4d7f45d1cf-5db7db07839mr40739040a12.28.1737971963951; Mon, 27 Jan 2025 01:59:23 -0800 (PST) Date: Mon, 27 Jan 2025 10:58:51 +0100 In-Reply-To: Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: X-Mailer: git-send-email 2.48.1.262.g85cc9f2d1e-goog Message-ID: <289635b78c94222012184f0331a793741b6f7531.1737971364.git.dvyukov@google.com> Subject: [PATCH v3 4/7] perf report: Add parallelism filter From: Dmitry Vyukov To: namhyung@kernel.org, irogers@google.com Cc: linux-perf-users@vger.kernel.org, linux-kernel@vger.kernel.org, Dmitry Vyukov , Arnaldo Carvalho de Melo Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Add parallelism filter that can be used to look at specific parallelism levels only. The format is the same as cpu lists. For example: Only single-threaded samples: --parallelism=3D1 Low parallelism only: --parallelism=3D1-4 High parallelism only: --parallelism=3D64-128 Signed-off-by: Dmitry Vyukov Cc: Namhyung Kim Cc: Arnaldo Carvalho de Melo Cc: Ian Rogers Cc: linux-perf-users@vger.kernel.org Cc: linux-kernel@vger.kernel.org --- tools/perf/builtin-report.c | 5 ++++- tools/perf/util/event.c | 2 ++ tools/perf/util/hist.c | 31 +++++++++++++++++++++++++++++++ tools/perf/util/hist.h | 6 +++++- tools/perf/util/sort.c | 11 +++++++++++ tools/perf/util/symbol.c | 34 ++++++++++++++++++++++++++++++++++ tools/perf/util/symbol_conf.h | 4 ++++ 7 files changed, 91 insertions(+), 2 deletions(-) diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c index 14d49f0625881..2a19abdc869a1 100644 --- a/tools/perf/builtin-report.c +++ b/tools/perf/builtin-report.c @@ -1390,6 +1390,8 @@ int cmd_report(int argc, const char **argv) symbol__config_symfs), OPT_STRING('C', "cpu", &report.cpu_list, "cpu", "list of cpus to profile"), + OPT_STRING(0, "parallelism", &symbol_conf.parallelism_list_str, "parallel= ism", + "only consider these parallelism levels (cpu set format)"), OPT_BOOLEAN('I', "show-info", &report.show_full_info, "Display extended information about perf.data file"), OPT_BOOLEAN(0, "source", &annotate_opts.annotate_src, @@ -1721,7 +1723,8 @@ int cmd_report(int argc, const char **argv) } =20 if (report.disable_order || !perf_session__has_switch_events(session)) { - if ((sort_order && strstr(sort_order, "parallelism")) || + if (symbol_conf.parallelism_list_str || + (sort_order && strstr(sort_order, "parallelism")) || (field_order && strstr(field_order, "parallelism"))) { if (report.disable_order) ui__error("Use of parallelism is incompatible with --disable-order.\n"= ); diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c index 3d3ac58e1c660..bea9698e0c6bf 100644 --- a/tools/perf/util/event.c +++ b/tools/perf/util/event.c @@ -769,6 +769,8 @@ int machine__resolve(struct machine *machine, struct ad= dr_location *al, =20 /* Account for possible out-of-order switch events. */ al->parallelism =3D min(max(machine->parallelism, 1), machine__nr_cpus_av= ail(machine)); + if (test_bit(al->parallelism, symbol_conf.parallelism_filter)) + al->filtered |=3D (1 << HIST_FILTER__PARALLELISM); =20 if (al->map) { if (symbol_conf.dso_list && diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c index 6b8f8da8d3b66..446342246f5ee 100644 --- a/tools/perf/util/hist.c +++ b/tools/perf/util/hist.c @@ -43,6 +43,8 @@ static bool hists__filter_entry_by_symbol(struct hists *h= ists, struct hist_entry *he); static bool hists__filter_entry_by_socket(struct hists *hists, struct hist_entry *he); +static bool hists__filter_entry_by_parallelism(struct hists *hists, + struct hist_entry *he); =20 u16 hists__col_len(struct hists *hists, enum hist_column col) { @@ -1457,6 +1459,10 @@ static void hist_entry__check_and_remove_filter(stru= ct hist_entry *he, if (symbol_conf.sym_list =3D=3D NULL) return; break; + case HIST_FILTER__PARALLELISM: + if (__bitmap_weight(symbol_conf.parallelism_filter, MAX_NR_CPUS + 1) =3D= =3D 0) + return; + break; case HIST_FILTER__PARENT: case HIST_FILTER__GUEST: case HIST_FILTER__HOST: @@ -1515,6 +1521,9 @@ static void hist_entry__apply_hierarchy_filters(struc= t hist_entry *he) hist_entry__check_and_remove_filter(he, HIST_FILTER__SYMBOL, perf_hpp__is_sym_entry); =20 + hist_entry__check_and_remove_filter(he, HIST_FILTER__PARALLELISM, + perf_hpp__is_parallelism_entry); + hists__apply_filters(he->hists, he); } =20 @@ -1711,6 +1720,7 @@ static void hists__apply_filters(struct hists *hists,= struct hist_entry *he) hists__filter_entry_by_thread(hists, he); hists__filter_entry_by_symbol(hists, he); hists__filter_entry_by_socket(hists, he); + hists__filter_entry_by_parallelism(hists, he); } =20 int hists__collapse_resort(struct hists *hists, struct ui_progress *prog) @@ -2197,6 +2207,16 @@ static bool hists__filter_entry_by_socket(struct his= ts *hists, return false; } =20 +static bool hists__filter_entry_by_parallelism(struct hists *hists, + struct hist_entry *he) +{ + if (test_bit(he->parallelism, hists->parallelism_filter)) { + he->filtered |=3D (1 << HIST_FILTER__PARALLELISM); + return true; + } + return false; +} + typedef bool (*filter_fn_t)(struct hists *hists, struct hist_entry *he); =20 static void hists__filter_by_type(struct hists *hists, int type, filter_fn= _t filter) @@ -2366,6 +2386,16 @@ void hists__filter_by_socket(struct hists *hists) hists__filter_entry_by_socket); } =20 +void hists__filter_by_parallelism(struct hists *hists) +{ + if (symbol_conf.report_hierarchy) + hists__filter_hierarchy(hists, HIST_FILTER__PARALLELISM, + hists->parallelism_filter); + else + hists__filter_by_type(hists, HIST_FILTER__PARALLELISM, + hists__filter_entry_by_parallelism); +} + void events_stats__inc(struct events_stats *stats, u32 type) { ++stats->nr_events[0]; @@ -2872,6 +2902,7 @@ int __hists__init(struct hists *hists, struct perf_hp= p_list *hpp_list) hists->entries =3D RB_ROOT_CACHED; mutex_init(&hists->lock); hists->socket_filter =3D -1; + hists->parallelism_filter =3D symbol_conf.parallelism_filter; hists->hpp_list =3D hpp_list; INIT_LIST_HEAD(&hists->hpp_formats); return 0; diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h index 4035106a74087..c2236e0d89f2a 100644 --- a/tools/perf/util/hist.h +++ b/tools/perf/util/hist.h @@ -31,6 +31,7 @@ enum hist_filter { HIST_FILTER__HOST, HIST_FILTER__SOCKET, HIST_FILTER__C2C, + HIST_FILTER__PARALLELISM, }; =20 typedef u16 filter_mask_t; @@ -112,6 +113,7 @@ struct hists { const struct dso *dso_filter; const char *uid_filter_str; const char *symbol_filter_str; + unsigned long *parallelism_filter; struct mutex lock; struct hists_stats stats; u64 event_stream; @@ -388,11 +390,13 @@ void hists__filter_by_dso(struct hists *hists); void hists__filter_by_thread(struct hists *hists); void hists__filter_by_symbol(struct hists *hists); void hists__filter_by_socket(struct hists *hists); +void hists__filter_by_parallelism(struct hists *hists); =20 static inline bool hists__has_filter(struct hists *hists) { return hists->thread_filter || hists->dso_filter || - hists->symbol_filter_str || (hists->socket_filter > -1); + hists->symbol_filter_str || (hists->socket_filter > -1) || + hists->parallelism_filter; } =20 u16 hists__col_len(struct hists *hists, enum hist_column col); diff --git a/tools/perf/util/sort.c b/tools/perf/util/sort.c index 7eef43f5be360..3055496358ebb 100644 --- a/tools/perf/util/sort.c +++ b/tools/perf/util/sort.c @@ -900,6 +900,16 @@ sort__parallelism_cmp(struct hist_entry *left, struct = hist_entry *right) return right->parallelism - left->parallelism; } =20 +static int hist_entry__parallelism_filter(struct hist_entry *he, int type,= const void *arg) +{ + const unsigned long *parallelism_filter =3D arg; + + if (type !=3D HIST_FILTER__PARALLELISM) + return -1; + + return test_bit(he->parallelism, parallelism_filter); +} + static int hist_entry__parallelism_snprintf(struct hist_entry *he, char *b= f, size_t size, unsigned int width) { @@ -909,6 +919,7 @@ static int hist_entry__parallelism_snprintf(struct hist= _entry *he, char *bf, struct sort_entry sort_parallelism =3D { .se_header =3D "Parallelism", .se_cmp =3D sort__parallelism_cmp, + .se_filter =3D hist_entry__parallelism_filter, .se_snprintf =3D hist_entry__parallelism_snprintf, .se_width_idx =3D HISTC_PARALLELISM, }; diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c index 49b08adc6ee34..315f74b5bac06 100644 --- a/tools/perf/util/symbol.c +++ b/tools/perf/util/symbol.c @@ -18,6 +18,7 @@ #include "annotate.h" #include "build-id.h" #include "cap.h" +#include "cpumap.h" #include "dso.h" #include "util.h" // lsdir() #include "debug.h" @@ -2471,6 +2472,36 @@ int symbol__annotation_init(void) return 0; } =20 +static int setup_parallelism_bitmap(void) +{ + struct perf_cpu_map *map; + struct perf_cpu cpu; + int i, err =3D -1; + + if (symbol_conf.parallelism_list_str =3D=3D NULL) + return 0; + + map =3D perf_cpu_map__new(symbol_conf.parallelism_list_str); + if (map =3D=3D NULL) { + pr_err("failed to parse parallelism filter list\n"); + return -1; + } + + bitmap_fill(symbol_conf.parallelism_filter, MAX_NR_CPUS + 1); + perf_cpu_map__for_each_cpu(cpu, i, map) { + if (cpu.cpu <=3D 0 || cpu.cpu > MAX_NR_CPUS) { + pr_err("Requested parallelism level %d is invalid.\n", cpu.cpu); + goto out_delete_map; + } + __clear_bit(cpu.cpu, symbol_conf.parallelism_filter); + } + + err =3D 0; +out_delete_map: + perf_cpu_map__put(map); + return err; +} + int symbol__init(struct perf_env *env) { const char *symfs; @@ -2490,6 +2521,9 @@ int symbol__init(struct perf_env *env) return -1; } =20 + if (setup_parallelism_bitmap()) + return -1; + if (setup_list(&symbol_conf.dso_list, symbol_conf.dso_list_str, "dso") < 0) return -1; diff --git a/tools/perf/util/symbol_conf.h b/tools/perf/util/symbol_conf.h index a9c51acc722fe..c5b2e56127e22 100644 --- a/tools/perf/util/symbol_conf.h +++ b/tools/perf/util/symbol_conf.h @@ -3,6 +3,8 @@ #define __PERF_SYMBOL_CONF 1 =20 #include +#include +#include "perf.h" =20 struct strlist; struct intlist; @@ -62,6 +64,7 @@ struct symbol_conf { *pid_list_str, *tid_list_str, *sym_list_str, + *parallelism_list_str, *col_width_list_str, *bt_stop_list_str; const char *addr2line_path; @@ -82,6 +85,7 @@ struct symbol_conf { int pad_output_len_dso; int group_sort_idx; int addr_range; + DECLARE_BITMAP(parallelism_filter, MAX_NR_CPUS + 1); }; =20 extern struct symbol_conf symbol_conf; --=20 2.48.1.262.g85cc9f2d1e-goog