linux-perf-users.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v2 1/3] perf list: Print matching PMU events for --unit
@ 2025-11-20  0:47 Namhyung Kim
  2025-11-20  0:47 ` [PATCH v2 2/3] perf list: Share print state with JSON output Namhyung Kim
                   ` (2 more replies)
  0 siblings, 3 replies; 7+ messages in thread
From: Namhyung Kim @ 2025-11-20  0:47 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo, Ian Rogers, James Clark
  Cc: Jiri Olsa, Adrian Hunter, Peter Zijlstra, Ingo Molnar, LKML,
	linux-perf-users

When --unit option is used, pmu_glob is set to the argument.  It should
match with event PMU and display the matching ones only.  But it also
shows raw events and metrics after that.

  $ perf list --unit tool
  List of pre-defined events (to be used in -e or -M):

  tool:
    core_wide
         [1 if not SMT,if SMT are events being gathered on all SMT threads 1 otherwise 0. Unit: tool]
    duration_time
         [Wall clock interval time in nanoseconds. Unit: tool]
    has_pmem
         [1 if persistent memory installed otherwise 0. Unit: tool]
    num_cores
         [Number of cores. A core consists of 1 or more thread,with each thread being associated with a logical Linux CPU. Unit: tool]
    num_cpus
         [Number of logical Linux CPUs. There may be multiple such CPUs on a core. Unit: tool]
    ...
    rNNN                                               [Raw event descriptor]
    cpu/event=0..255,pc,edge,.../modifier              [Raw event descriptor]
         [(see 'man perf-list' or 'man perf-record' on how to encode it)]
    breakpoint//modifier                               [Raw event descriptor]
    cstate_core/event=0..0xffffffffffffffff/modifier   [Raw event descriptor]
    cstate_pkg/event=0..0xffffffffffffffff/modifier    [Raw event descriptor]
    drm_i915//modifier                                 [Raw event descriptor]
    hwmon_acpitz//modifier                             [Raw event descriptor]
    hwmon_ac//modifier                                 [Raw event descriptor]
    hwmon_bat0//modifier                               [Raw event descriptor]
    hwmon_coretemp//modifier                           [Raw event descriptor]
    ...

  Metric Groups:

  Backend: [Grouping from Top-down Microarchitecture Analysis Metrics spreadsheet]
    tma_core_bound
         [This metric represents fraction of slots where Core non-memory issues were of a bottleneck]
    tma_info_core_ilp
         [Instruction-Level-Parallelism (average number of uops executed when there is execution) per thread (logical-processor)]
    tma_info_memory_l2mpki
         [L2 cache true misses per kilo instruction for retired demand loads]
    ...

This change makes it print the tool PMU events only.

Reviewed-by: Ian Rogers <irogers@google.com>
Signed-off-by: Namhyung Kim <namhyung@kernel.org>
---
 tools/perf/builtin-list.c | 8 +++++---
 1 file changed, 5 insertions(+), 3 deletions(-)

diff --git a/tools/perf/builtin-list.c b/tools/perf/builtin-list.c
index 16400366f8276a7a..28bf1fc7f5eeff8f 100644
--- a/tools/perf/builtin-list.c
+++ b/tools/perf/builtin-list.c
@@ -130,7 +130,7 @@ static void default_print_event(void *ps, const char *topic,
 	if (deprecated && !print_state->deprecated)
 		return;
 
-	if (print_state->pmu_glob && pmu_name && !strglobmatch(pmu_name, print_state->pmu_glob))
+	if (print_state->pmu_glob && (!pmu_name || !strglobmatch(pmu_name, print_state->pmu_glob)))
 		return;
 
 	if (print_state->exclude_abi && pmu_type < PERF_TYPE_MAX && pmu_type != PERF_TYPE_RAW)
@@ -612,8 +612,10 @@ int cmd_list(int argc, const char **argv)
 	print_cb.print_start(ps);
 
 	if (argc == 0) {
-		default_ps.metrics = true;
-		default_ps.metricgroups = true;
+		if (!unit_name) {
+			default_ps.metrics = true;
+			default_ps.metricgroups = true;
+		}
 		print_events(&print_cb, ps);
 		goto out;
 	}
-- 
2.52.0.rc1.455.g30608eb744-goog


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH v2 2/3] perf list: Share print state with JSON output
  2025-11-20  0:47 [PATCH v2 1/3] perf list: Print matching PMU events for --unit Namhyung Kim
@ 2025-11-20  0:47 ` Namhyung Kim
  2025-11-20  5:30   ` Ian Rogers
  2025-11-20  0:47 ` [PATCH v2 3/3] perf list: Support filtering in " Namhyung Kim
  2025-11-21 20:02 ` [PATCH v2 1/3] perf list: Print matching PMU events for --unit Namhyung Kim
  2 siblings, 1 reply; 7+ messages in thread
From: Namhyung Kim @ 2025-11-20  0:47 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo, Ian Rogers, James Clark
  Cc: Jiri Olsa, Adrian Hunter, Peter Zijlstra, Ingo Molnar, LKML,
	linux-perf-users

The JSON print state has only one different field (need_sep).  Let's
add the default print state to the json state and use it.  Then we can
use the 'ps' variable to update the state properly.

This is a preparation for the next commit.

Signed-off-by: Namhyung Kim <namhyung@kernel.org>
---
 tools/perf/builtin-list.c | 127 +++++++++++++++++++-------------------
 1 file changed, 65 insertions(+), 62 deletions(-)

diff --git a/tools/perf/builtin-list.c b/tools/perf/builtin-list.c
index 28bf1fc7f5eeff8f..6c5913f129f39c94 100644
--- a/tools/perf/builtin-list.c
+++ b/tools/perf/builtin-list.c
@@ -283,8 +283,8 @@ static void default_print_metric(void *ps,
 }
 
 struct json_print_state {
-	/** @fp: File to write output to. */
-	FILE *fp;
+	/** The shared print_state */
+	struct print_state common;
 	/** Should a separator be printed prior to the next item? */
 	bool need_sep;
 };
@@ -292,7 +292,7 @@ struct json_print_state {
 static void json_print_start(void *ps)
 {
 	struct json_print_state *print_state = ps;
-	FILE *fp = print_state->fp;
+	FILE *fp = print_state->common.fp;
 
 	fprintf(fp, "[\n");
 }
@@ -300,7 +300,7 @@ static void json_print_start(void *ps)
 static void json_print_end(void *ps)
 {
 	struct json_print_state *print_state = ps;
-	FILE *fp = print_state->fp;
+	FILE *fp = print_state->common.fp;
 
 	fprintf(fp, "%s]\n", print_state->need_sep ? "\n" : "");
 }
@@ -370,7 +370,7 @@ static void json_print_event(void *ps, const char *topic,
 {
 	struct json_print_state *print_state = ps;
 	bool need_sep = false;
-	FILE *fp = print_state->fp;
+	FILE *fp = print_state->common.fp;
 	struct strbuf buf;
 
 	strbuf_init(&buf, 0);
@@ -446,7 +446,7 @@ static void json_print_metric(void *ps __maybe_unused, const char *group,
 {
 	struct json_print_state *print_state = ps;
 	bool need_sep = false;
-	FILE *fp = print_state->fp;
+	FILE *fp = print_state->common.fp;
 	struct strbuf buf;
 
 	strbuf_init(&buf, 0);
@@ -521,10 +521,12 @@ int cmd_list(int argc, const char **argv)
 		.fp = stdout,
 		.desc = true,
 	};
-	struct print_state json_ps = {
-		.fp = stdout,
+	struct json_print_state json_ps = {
+		.common = {
+			.fp = stdout,
+		},
 	};
-	void *ps = &default_ps;
+	struct print_state *ps = &default_ps;
 	struct print_callbacks print_cb = {
 		.print_start = default_print_start,
 		.print_end = default_print_end,
@@ -572,9 +574,11 @@ int cmd_list(int argc, const char **argv)
 	argc = parse_options(argc, argv, list_options, list_usage,
 			     PARSE_OPT_STOP_AT_NON_OPTION);
 
+	if (json)
+		ps = &json_ps.common;
+
 	if (output_path) {
-		default_ps.fp = fopen(output_path, "w");
-		json_ps.fp = default_ps.fp;
+		ps->fp = fopen(output_path, "w");
 	}
 
 	setup_pager();
@@ -590,14 +594,13 @@ int cmd_list(int argc, const char **argv)
 			.print_metric = json_print_metric,
 			.skip_duplicate_pmus = json_skip_duplicate_pmus,
 		};
-		ps = &json_ps;
 	} else {
-		default_ps.last_topic = strdup("");
-		assert(default_ps.last_topic);
-		default_ps.visited_metrics = strlist__new(NULL, NULL);
-		assert(default_ps.visited_metrics);
+		ps->last_topic = strdup("");
+		assert(ps->last_topic);
+		ps->visited_metrics = strlist__new(NULL, NULL);
+		assert(ps->visited_metrics);
 		if (unit_name)
-			default_ps.pmu_glob = strdup(unit_name);
+			ps->pmu_glob = strdup(unit_name);
 		else if (cputype) {
 			const struct perf_pmu *pmu = perf_pmus__pmu_for_pmu_filter(cputype);
 
@@ -606,15 +609,15 @@ int cmd_list(int argc, const char **argv)
 				ret = -1;
 				goto out;
 			}
-			default_ps.pmu_glob = strdup(pmu->name);
+			ps->pmu_glob = strdup(pmu->name);
 		}
 	}
 	print_cb.print_start(ps);
 
 	if (argc == 0) {
 		if (!unit_name) {
-			default_ps.metrics = true;
-			default_ps.metricgroups = true;
+			ps->metrics = true;
+			ps->metricgroups = true;
 		}
 		print_events(&print_cb, ps);
 		goto out;
@@ -636,57 +639,57 @@ int cmd_list(int argc, const char **argv)
 			default_ps.pmu_glob = old_pmu_glob;
 		} else if (strcmp(argv[i], "hw") == 0 ||
 			   strcmp(argv[i], "hardware") == 0) {
-			char *old_event_glob = default_ps.event_glob;
+			char *old_event_glob = ps->event_glob;
 
-			default_ps.event_glob = strdup("legacy hardware");
-			if (!default_ps.event_glob) {
+			ps->event_glob = strdup("legacy hardware");
+			if (!ps->event_glob) {
 				ret = -1;
 				goto out;
 			}
 			perf_pmus__print_pmu_events(&print_cb, ps);
-			zfree(&default_ps.event_glob);
-			default_ps.event_glob = old_event_glob;
+			zfree(&ps->event_glob);
+			ps->event_glob = old_event_glob;
 		} else if (strcmp(argv[i], "sw") == 0 ||
 			 strcmp(argv[i], "software") == 0) {
-			char *old_pmu_glob = default_ps.pmu_glob;
+			char *old_pmu_glob = ps->pmu_glob;
 			static const char * const sw_globs[] = { "software", "tool" };
 
 			for (size_t j = 0; j < ARRAY_SIZE(sw_globs); j++) {
-				default_ps.pmu_glob = strdup(sw_globs[j]);
-				if (!default_ps.pmu_glob) {
+				ps->pmu_glob = strdup(sw_globs[j]);
+				if (!ps->pmu_glob) {
 					ret = -1;
 					goto out;
 				}
 				perf_pmus__print_pmu_events(&print_cb, ps);
-				zfree(&default_ps.pmu_glob);
+				zfree(&ps->pmu_glob);
 			}
-			default_ps.pmu_glob = old_pmu_glob;
+			ps->pmu_glob = old_pmu_glob;
 		} else if (strcmp(argv[i], "cache") == 0 ||
 			   strcmp(argv[i], "hwcache") == 0) {
-			char *old_event_glob = default_ps.event_glob;
+			char *old_event_glob = ps->event_glob;
 
-			default_ps.event_glob = strdup("legacy cache");
-			if (!default_ps.event_glob) {
+			ps->event_glob = strdup("legacy cache");
+			if (!ps->event_glob) {
 				ret = -1;
 				goto out;
 			}
 			perf_pmus__print_pmu_events(&print_cb, ps);
-			zfree(&default_ps.event_glob);
-			default_ps.event_glob = old_event_glob;
+			zfree(&ps->event_glob);
+			ps->event_glob = old_event_glob;
 		} else if (strcmp(argv[i], "pmu") == 0) {
-			default_ps.exclude_abi = true;
+			ps->exclude_abi = true;
 			perf_pmus__print_pmu_events(&print_cb, ps);
-			default_ps.exclude_abi = false;
+			ps->exclude_abi = false;
 		} else if (strcmp(argv[i], "sdt") == 0)
 			print_sdt_events(&print_cb, ps);
 		else if (strcmp(argv[i], "metric") == 0 || strcmp(argv[i], "metrics") == 0) {
-			default_ps.metricgroups = false;
-			default_ps.metrics = true;
+			ps->metricgroups = false;
+			ps->metrics = true;
 			metricgroup__print(&print_cb, ps);
 		} else if (strcmp(argv[i], "metricgroup") == 0 ||
 			   strcmp(argv[i], "metricgroups") == 0) {
-			default_ps.metricgroups = true;
-			default_ps.metrics = false;
+			ps->metricgroups = true;
+			ps->metrics = false;
 			metricgroup__print(&print_cb, ps);
 		}
 #ifdef HAVE_LIBPFM
@@ -694,40 +697,40 @@ int cmd_list(int argc, const char **argv)
 			print_libpfm_events(&print_cb, ps);
 #endif
 		else if ((sep = strchr(argv[i], ':')) != NULL) {
-			char *old_pmu_glob = default_ps.pmu_glob;
-			char *old_event_glob = default_ps.event_glob;
+			char *old_pmu_glob = ps->pmu_glob;
+			char *old_event_glob = ps->event_glob;
 
-			default_ps.event_glob = strdup(argv[i]);
-			if (!default_ps.event_glob) {
+			ps->event_glob = strdup(argv[i]);
+			if (!ps->event_glob) {
 				ret = -1;
 				goto out;
 			}
 
-			default_ps.pmu_glob = strdup("tracepoint");
-			if (!default_ps.pmu_glob) {
-				zfree(&default_ps.event_glob);
+			ps->pmu_glob = strdup("tracepoint");
+			if (!ps->pmu_glob) {
+				zfree(&ps->event_glob);
 				ret = -1;
 				goto out;
 			}
 			perf_pmus__print_pmu_events(&print_cb, ps);
-			zfree(&default_ps.pmu_glob);
-			default_ps.pmu_glob = old_pmu_glob;
+			zfree(&ps->pmu_glob);
+			ps->pmu_glob = old_pmu_glob;
 			print_sdt_events(&print_cb, ps);
-			default_ps.metrics = true;
-			default_ps.metricgroups = true;
+			ps->metrics = true;
+			ps->metricgroups = true;
 			metricgroup__print(&print_cb, ps);
-			zfree(&default_ps.event_glob);
-			default_ps.event_glob = old_event_glob;
+			zfree(&ps->event_glob);
+			ps->event_glob = old_event_glob;
 		} else {
 			if (asprintf(&s, "*%s*", argv[i]) < 0) {
 				printf("Critical: Not enough memory! Trying to continue...\n");
 				continue;
 			}
-			default_ps.event_glob = s;
+			ps->event_glob = s;
 			perf_pmus__print_pmu_events(&print_cb, ps);
 			print_sdt_events(&print_cb, ps);
-			default_ps.metrics = true;
-			default_ps.metricgroups = true;
+			ps->metrics = true;
+			ps->metricgroups = true;
 			metricgroup__print(&print_cb, ps);
 			free(s);
 		}
@@ -735,12 +738,12 @@ int cmd_list(int argc, const char **argv)
 
 out:
 	print_cb.print_end(ps);
-	free(default_ps.pmu_glob);
-	free(default_ps.last_topic);
-	free(default_ps.last_metricgroups);
-	strlist__delete(default_ps.visited_metrics);
+	free(ps->pmu_glob);
+	free(ps->last_topic);
+	free(ps->last_metricgroups);
+	strlist__delete(ps->visited_metrics);
 	if (output_path)
-		fclose(default_ps.fp);
+		fclose(ps->fp);
 
 	return ret;
 }
-- 
2.52.0.rc1.455.g30608eb744-goog


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH v2 3/3] perf list: Support filtering in JSON output
  2025-11-20  0:47 [PATCH v2 1/3] perf list: Print matching PMU events for --unit Namhyung Kim
  2025-11-20  0:47 ` [PATCH v2 2/3] perf list: Share print state with JSON output Namhyung Kim
@ 2025-11-20  0:47 ` Namhyung Kim
  2025-11-20  5:42   ` Ian Rogers
  2025-11-21 20:02 ` [PATCH v2 1/3] perf list: Print matching PMU events for --unit Namhyung Kim
  2 siblings, 1 reply; 7+ messages in thread
From: Namhyung Kim @ 2025-11-20  0:47 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo, Ian Rogers, James Clark
  Cc: Jiri Olsa, Adrian Hunter, Peter Zijlstra, Ingo Molnar, LKML,
	linux-perf-users

Like regular output mode, it should honor command line arguments to
limit to a certain type of PMUs or events.

  $ perf list -j hw
  [
  {
          "Unit": "cpu",
          "Topic": "legacy hardware",
          "EventName": "branch-instructions",
          "EventType": "Kernel PMU event",
          "BriefDescription": "Retired branch instructions [This event is an alias of branches]",
          "Encoding": "cpu/event=0xc4\n/"
  },
  {
          "Unit": "cpu",
          "Topic": "legacy hardware",
          "EventName": "branch-misses",
          "EventType": "Kernel PMU event",
          "BriefDescription": "Mispredicted branch instructions",
          "Encoding": "cpu/event=0xc5\n/"
  },
  ...

Signed-off-by: Namhyung Kim <namhyung@kernel.org>
---
 tools/perf/builtin-list.c | 24 ++++++++++++++++++++++++
 1 file changed, 24 insertions(+)

diff --git a/tools/perf/builtin-list.c b/tools/perf/builtin-list.c
index 6c5913f129f39c94..5cbca0bacd35237e 100644
--- a/tools/perf/builtin-list.c
+++ b/tools/perf/builtin-list.c
@@ -373,6 +373,23 @@ static void json_print_event(void *ps, const char *topic,
 	FILE *fp = print_state->common.fp;
 	struct strbuf buf;
 
+	if (deprecated && !print_state->common.deprecated)
+		return;
+
+	if (print_state->common.pmu_glob &&
+	    (!pmu_name || !strglobmatch(pmu_name, print_state->common.pmu_glob)))
+		return;
+
+	if (print_state->common.exclude_abi && pmu_type < PERF_TYPE_MAX &&
+	    pmu_type != PERF_TYPE_RAW)
+		return;
+
+	if (print_state->common.event_glob &&
+	    (!event_name || !strglobmatch(event_name, print_state->common.event_glob)) &&
+	    (!event_alias || !strglobmatch(event_alias, print_state->common.event_glob)) &&
+	    (!topic || !strglobmatch_nocase(topic, print_state->common.event_glob)))
+		return;
+
 	strbuf_init(&buf, 0);
 	fprintf(fp, "%s{\n", print_state->need_sep ? ",\n" : "");
 	print_state->need_sep = true;
@@ -449,6 +466,13 @@ static void json_print_metric(void *ps __maybe_unused, const char *group,
 	FILE *fp = print_state->common.fp;
 	struct strbuf buf;
 
+	if (print_state->common.event_glob &&
+	    (!print_state->common.metrics || !name ||
+	     !strglobmatch(name, print_state->common.event_glob)) &&
+	    (!print_state->common.metricgroups || !group ||
+	     !strglobmatch(group, print_state->common.event_glob)))
+		return;
+
 	strbuf_init(&buf, 0);
 	fprintf(fp, "%s{\n", print_state->need_sep ? ",\n" : "");
 	print_state->need_sep = true;
-- 
2.52.0.rc1.455.g30608eb744-goog


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* Re: [PATCH v2 2/3] perf list: Share print state with JSON output
  2025-11-20  0:47 ` [PATCH v2 2/3] perf list: Share print state with JSON output Namhyung Kim
@ 2025-11-20  5:30   ` Ian Rogers
  0 siblings, 0 replies; 7+ messages in thread
From: Ian Rogers @ 2025-11-20  5:30 UTC (permalink / raw)
  To: Namhyung Kim
  Cc: Arnaldo Carvalho de Melo, James Clark, Jiri Olsa, Adrian Hunter,
	Peter Zijlstra, Ingo Molnar, LKML, linux-perf-users

On Wed, Nov 19, 2025 at 4:47 PM Namhyung Kim <namhyung@kernel.org> wrote:
>
> The JSON print state has only one different field (need_sep).  Let's
> add the default print state to the json state and use it.  Then we can
> use the 'ps' variable to update the state properly.
>
> This is a preparation for the next commit.
>
> Signed-off-by: Namhyung Kim <namhyung@kernel.org>

Reviewed-by: Ian Rogers <irogers@google.com>

Thanks,
Ian

> ---
>  tools/perf/builtin-list.c | 127 +++++++++++++++++++-------------------
>  1 file changed, 65 insertions(+), 62 deletions(-)
>
> diff --git a/tools/perf/builtin-list.c b/tools/perf/builtin-list.c
> index 28bf1fc7f5eeff8f..6c5913f129f39c94 100644
> --- a/tools/perf/builtin-list.c
> +++ b/tools/perf/builtin-list.c
> @@ -283,8 +283,8 @@ static void default_print_metric(void *ps,
>  }
>
>  struct json_print_state {
> -       /** @fp: File to write output to. */
> -       FILE *fp;
> +       /** The shared print_state */
> +       struct print_state common;
>         /** Should a separator be printed prior to the next item? */
>         bool need_sep;
>  };
> @@ -292,7 +292,7 @@ struct json_print_state {
>  static void json_print_start(void *ps)
>  {
>         struct json_print_state *print_state = ps;
> -       FILE *fp = print_state->fp;
> +       FILE *fp = print_state->common.fp;
>
>         fprintf(fp, "[\n");
>  }
> @@ -300,7 +300,7 @@ static void json_print_start(void *ps)
>  static void json_print_end(void *ps)
>  {
>         struct json_print_state *print_state = ps;
> -       FILE *fp = print_state->fp;
> +       FILE *fp = print_state->common.fp;
>
>         fprintf(fp, "%s]\n", print_state->need_sep ? "\n" : "");
>  }
> @@ -370,7 +370,7 @@ static void json_print_event(void *ps, const char *topic,
>  {
>         struct json_print_state *print_state = ps;
>         bool need_sep = false;
> -       FILE *fp = print_state->fp;
> +       FILE *fp = print_state->common.fp;
>         struct strbuf buf;
>
>         strbuf_init(&buf, 0);
> @@ -446,7 +446,7 @@ static void json_print_metric(void *ps __maybe_unused, const char *group,
>  {
>         struct json_print_state *print_state = ps;
>         bool need_sep = false;
> -       FILE *fp = print_state->fp;
> +       FILE *fp = print_state->common.fp;
>         struct strbuf buf;
>
>         strbuf_init(&buf, 0);
> @@ -521,10 +521,12 @@ int cmd_list(int argc, const char **argv)
>                 .fp = stdout,
>                 .desc = true,
>         };
> -       struct print_state json_ps = {
> -               .fp = stdout,
> +       struct json_print_state json_ps = {
> +               .common = {
> +                       .fp = stdout,
> +               },
>         };
> -       void *ps = &default_ps;
> +       struct print_state *ps = &default_ps;
>         struct print_callbacks print_cb = {
>                 .print_start = default_print_start,
>                 .print_end = default_print_end,
> @@ -572,9 +574,11 @@ int cmd_list(int argc, const char **argv)
>         argc = parse_options(argc, argv, list_options, list_usage,
>                              PARSE_OPT_STOP_AT_NON_OPTION);
>
> +       if (json)
> +               ps = &json_ps.common;
> +
>         if (output_path) {
> -               default_ps.fp = fopen(output_path, "w");
> -               json_ps.fp = default_ps.fp;
> +               ps->fp = fopen(output_path, "w");
>         }
>
>         setup_pager();
> @@ -590,14 +594,13 @@ int cmd_list(int argc, const char **argv)
>                         .print_metric = json_print_metric,
>                         .skip_duplicate_pmus = json_skip_duplicate_pmus,
>                 };
> -               ps = &json_ps;
>         } else {
> -               default_ps.last_topic = strdup("");
> -               assert(default_ps.last_topic);
> -               default_ps.visited_metrics = strlist__new(NULL, NULL);
> -               assert(default_ps.visited_metrics);
> +               ps->last_topic = strdup("");
> +               assert(ps->last_topic);
> +               ps->visited_metrics = strlist__new(NULL, NULL);
> +               assert(ps->visited_metrics);
>                 if (unit_name)
> -                       default_ps.pmu_glob = strdup(unit_name);
> +                       ps->pmu_glob = strdup(unit_name);
>                 else if (cputype) {
>                         const struct perf_pmu *pmu = perf_pmus__pmu_for_pmu_filter(cputype);
>
> @@ -606,15 +609,15 @@ int cmd_list(int argc, const char **argv)
>                                 ret = -1;
>                                 goto out;
>                         }
> -                       default_ps.pmu_glob = strdup(pmu->name);
> +                       ps->pmu_glob = strdup(pmu->name);
>                 }
>         }
>         print_cb.print_start(ps);
>
>         if (argc == 0) {
>                 if (!unit_name) {
> -                       default_ps.metrics = true;
> -                       default_ps.metricgroups = true;
> +                       ps->metrics = true;
> +                       ps->metricgroups = true;
>                 }
>                 print_events(&print_cb, ps);
>                 goto out;
> @@ -636,57 +639,57 @@ int cmd_list(int argc, const char **argv)
>                         default_ps.pmu_glob = old_pmu_glob;
>                 } else if (strcmp(argv[i], "hw") == 0 ||
>                            strcmp(argv[i], "hardware") == 0) {
> -                       char *old_event_glob = default_ps.event_glob;
> +                       char *old_event_glob = ps->event_glob;
>
> -                       default_ps.event_glob = strdup("legacy hardware");
> -                       if (!default_ps.event_glob) {
> +                       ps->event_glob = strdup("legacy hardware");
> +                       if (!ps->event_glob) {
>                                 ret = -1;
>                                 goto out;
>                         }
>                         perf_pmus__print_pmu_events(&print_cb, ps);
> -                       zfree(&default_ps.event_glob);
> -                       default_ps.event_glob = old_event_glob;
> +                       zfree(&ps->event_glob);
> +                       ps->event_glob = old_event_glob;
>                 } else if (strcmp(argv[i], "sw") == 0 ||
>                          strcmp(argv[i], "software") == 0) {
> -                       char *old_pmu_glob = default_ps.pmu_glob;
> +                       char *old_pmu_glob = ps->pmu_glob;
>                         static const char * const sw_globs[] = { "software", "tool" };
>
>                         for (size_t j = 0; j < ARRAY_SIZE(sw_globs); j++) {
> -                               default_ps.pmu_glob = strdup(sw_globs[j]);
> -                               if (!default_ps.pmu_glob) {
> +                               ps->pmu_glob = strdup(sw_globs[j]);
> +                               if (!ps->pmu_glob) {
>                                         ret = -1;
>                                         goto out;
>                                 }
>                                 perf_pmus__print_pmu_events(&print_cb, ps);
> -                               zfree(&default_ps.pmu_glob);
> +                               zfree(&ps->pmu_glob);
>                         }
> -                       default_ps.pmu_glob = old_pmu_glob;
> +                       ps->pmu_glob = old_pmu_glob;
>                 } else if (strcmp(argv[i], "cache") == 0 ||
>                            strcmp(argv[i], "hwcache") == 0) {
> -                       char *old_event_glob = default_ps.event_glob;
> +                       char *old_event_glob = ps->event_glob;
>
> -                       default_ps.event_glob = strdup("legacy cache");
> -                       if (!default_ps.event_glob) {
> +                       ps->event_glob = strdup("legacy cache");
> +                       if (!ps->event_glob) {
>                                 ret = -1;
>                                 goto out;
>                         }
>                         perf_pmus__print_pmu_events(&print_cb, ps);
> -                       zfree(&default_ps.event_glob);
> -                       default_ps.event_glob = old_event_glob;
> +                       zfree(&ps->event_glob);
> +                       ps->event_glob = old_event_glob;
>                 } else if (strcmp(argv[i], "pmu") == 0) {
> -                       default_ps.exclude_abi = true;
> +                       ps->exclude_abi = true;
>                         perf_pmus__print_pmu_events(&print_cb, ps);
> -                       default_ps.exclude_abi = false;
> +                       ps->exclude_abi = false;
>                 } else if (strcmp(argv[i], "sdt") == 0)
>                         print_sdt_events(&print_cb, ps);
>                 else if (strcmp(argv[i], "metric") == 0 || strcmp(argv[i], "metrics") == 0) {
> -                       default_ps.metricgroups = false;
> -                       default_ps.metrics = true;
> +                       ps->metricgroups = false;
> +                       ps->metrics = true;
>                         metricgroup__print(&print_cb, ps);
>                 } else if (strcmp(argv[i], "metricgroup") == 0 ||
>                            strcmp(argv[i], "metricgroups") == 0) {
> -                       default_ps.metricgroups = true;
> -                       default_ps.metrics = false;
> +                       ps->metricgroups = true;
> +                       ps->metrics = false;
>                         metricgroup__print(&print_cb, ps);
>                 }
>  #ifdef HAVE_LIBPFM
> @@ -694,40 +697,40 @@ int cmd_list(int argc, const char **argv)
>                         print_libpfm_events(&print_cb, ps);
>  #endif
>                 else if ((sep = strchr(argv[i], ':')) != NULL) {
> -                       char *old_pmu_glob = default_ps.pmu_glob;
> -                       char *old_event_glob = default_ps.event_glob;
> +                       char *old_pmu_glob = ps->pmu_glob;
> +                       char *old_event_glob = ps->event_glob;
>
> -                       default_ps.event_glob = strdup(argv[i]);
> -                       if (!default_ps.event_glob) {
> +                       ps->event_glob = strdup(argv[i]);
> +                       if (!ps->event_glob) {
>                                 ret = -1;
>                                 goto out;
>                         }
>
> -                       default_ps.pmu_glob = strdup("tracepoint");
> -                       if (!default_ps.pmu_glob) {
> -                               zfree(&default_ps.event_glob);
> +                       ps->pmu_glob = strdup("tracepoint");
> +                       if (!ps->pmu_glob) {
> +                               zfree(&ps->event_glob);
>                                 ret = -1;
>                                 goto out;
>                         }
>                         perf_pmus__print_pmu_events(&print_cb, ps);
> -                       zfree(&default_ps.pmu_glob);
> -                       default_ps.pmu_glob = old_pmu_glob;
> +                       zfree(&ps->pmu_glob);
> +                       ps->pmu_glob = old_pmu_glob;
>                         print_sdt_events(&print_cb, ps);
> -                       default_ps.metrics = true;
> -                       default_ps.metricgroups = true;
> +                       ps->metrics = true;
> +                       ps->metricgroups = true;
>                         metricgroup__print(&print_cb, ps);
> -                       zfree(&default_ps.event_glob);
> -                       default_ps.event_glob = old_event_glob;
> +                       zfree(&ps->event_glob);
> +                       ps->event_glob = old_event_glob;
>                 } else {
>                         if (asprintf(&s, "*%s*", argv[i]) < 0) {
>                                 printf("Critical: Not enough memory! Trying to continue...\n");
>                                 continue;
>                         }
> -                       default_ps.event_glob = s;
> +                       ps->event_glob = s;
>                         perf_pmus__print_pmu_events(&print_cb, ps);
>                         print_sdt_events(&print_cb, ps);
> -                       default_ps.metrics = true;
> -                       default_ps.metricgroups = true;
> +                       ps->metrics = true;
> +                       ps->metricgroups = true;
>                         metricgroup__print(&print_cb, ps);
>                         free(s);
>                 }
> @@ -735,12 +738,12 @@ int cmd_list(int argc, const char **argv)
>
>  out:
>         print_cb.print_end(ps);
> -       free(default_ps.pmu_glob);
> -       free(default_ps.last_topic);
> -       free(default_ps.last_metricgroups);
> -       strlist__delete(default_ps.visited_metrics);
> +       free(ps->pmu_glob);
> +       free(ps->last_topic);
> +       free(ps->last_metricgroups);
> +       strlist__delete(ps->visited_metrics);
>         if (output_path)
> -               fclose(default_ps.fp);
> +               fclose(ps->fp);
>
>         return ret;
>  }
> --
> 2.52.0.rc1.455.g30608eb744-goog
>

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH v2 3/3] perf list: Support filtering in JSON output
  2025-11-20  0:47 ` [PATCH v2 3/3] perf list: Support filtering in " Namhyung Kim
@ 2025-11-20  5:42   ` Ian Rogers
  2025-11-20 19:11     ` Namhyung Kim
  0 siblings, 1 reply; 7+ messages in thread
From: Ian Rogers @ 2025-11-20  5:42 UTC (permalink / raw)
  To: Namhyung Kim
  Cc: Arnaldo Carvalho de Melo, James Clark, Jiri Olsa, Adrian Hunter,
	Peter Zijlstra, Ingo Molnar, LKML, linux-perf-users

On Wed, Nov 19, 2025 at 4:47 PM Namhyung Kim <namhyung@kernel.org> wrote:
>
> Like regular output mode, it should honor command line arguments to
> limit to a certain type of PMUs or events.
>
>   $ perf list -j hw
>   [
>   {
>           "Unit": "cpu",
>           "Topic": "legacy hardware",
>           "EventName": "branch-instructions",
>           "EventType": "Kernel PMU event",
>           "BriefDescription": "Retired branch instructions [This event is an alias of branches]",
>           "Encoding": "cpu/event=0xc4\n/"
>   },
>   {
>           "Unit": "cpu",
>           "Topic": "legacy hardware",
>           "EventName": "branch-misses",
>           "EventType": "Kernel PMU event",
>           "BriefDescription": "Mispredicted branch instructions",
>           "Encoding": "cpu/event=0xc5\n/"

I think these newlines can be fixed by changing:
https://web.git.kernel.org/pub/scm/linux/kernel/git/perf/perf-tools-next.git/tree/tools/perf/util/pmu.c?h=perf-tools-next#n643
```
ret = io__getline(&io, &alias->terms, &line_len) < 0 ? -errno : 0;
if (ret) {
   ...
}
```
to something like:
```
ret = io__getline(&io, &alias->terms, &line_len) < 0 ? -errno : 0;
if (ret) {
    ...
}
if (alias->terms[line_len - 1] == '\n')
    alias->terms[line_len - 1] = '\0';
```

>   },
>   ...
>
> Signed-off-by: Namhyung Kim <namhyung@kernel.org>

Reviewed-by: Ian Rogers <irogers@google.com>

Thanks,
Ian

> ---
>  tools/perf/builtin-list.c | 24 ++++++++++++++++++++++++
>  1 file changed, 24 insertions(+)
>
> diff --git a/tools/perf/builtin-list.c b/tools/perf/builtin-list.c
> index 6c5913f129f39c94..5cbca0bacd35237e 100644
> --- a/tools/perf/builtin-list.c
> +++ b/tools/perf/builtin-list.c
> @@ -373,6 +373,23 @@ static void json_print_event(void *ps, const char *topic,
>         FILE *fp = print_state->common.fp;
>         struct strbuf buf;
>
> +       if (deprecated && !print_state->common.deprecated)
> +               return;
> +
> +       if (print_state->common.pmu_glob &&
> +           (!pmu_name || !strglobmatch(pmu_name, print_state->common.pmu_glob)))
> +               return;
> +
> +       if (print_state->common.exclude_abi && pmu_type < PERF_TYPE_MAX &&
> +           pmu_type != PERF_TYPE_RAW)
> +               return;
> +
> +       if (print_state->common.event_glob &&
> +           (!event_name || !strglobmatch(event_name, print_state->common.event_glob)) &&
> +           (!event_alias || !strglobmatch(event_alias, print_state->common.event_glob)) &&
> +           (!topic || !strglobmatch_nocase(topic, print_state->common.event_glob)))
> +               return;
> +
>         strbuf_init(&buf, 0);
>         fprintf(fp, "%s{\n", print_state->need_sep ? ",\n" : "");
>         print_state->need_sep = true;
> @@ -449,6 +466,13 @@ static void json_print_metric(void *ps __maybe_unused, const char *group,
>         FILE *fp = print_state->common.fp;
>         struct strbuf buf;
>
> +       if (print_state->common.event_glob &&
> +           (!print_state->common.metrics || !name ||
> +            !strglobmatch(name, print_state->common.event_glob)) &&
> +           (!print_state->common.metricgroups || !group ||
> +            !strglobmatch(group, print_state->common.event_glob)))
> +               return;
> +
>         strbuf_init(&buf, 0);
>         fprintf(fp, "%s{\n", print_state->need_sep ? ",\n" : "");
>         print_state->need_sep = true;
> --
> 2.52.0.rc1.455.g30608eb744-goog
>

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH v2 3/3] perf list: Support filtering in JSON output
  2025-11-20  5:42   ` Ian Rogers
@ 2025-11-20 19:11     ` Namhyung Kim
  0 siblings, 0 replies; 7+ messages in thread
From: Namhyung Kim @ 2025-11-20 19:11 UTC (permalink / raw)
  To: Ian Rogers
  Cc: Arnaldo Carvalho de Melo, James Clark, Jiri Olsa, Adrian Hunter,
	Peter Zijlstra, Ingo Molnar, LKML, linux-perf-users

On Wed, Nov 19, 2025 at 09:42:51PM -0800, Ian Rogers wrote:
> On Wed, Nov 19, 2025 at 4:47 PM Namhyung Kim <namhyung@kernel.org> wrote:
> >
> > Like regular output mode, it should honor command line arguments to
> > limit to a certain type of PMUs or events.
> >
> >   $ perf list -j hw
> >   [
> >   {
> >           "Unit": "cpu",
> >           "Topic": "legacy hardware",
> >           "EventName": "branch-instructions",
> >           "EventType": "Kernel PMU event",
> >           "BriefDescription": "Retired branch instructions [This event is an alias of branches]",
> >           "Encoding": "cpu/event=0xc4\n/"
> >   },
> >   {
> >           "Unit": "cpu",
> >           "Topic": "legacy hardware",
> >           "EventName": "branch-misses",
> >           "EventType": "Kernel PMU event",
> >           "BriefDescription": "Mispredicted branch instructions",
> >           "Encoding": "cpu/event=0xc5\n/"
> 
> I think these newlines can be fixed by changing:
> https://web.git.kernel.org/pub/scm/linux/kernel/git/perf/perf-tools-next.git/tree/tools/perf/util/pmu.c?h=perf-tools-next#n643
> ```
> ret = io__getline(&io, &alias->terms, &line_len) < 0 ? -errno : 0;
> if (ret) {
>    ...
> }
> ```
> to something like:
> ```
> ret = io__getline(&io, &alias->terms, &line_len) < 0 ? -errno : 0;
> if (ret) {
>     ...
> }
> if (alias->terms[line_len - 1] == '\n')
>     alias->terms[line_len - 1] = '\0';
> ```

Yep, will do in a separate patch.

> 
> >   },
> >   ...
> >
> > Signed-off-by: Namhyung Kim <namhyung@kernel.org>
> 
> Reviewed-by: Ian Rogers <irogers@google.com>

Thanks for your review!
Namhyung
 
> > ---
> >  tools/perf/builtin-list.c | 24 ++++++++++++++++++++++++
> >  1 file changed, 24 insertions(+)
> >
> > diff --git a/tools/perf/builtin-list.c b/tools/perf/builtin-list.c
> > index 6c5913f129f39c94..5cbca0bacd35237e 100644
> > --- a/tools/perf/builtin-list.c
> > +++ b/tools/perf/builtin-list.c
> > @@ -373,6 +373,23 @@ static void json_print_event(void *ps, const char *topic,
> >         FILE *fp = print_state->common.fp;
> >         struct strbuf buf;
> >
> > +       if (deprecated && !print_state->common.deprecated)
> > +               return;
> > +
> > +       if (print_state->common.pmu_glob &&
> > +           (!pmu_name || !strglobmatch(pmu_name, print_state->common.pmu_glob)))
> > +               return;
> > +
> > +       if (print_state->common.exclude_abi && pmu_type < PERF_TYPE_MAX &&
> > +           pmu_type != PERF_TYPE_RAW)
> > +               return;
> > +
> > +       if (print_state->common.event_glob &&
> > +           (!event_name || !strglobmatch(event_name, print_state->common.event_glob)) &&
> > +           (!event_alias || !strglobmatch(event_alias, print_state->common.event_glob)) &&
> > +           (!topic || !strglobmatch_nocase(topic, print_state->common.event_glob)))
> > +               return;
> > +
> >         strbuf_init(&buf, 0);
> >         fprintf(fp, "%s{\n", print_state->need_sep ? ",\n" : "");
> >         print_state->need_sep = true;
> > @@ -449,6 +466,13 @@ static void json_print_metric(void *ps __maybe_unused, const char *group,
> >         FILE *fp = print_state->common.fp;
> >         struct strbuf buf;
> >
> > +       if (print_state->common.event_glob &&
> > +           (!print_state->common.metrics || !name ||
> > +            !strglobmatch(name, print_state->common.event_glob)) &&
> > +           (!print_state->common.metricgroups || !group ||
> > +            !strglobmatch(group, print_state->common.event_glob)))
> > +               return;
> > +
> >         strbuf_init(&buf, 0);
> >         fprintf(fp, "%s{\n", print_state->need_sep ? ",\n" : "");
> >         print_state->need_sep = true;
> > --
> > 2.52.0.rc1.455.g30608eb744-goog
> >

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH v2 1/3] perf list: Print matching PMU events for --unit
  2025-11-20  0:47 [PATCH v2 1/3] perf list: Print matching PMU events for --unit Namhyung Kim
  2025-11-20  0:47 ` [PATCH v2 2/3] perf list: Share print state with JSON output Namhyung Kim
  2025-11-20  0:47 ` [PATCH v2 3/3] perf list: Support filtering in " Namhyung Kim
@ 2025-11-21 20:02 ` Namhyung Kim
  2 siblings, 0 replies; 7+ messages in thread
From: Namhyung Kim @ 2025-11-21 20:02 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo, Ian Rogers, James Clark, Namhyung Kim
  Cc: Jiri Olsa, Adrian Hunter, Peter Zijlstra, Ingo Molnar, LKML,
	linux-perf-users

On Wed, 19 Nov 2025 16:47:24 -0800, Namhyung Kim wrote:
> When --unit option is used, pmu_glob is set to the argument.  It should
> match with event PMU and display the matching ones only.  But it also
> shows raw events and metrics after that.
> 
>   $ perf list --unit tool
>   List of pre-defined events (to be used in -e or -M):
> 
> [...]
Applied to perf-tools-next, thanks!

Best regards,
Namhyung



^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2025-11-21 20:02 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-11-20  0:47 [PATCH v2 1/3] perf list: Print matching PMU events for --unit Namhyung Kim
2025-11-20  0:47 ` [PATCH v2 2/3] perf list: Share print state with JSON output Namhyung Kim
2025-11-20  5:30   ` Ian Rogers
2025-11-20  0:47 ` [PATCH v2 3/3] perf list: Support filtering in " Namhyung Kim
2025-11-20  5:42   ` Ian Rogers
2025-11-20 19:11     ` Namhyung Kim
2025-11-21 20:02 ` [PATCH v2 1/3] perf list: Print matching PMU events for --unit Namhyung Kim

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).