Re: [PATCH v2] perf test: Fix perf stat --bpf-counters on hybrid machines

From: Falcon, Thomas

Date: Fri Apr 03 2026 - 15:21:42 EST


On Wed, 2026-03-25 at 10:16 -0700, Ian Rogers wrote:
> Events on hardware PMUs may open on >1 hardware PMU on hybrid
> machines. Unfortunately multiplexing introduces a scaling issue as
> reported in:
> https://lore.kernel.org/lkml/20250716223924.825772-1-irogers@xxxxxxxxxx/
>
> Switch to using task-clock which as a software event runs on all CPUs
> and has a single PMU.
>
> For when hybrid event scaling is fixed, incorporate support for
> combining hybrid counts as posted by Namhyung Kim in:
> https://lore.kernel.org/lkml/20260319064513.9269-1-namhyung@xxxxxxxxxx/
>
> Signed-off-by: Ian Rogers <irogers@xxxxxxxxxx>
> Acked-by: Namhyung Kim <namhyung@xxxxxxxxxx>

$ sudo ./perf test "perf stat --bpf-counters test" -vvv

Before:

152: perf stat --bpf-counters test:
--- start ---
test child forked, pid 444406
Testing --bpf-counters The difference between 400418163 and 11886805947
are greater than 20%.
---- end(-1) ----
152: perf stat --bpf-counters test :
FAILED!

After:

152: perf stat --bpf-counters test:
--- start ---
test child forked, pid 466896
Testing --bpf-counters [Success]
Testing bpf event modifier [Success]
---- end(0) ----
152: perf stat --bpf-counters test :
Ok


Tested-by: Thomas Falcon <thomas.falcon@xxxxxxxxx>

Thanks,
Tom

> ---
> v1:
> https://lore.kernel.org/lkml/20260323202409.194123-1-irogers@xxxxxxxxxx/
> ---
>  tools/perf/tests/shell/stat_bpf_counters.sh | 55 ++++++++++++++-----
> --
>  1 file changed, 38 insertions(+), 17 deletions(-)
>
> diff --git a/tools/perf/tests/shell/stat_bpf_counters.sh
> b/tools/perf/tests/shell/stat_bpf_counters.sh
> index f43e28a136d3..f8c24ccc7830 100755
> --- a/tools/perf/tests/shell/stat_bpf_counters.sh
> +++ b/tools/perf/tests/shell/stat_bpf_counters.sh
> @@ -5,6 +5,24 @@
>  set -e
>  
>  workload="perf test -w sqrtloop"
> +event=task-clock
> +
> +extract_count()
> +{
> + local target_event="$1"
> +
> + awk -v target="$target_event" -v i=0 -v c=0 '
> + $0 ~ target {
> + i++;
> + c += $1
> + }
> + END {
> + if (i > 0)
> + printf "%.0f\n", c;
> + else
> + print "<not counted>"
> + }'
> +}
>  
>  # check whether $2 is within +/- 20% of $1
>  compare_number()
> @@ -25,15 +43,15 @@ compare_number()
>  
>  check_counts()
>  {
> - base_instructions=$1
> - bpf_instructions=$2
> + base_count=$1
> + bpf_count=$2
>  
> - if [ "$base_instructions" = "<not" ]; then
> - echo "Skipping: instructions event not counted"
> + if [ "$base_count" = "<not counted>" ]; then
> + echo "Skipping: $event event not counted"
>   exit 2
>   fi
> - if [ "$bpf_instructions" = "<not" ]; then
> - echo "Failed: instructions not counted with --bpf-
> counters"
> + if [ "$bpf_count" = "<not counted>" ]; then
> + echo "Failed: $event not counted with --bpf-
> counters"
>   exit 1
>   fi
>  }
> @@ -41,29 +59,32 @@ check_counts()
>  test_bpf_counters()
>  {
>   printf "Testing --bpf-counters "
> - base_instructions=$(perf stat --no-big-num -e instructions -
> - $workload 2>&1 | awk '/instructions/ {print $1}')
> - bpf_instructions=$(perf stat --no-big-num --bpf-counters -e
> instructions -- $workload  2>&1 | awk '/instructions/ {print $1}')
> - check_counts $base_instructions $bpf_instructions
> - compare_number $base_instructions $bpf_instructions
> + base_count=$(perf stat --no-big-num -e "$event" -- $workload
> 2>&1 \
> +          | extract_count "$event")
> + bpf_count=$(perf stat --no-big-num --bpf-counters -e
> "$event" -- $workload  2>&1 \
> +          | extract_count "$event")
> + check_counts "$base_count" "$bpf_count"
> + compare_number "$base_count" "$bpf_count"
>   echo "[Success]"
>  }
>  
>  test_bpf_modifier()
>  {
>   printf "Testing bpf event modifier "
> - stat_output=$(perf stat --no-big-num -e
> instructions/name=base_instructions/,instructions/name=bpf_instructio
> ns/b -- $workload 2>&1)
> - base_instructions=$(echo "$stat_output"| awk
> '/base_instructions/ {print $1}')
> - bpf_instructions=$(echo "$stat_output"| awk
> '/bpf_instructions/ {print $1}')
> - check_counts $base_instructions $bpf_instructions
> - compare_number $base_instructions $bpf_instructions
> + stat_output=$(perf stat --no-big-num \
> +          -e "$event/name=base_$event/,$event/name=bpf_$event/b" --
> $workload 2>&1)
> + base_count=$(echo "$stat_output" | extract_count
> "base_$event")
> + bpf_count=$(echo "$stat_output"|  extract_count
> "bpf_$event")
> + check_counts "$base_count" "$bpf_count"
> + compare_number "$base_count" "$bpf_count"
>   echo "[Success]"
>  }
>  
>  # skip if --bpf-counters is not supported
> -if ! perf stat -e instructions --bpf-counters true > /dev/null 2>&1;
> then
> +if ! perf stat -e "$event" --bpf-counters true > /dev/null 2>&1;
> then
>   if [ "$1" = "-v" ]; then
>   echo "Skipping: --bpf-counters not supported"
> - perf --no-pager stat -e instructions --bpf-counters
> true || true
> + perf --no-pager stat -e "$event" --bpf-counters true
> || true
>   fi
>   exit 2
>  fi