perf stat: Add --hide-zero-events option to suppress zero-count events

When monitoring a large number of events (e.g., with wildcards such as
--event 'syscalls:sys_enter_*'), many matched events will return a count
of zero. This clutters the output, making it difficult to spot the
active events.

Add a new option --hide-zero-events to suppress printing events that
have a count of zero.

To prevent formatting and diagnostic issues, the zero-skipping logic
implements the following rules:

    1. In metric-only mode (i.e., --metric-only), columns must remain
       aligned in the output grid. We evaluate config->metric_only first
       to avoid skipping zero-valued columns, preventing values from
       shifting left and aligning under incorrect headers

    2. For explicitly requested events, we ensure they are not silently
       hidden if they are unsupported. We only hide a zero-count event
       if counter->supported is true, ensuring that unsupported explicit
       events still report "<not supported>"

Signed-off-by: Aaron Tomlin <atomlin@atomlin.com>
Reviewed-by: Ian Rogers <irogers@google.com>
Signed-off-by: Namhyung Kim <namhyung@kernel.org>
This commit is contained in:
Aaron Tomlin 2026-07-18 21:38:00 -04:00 committed by Namhyung Kim
parent e01c7bd5b1
commit 64724095a3
5 changed files with 55 additions and 0 deletions

View File

@ -162,6 +162,9 @@ null run - Don't start any counters.
This can be useful to measure just elapsed wall-clock time - or to assess the
raw overhead of perf stat itself, without running any counters.
--hide-zero-events::
Do not show events with a zero count.
-v::
--verbose::
be more verbose (show counter open errors, etc)

View File

@ -2505,6 +2505,8 @@ int cmd_stat(int argc, const char **argv)
"display details about each run (only with -r option)"),
OPT_BOOLEAN('n', "null", &stat_config.null_run,
"null run - dont start any counters"),
OPT_BOOLEAN(0, "hide-zero-events", &stat_config.hide_zero,
"Do not show events with a zero count"),
OPT_INCR('d', "detailed", &detailed_run,
"detailed run - start a lot of events"),
OPT_BOOLEAN('S', "sync", &sync_run,

View File

@ -546,6 +546,51 @@ test_csv_json_fail() {
fi
}
test_hide_zero_events_stat() {
echo "Hide zero events stat test"
if ! perf stat -e context-switches,cpu-migrations true > "${stat_output}" 2>&1
then
echo "Hide zero events stat test [Skipped event parsing failed]"
return
fi
zero_event=""
if grep -q -E "[[:space:]]+0[[:space:]]+context-switches" "${stat_output}"; then
zero_event="context-switches"
elif grep -q -E "[[:space:]]+0[[:space:]]+cpu-migrations" "${stat_output}"; then
zero_event="cpu-migrations"
fi
if [ -z "$zero_event" ]; then
echo "Hide zero events stat test [Skipped - no zero count event found]"
return
fi
if ! perf stat --hide-zero-events -e context-switches,cpu-migrations true > "${stat_output}" 2>&1
then
echo "Hide zero events stat test [Failed - command failed]"
err=1
return
fi
if grep -q -E "$zero_event" "${stat_output}"
then
echo "Hide zero events stat test [Failed - zero event $zero_event was not hidden]"
err=1
return
fi
# Check that --metric-only works with --hide-zero-events
if ! perf stat --hide-zero-events --metric-only -e instructions,cycles true > "${stat_output}" 2>&1
then
echo "Hide zero events stat test [Failed - metric-only command failed]"
err=1
return
fi
echo "Hide zero events stat test [Success]"
}
test_default_stat
test_null_stat
test_offline_cpu_stat
@ -563,6 +608,7 @@ test_stat_repeat
test_stat_pid
test_stat_delay
test_csv_json_fail
test_hide_zero_events_stat
cleanup
exit $err

View File

@ -907,6 +907,9 @@ static bool should_skip_zero_counter(struct perf_stat_config *config,
/* Metric only counts won't be displayed but the metric wants to be computed. */
if (config->metric_only)
return false;
if (config->hide_zero && counter->supported)
return true;
/*
* Skip value 0 when enabling --per-thread globally,
* otherwise it will have too many 0 output.

View File

@ -69,6 +69,7 @@ struct perf_stat_config {
bool interval_clear;
bool metric_only;
bool null_run;
bool hide_zero;
bool ru_display;
bool big_num;
bool hybrid_merge;