BPF List
 help / color / mirror / Atom feed
From: Mykyta Yatsenko <mykyta.yatsenko5@gmail.com>
To: bot+bpf-ci@kernel.org, bpf@vger.kernel.org, ast@kernel.org,
	andrii@kernel.org, daniel@iogearbox.net, kernel-team@meta.com,
	eddyz87@gmail.com, memxor@gmail.com, qmo@kernel.org
Cc: yatsenko@meta.com, martin.lau@kernel.org,
	yonghong.song@linux.dev, mason@kernel.org,
	ihor.solodrai@linux.dev
Subject: Re: [PATCH bpf-next v2] bpftool: Scale multiplexed perf counters
Date: Thu, 3 Sep 2026 15:33:22 +0100	[thread overview]
Message-ID: <4adbd22f-886e-4497-a6da-55514a1d5fba@gmail.com> (raw)
In-Reply-To: <17835286-3b20-49ec-b5a5-4e5944073282@gmail.com>



On 9/2/26 7:14 PM, Mykyta Yatsenko wrote:
> 
> 
> On 9/2/26 4:20 PM, bot+bpf-ci@kernel.org wrote:
>>> diff --git a/tools/bpf/bpftool/Documentation/bpftool-prog.rst b/tools/bpf/bpftool/Documentation/bpftool-prog.rst
>>> index 90fa2a48cc26a..2280dc4492c06 100644
>>> --- a/tools/bpf/bpftool/Documentation/bpftool-prog.rst
>>> +++ b/tools/bpf/bpftool/Documentation/bpftool-prog.rst
>>> @@ -217,7 +217,9 @@ bpftool prog run *PROG* data_in *FILE* [data_out *FILE* [data_size_out *L*]] [ct
>>>  bpftool prog profile *PROG* [duration *DURATION*] *METRICs*
>>>      Profile *METRICs* for bpf program *PROG* for *DURATION* seconds or until
>>>      user hits <Ctrl+C>. *DURATION* is optional. If *DURATION* is not specified,
>>> -    the profiling will run up to **UINT_MAX** seconds.
>>> +    the profiling will run up to **UINT_MAX** seconds. When **cycles** is
>>> +    selected, plain output also reports the average number of cycles per
>>> +    program run.
>>
>> [ ... ]
>>
>>> diff --git a/tools/bpf/bpftool/prog.c b/tools/bpf/bpftool/prog.c
>>> index a9f730d407a92..ad6d33f838e3c 100644
>>> --- a/tools/bpf/bpftool/prog.c
>>> +++ b/tools/bpf/bpftool/prog.c
>>
>> [ ... ]
>>
>>> @@ -2185,6 +2200,7 @@ static int profile_parse_metrics(int argc, char **argv)
>>>  static void profile_read_values(struct profiler_bpf *obj)
>>>  {
>>>  	__u32 m, cpu, num_cpu = obj->rodata->num_cpu;
>>> +	struct bpf_perf_event_value *val;
>>>  	int reading_map_fd, count_map_fd;
>>>  	__u64 counts[num_cpu];
>>>  	__u32 key = 0;
>>> @@ -2209,6 +2225,7 @@ static void profile_read_values(struct profiler_bpf *obj)
>>>
>>>  	for (m = 0; m < ARRAY_SIZE(metrics); m++) {
>>>  		struct bpf_perf_event_value values[num_cpu];
>>> +		double scale;
>>>
>>>  		if (!metrics[m].selected)
>>>  			continue;
>>> @@ -2220,9 +2237,22 @@ static void profile_read_values(struct profiler_bpf *obj)
>>>  			return;
>>>  		}
>>>  		for (cpu = 0; cpu < num_cpu; cpu++) {
>>> -			metrics[m].val.counter += values[cpu].counter;
>>> -			metrics[m].val.enabled += values[cpu].enabled;
>>> -			metrics[m].val.running += values[cpu].running;
>>> +			val = &values[cpu];
>>> +
>>> +			metrics[m].val.enabled += val->enabled;
>>> +			metrics[m].val.running += val->running;
>>> +
>>> +			/* This counter has never been scheduled */
>>> +			if (!val->running) {
>>> +				if (counts[cpu])
>>> +					p_info("%s not scheduled on CPU %u; results may be inaccurate",
>>> +					       metrics[m].name, cpu);
>>> +				continue;
>>> +			}
>>> +
>>> +			/* Scale counter values to account for perf event multiplexing. */
>>> +			scale = (double)val->enabled / val->running;
>>> +			metrics[m].val.counter += val->counter * scale;
>>>  		}
>>>  		key++;
>>>  	}
>>
>> Does this change the semantics of the JSON output? Looking at
>> profile_print_readings_json() in prog.c:
>>
>> profile_print_readings_json() {
>>     ...
>>     jsonw_lluint_field(json_wtr, "value",   metrics[m].val.counter);
>>     jsonw_lluint_field(json_wtr, "enabled", metrics[m].val.enabled);
>>     jsonw_lluint_field(json_wtr, "running", metrics[m].val.running);
>>     ...
>> }
>>
>> Before this commit "value" was the raw counter sum and "enabled"/"running"
>> let a consumer apply the correction value * enabled / running itself.
>>
>> After this commit "value" is already scaled (multiplied by enabled/running)
>> while "enabled" and "running" remain as raw sums. If an existing consumer
>> of bpftool -j prog profile applies the documented formula - value * enabled
>> / running - it would now double-scale the result.
>>
>> There is no new field and no version marker letting a consumer distinguish
>> between the two output formats. The changelog says only "Scale resulting
>> values similar to how perf does it" without mentioning the JSON output,
>> and the .rst hunk explicitly scopes its wording to plain output ("When
>> **cycles** is selected, plain output also reports ...").
>>
>> Should the JSON "value" field stay raw to keep the interface stable, or
>> should the scaled/raw split be made explicit with a new "scaled_value"
>> field?
>>
>> The same asymmetry appears in plain output. profile_print_readings_plain()
>> still prints the raw multiplex percentage next to a counter that has
>> already been corrected for that percentage:
>>
>> if (val->enabled > val->running)
>>     printf("(%4.2f%%)", val->running * 100.0 / val->enabled);
>>
>> which reads as if the correction still has to be applied by the reader.
>>
> 
> This is a good point. I don't think we should scale for plain output, but not json.
> But otherwise we potentially break users.
>>

Discussed with Andrii, we'll scale for stdout and keep existing behaviour for the json.

>> ---
>> AI reviewed your patch. Please fix the bug or email reply why it's not a bug.
>> See: https://github.com/kernel-patches/vmtest/blob/master/ci/claude/README.md
>>
>> CI run summary: https://github.com/kernel-patches/bpf/actions/runs/33641892894
> 


  reply	other threads:[~2026-09-03 14:33 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-09-02 13:53 [PATCH bpf-next v2] bpftool: Scale multiplexed perf counters Mykyta Yatsenko
2026-09-02 15:20 ` bot+bpf-ci
2026-09-02 18:14   ` Mykyta Yatsenko
2026-09-03 14:33     ` Mykyta Yatsenko [this message]
2026-09-03 16:15       ` Ihor Solodrai

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=4adbd22f-886e-4497-a6da-55514a1d5fba@gmail.com \
    --to=mykyta.yatsenko5@gmail.com \
    --cc=andrii@kernel.org \
    --cc=ast@kernel.org \
    --cc=bot+bpf-ci@kernel.org \
    --cc=bpf@vger.kernel.org \
    --cc=daniel@iogearbox.net \
    --cc=eddyz87@gmail.com \
    --cc=ihor.solodrai@linux.dev \
    --cc=kernel-team@meta.com \
    --cc=martin.lau@kernel.org \
    --cc=mason@kernel.org \
    --cc=memxor@gmail.com \
    --cc=qmo@kernel.org \
    --cc=yatsenko@meta.com \
    --cc=yonghong.song@linux.dev \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox