From: Namhyung Kim <namhyung@kernel.org>
To: Tengda Wu <wutengda@huaweicloud.com>
Cc: Peter Zijlstra <peterz@infradead.org>,
song@kernel.org, Ingo Molnar <mingo@redhat.com>,
Arnaldo Carvalho de Melo <acme@kernel.org>,
Mark Rutland <mark.rutland@arm.com>,
Alexander Shishkin <alexander.shishkin@linux.intel.com>,
Jiri Olsa <jolsa@kernel.org>, Ian Rogers <irogers@google.com>,
Adrian Hunter <adrian.hunter@intel.com>,
kan.liang@linux.intel.com, linux-perf-users@vger.kernel.org,
linux-kernel@vger.kernel.org, bpf@vger.kernel.org
Subject: Re: [PATCH -next v4 1/2] perf stat: Support inherit events during fork() for bperf
Date: Sat, 19 Oct 2024 09:28:29 -0700 [thread overview]
Message-ID: <ZxPeLaYXsEu9N1f1@google.com> (raw)
In-Reply-To: <093e14a9-4008-4490-9946-5080449935c4@huaweicloud.com>
On Sat, Oct 19, 2024 at 04:27:38PM +0800, Tengda Wu wrote:
>
>
> On 2024/10/19 1:12, Namhyung Kim wrote:
> > On Thu, Oct 17, 2024 at 10:53:46AM +0800, Tengda Wu wrote:
> >> Hi,
> >>
> >> On 2024/10/17 5:16, Namhyung Kim wrote:
> >>> Hello,
> >>>
> >>> On Sat, Oct 12, 2024 at 02:32:24AM +0000, Tengda Wu wrote:
> >>>> bperf has a nice ability to share PMUs, but it still does not support
> >>>> inherit events during fork(), resulting in some deviations in its stat
> >>>> results compared with perf.
> >>>>
> >>>> perf stat result:
> >>>> $ ./perf stat -e cycles,instructions -- ./perf test -w sqrtloop
> >>>>
> >>>> Performance counter stats for './perf test -w sqrtloop':
> >>>>
> >>>> 2,316,038,116 cycles
> >>>> 2,859,350,725 instructions
> >>>>
> >>>> 1.009603637 seconds time elapsed
> >>>>
> >>>> 1.004196000 seconds user
> >>>> 0.003950000 seconds sys
> >>>>
> >>>> bperf stat result:
> >>>> $ ./perf stat --bpf-counters -e cycles,instructions -- \
> >>>> ./perf test -w sqrtloop
> >>>>
> >>>> Performance counter stats for './perf test -w sqrtloop':
> >>>>
> >>>> 18,762,093 cycles
> >>>> 23,487,766 instructions
> >>>>
> >>>> 1.008913769 seconds time elapsed
> >>>>
> >>>> 1.003248000 seconds user
> >>>> 0.004069000 seconds sys
> >>>>
> >>>> In order to support event inheritance, two new bpf programs are added
> >>>> to monitor the fork and exit of tasks respectively. When a task is
> >>>> created, add it to the filter map to enable counting, and reuse the
> >>>> `accum_key` of its parent task to count together with the parent task.
> >>>> When a task exits, remove it from the filter map to disable counting.
> >>>>
> >>>> After support:
> >>>> $ ./perf stat --bpf-counters -e cycles,instructions -- \
> >>>> ./perf test -w sqrtloop
> >>>>
> >>>> Performance counter stats for './perf test -w sqrtloop':
> >>>>
> >>>> 2,316,252,189 cycles
> >>>> 2,859,946,547 instructions
> >>>>
> >>>> 1.009422314 seconds time elapsed
> >>>>
> >>>> 1.003597000 seconds user
> >>>> 0.004270000 seconds sys
> >>>>
> >>>> Signed-off-by: Tengda Wu <wutengda@huaweicloud.com>
> >>>> ---
> >>>> tools/perf/builtin-stat.c | 4 +-
> >>>> tools/perf/util/bpf_counter.c | 57 +++++++++---
> >>>> tools/perf/util/bpf_counter.h | 13 ++-
> >>>> tools/perf/util/bpf_counter_cgroup.c | 3 +-
> >>>> tools/perf/util/bpf_skel/bperf_follower.bpf.c | 87 +++++++++++++++++--
> >>>> tools/perf/util/bpf_skel/bperf_u.h | 5 ++
> >>>> 6 files changed, 145 insertions(+), 24 deletions(-)
> >>>>
> >>>> diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
> >>>> index 3e6b9f216e80..c27b107c1985 100644
> >>>> --- a/tools/perf/builtin-stat.c
> >>>> +++ b/tools/perf/builtin-stat.c
> >>>> @@ -698,6 +698,7 @@ static int __run_perf_stat(int argc, const char **argv, int run_idx)
> >>>> char msg[BUFSIZ];
> >>>> unsigned long long t0, t1;
> >>>> struct evsel *counter;
> >>>> + struct bpf_stat_opts opts;
> >>>> size_t l;
> >>>> int status = 0;
> >>>> const bool forks = (argc > 0);
> >>>> @@ -725,7 +726,8 @@ static int __run_perf_stat(int argc, const char **argv, int run_idx)
> >>>>
> >>>> evlist__for_each_entry(evsel_list, counter) {
> >>>> counter->reset_group = false;
> >>>> - if (bpf_counter__load(counter, &target)) {
> >>>> + opts.inherit = !stat_config.no_inherit;
> >>>> + if (bpf_counter__load(counter, &target, &opts)) {
> >>>
> >>> Maybe you can just add a boolean member in the struct target.
> >>
> >> Yes,this approach would be more straightforward.
> >>
> >> I had considered it before, but, as you see, considering that `inherit` does not
> >> align well with the `target` semantics, I chose the another one.
> >
> > Well, I think 'inherit' is well aligned with the target semantics.
> > We want some processes as the targets of the event and we want to
> > profile their children or not.
> >
>
> Ok.
>
> >>
> >> Anyway, I'll try it. Code changes would be more clean. Thanks.
> >>
> >>>
> >>>
> >>>> err = -1;
> >>>> goto err_out;
> >>>> }
> >>>> diff --git a/tools/perf/util/bpf_counter.c b/tools/perf/util/bpf_counter.c
> >>>> index 7a8af60e0f51..00afea6bde63 100644
> >>>> --- a/tools/perf/util/bpf_counter.c
> >>>> +++ b/tools/perf/util/bpf_counter.c
> >>>> @@ -166,7 +166,9 @@ static int bpf_program_profiler_load_one(struct evsel *evsel, u32 prog_id)
> >>>> return -1;
> >>>> }
> >>>>
> >>>> -static int bpf_program_profiler__load(struct evsel *evsel, struct target *target)
> >>>> +static int bpf_program_profiler__load(struct evsel *evsel,
> >>>> + struct target *target,
> >>>> + struct bpf_stat_opts *opts __maybe_unused)
> >>>> {
> >>>> char *bpf_str, *bpf_str_, *tok, *saveptr = NULL, *p;
> >>>> u32 prog_id;
> >>>> @@ -364,6 +366,7 @@ static int bperf_lock_attr_map(struct target *target)
> >>>>
> >>>> static int bperf_check_target(struct evsel *evsel,
> >>>> struct target *target,
> >>>> + struct bpf_stat_opts *opts,
> >>>> enum bperf_filter_type *filter_type,
> >>>> __u32 *filter_entry_cnt)
> >>>> {
> >>>> @@ -383,7 +386,12 @@ static int bperf_check_target(struct evsel *evsel,
> >>>> *filter_type = BPERF_FILTER_PID;
> >>>> *filter_entry_cnt = perf_thread_map__nr(evsel->core.threads);
> >>>> } else if (target->pid || evsel->evlist->workload.pid != -1) {
> >>>> - *filter_type = BPERF_FILTER_TGID;
> >>>> + /*
> >>>> + * unlike the PID type, the TGID type implicitly enables
> >>>> + * event inheritance within a single process.
> >>>> + */
> >>>> + *filter_type = opts->inherit ?
> >>>> + BPERF_FILTER_TGID : BPERF_FILTER_PID;
> >>>
> >>> I'm not sure if it's right. You should be able to use PID type with
> >>> inheritance. In this case child processes or threads from the selected
> >>> thread would be counted only.
> >>
> >> Sorry, don't quite understand. TGID type counts together with all sub-threads within
> >> the same process, which is what inheritance needs to do; while PID type only counts
> >> for a single thread and should be used when inheritance is turned off. This is equivalent
> >> to the code above.
> >
> > Let me be clear:
> >
> > * PID w/o inherit : specified threads only
> > * PID w/ inherit : specified threads + all threads or child process from the threads
> > * TGID w/o inherit: specified process (all threads in the process) only
> > * TGID w/ inherit : specified process + all children from the processes
> >
> > For the TGID w/o inherit case, it's ok not to track new threads in the
> > process because they will have the same tgid anyway.
> >
> > So you cannot change the filter type using inherit value. It should be
> > used to control whether it tracks new task only.
> >
>
> So changing 'TGID w/o inherit' to 'PID w/o inherit' will lose counts of all
> threads in the process, right?
Yep.
>
> It's clear now. Thanks for the explanation.
No problem, looking forward to v5.
Thanks,
Namhyung
next prev parent reply other threads:[~2024-10-19 16:28 UTC|newest]
Thread overview: 8+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-10-12 2:32 [PATCH -next v4 0/2] perf stat: Support inherit events for bperf Tengda Wu
2024-10-12 2:32 ` [PATCH -next v4 1/2] perf stat: Support inherit events during fork() " Tengda Wu
2024-10-16 21:16 ` Namhyung Kim
2024-10-17 2:53 ` Tengda Wu
2024-10-18 17:12 ` Namhyung Kim
2024-10-19 8:27 ` Tengda Wu
2024-10-19 16:28 ` Namhyung Kim [this message]
2024-10-12 2:32 ` [PATCH -next v4 2/2] perf test: Use sqrtloop workload to test bperf event Tengda Wu
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=ZxPeLaYXsEu9N1f1@google.com \
--to=namhyung@kernel.org \
--cc=acme@kernel.org \
--cc=adrian.hunter@intel.com \
--cc=alexander.shishkin@linux.intel.com \
--cc=bpf@vger.kernel.org \
--cc=irogers@google.com \
--cc=jolsa@kernel.org \
--cc=kan.liang@linux.intel.com \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-perf-users@vger.kernel.org \
--cc=mark.rutland@arm.com \
--cc=mingo@redhat.com \
--cc=peterz@infradead.org \
--cc=song@kernel.org \
--cc=wutengda@huaweicloud.com \
/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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.