From: Jiri Olsa <olsajiri@gmail.com>
To: Andrii Nakryiko <andrii.nakryiko@gmail.com>
Cc: Jiri Olsa <olsajiri@gmail.com>,
Andrii Nakryiko <andrii@kernel.org>,
linux-trace-kernel@vger.kernel.org, peterz@infradead.org,
mingo@kernel.org, oleg@redhat.com, rostedt@goodmis.org,
mhiramat@kernel.org, bpf@vger.kernel.org,
linux-kernel@vger.kernel.org, liaochang1@huawei.com,
kernel-team@meta.com
Subject: Re: [PATCH perf/core 4/4] uprobes: reuse return_instances between multiple uretprobes within task
Date: Sat, 7 Dec 2024 01:36:57 +0100 [thread overview]
Message-ID: <Z1OYqdCZXXbNGEE8@krava> (raw)
In-Reply-To: <CAEf4BzaESrHfAXZrN0VbjQvxLJ0ij0ujKpsp2T6iQtbisYPa=A@mail.gmail.com>
On Fri, Dec 06, 2024 at 10:00:16AM -0800, Andrii Nakryiko wrote:
> On Fri, Dec 6, 2024 at 6:07 AM Jiri Olsa <olsajiri@gmail.com> wrote:
> >
> > On Thu, Dec 05, 2024 at 04:24:17PM -0800, Andrii Nakryiko wrote:
> >
> > SNIP
> >
> > > +static void free_ret_instance(struct uprobe_task *utask,
> > > + struct return_instance *ri, bool cleanup_hprobe)
> > > +{
> > > + unsigned seq;
> > > +
> > > if (cleanup_hprobe) {
> > > enum hprobe_state hstate;
> > >
> > > @@ -1897,8 +1923,22 @@ static void free_ret_instance(struct return_instance *ri, bool cleanup_hprobe)
> > > hprobe_finalize(&ri->hprobe, hstate);
> > > }
> > >
> > > - kfree(ri->extra_consumers);
> > > - kfree_rcu(ri, rcu);
> > > + /*
> > > + * At this point return_instance is unlinked from utask's
> > > + * return_instances list and this has become visible to ri_timer().
> > > + * If seqcount now indicates that ri_timer's return instance
> > > + * processing loop isn't active, we can return ri into the pool of
> > > + * to-be-reused return instances for future uretprobes. If ri_timer()
> > > + * happens to be running right now, though, we fallback to safety and
> > > + * just perform RCU-delated freeing of ri.
> > > + */
> > > + if (raw_seqcount_try_begin(&utask->ri_seqcount, seq)) {
> > > + /* immediate reuse of ri without RCU GP is OK */
> > > + ri_pool_push(utask, ri);
> >
> > should the push be limitted somehow? I wonder you could make uprobes/consumers
> > setup that would allocate/push many of ri instances that would not be freed
> > until the process exits?
>
> So I'm just relying on the existing MAX_URETPROBE_DEPTH limit that is
> enforced by prepare_uretprobe anyways. But yes, we can have up to 64
> instances in ri_pool.
>
> I did consider cleaning this up from ri_timer() (that would be a nice
> properly, because ri_timer fires after 100ms of inactivity), and my
> initial version did use lockless llist for that, but there is a bit of
> a problem: llist doesn't support popping single iter from the list
> (you can only atomically take *all* of the items) in lockless way. So
> my implementation had to swap the entire list, take one element out of
> it, and then put N - 1 items back. Which, when there are deep chains
> of uretprobes, would be quite an unnecessary CPU overhead. And I
> clearly didn't want to add locking anywhere in this hot path, of
> course.
>
> So I figured that at the absolute worst case we'll just keep
> MAX_URETPROBE_DEPTH items in ri_pool until the task dies. That's not
> that much memory for a small subset of tasks on the system.
>
> One more idea I explored and rejected was to limit the size of ri_pool
> to something smaller than MAX_URETPROBE_DEPTH, say just 16. But then
> there is a corner case of high-frequency long chain of uretprobes up
> to 64 depth, then returning through all of them, and then going into
> the same set of functions again, up to 64. So depth oscillates between
> 0 and full 64. In this case this ri_pool will be causing allocation
> for the majority of those invocations, completely defeating the
> purpose.
>
> So, in the end, it felt like 64 cached instances (worst case, if we
> actually ever reached such a deep chain) would be acceptable.
> Especially that commonly I wouldn't expect more than 3-4, actually.
>
> WDYT?
ah ok, there's MAX_URETPROBE_DEPTH limit for task, 64 should be fine
thanks,
jirka
>
> >
> > jirka
> >
> > > + } else {
> > > + /* we might be racing with ri_timer(), so play it safe */
> > > + ri_free(ri);
> > > + }
> > > }
> > >
> > > /*
>
> [...]
next prev parent reply other threads:[~2024-12-07 0:37 UTC|newest]
Thread overview: 23+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-12-06 0:24 [PATCH perf/core 0/4] Improve performance and scalability of uretprobes Andrii Nakryiko
2024-12-06 0:24 ` [PATCH perf/core 1/4] uprobes: simplify session consumer tracking Andrii Nakryiko
2024-12-06 9:38 ` [tip: perf/core] uprobes: Simplify " tip-bot2 for Andrii Nakryiko
2024-12-06 14:07 ` [PATCH perf/core 1/4] uprobes: simplify " Jiri Olsa
2024-12-06 17:50 ` Andrii Nakryiko
2024-12-09 10:32 ` [tip: perf/core] uprobes: Simplify " tip-bot2 for Andrii Nakryiko
2024-12-09 14:55 ` tip-bot2 for Andrii Nakryiko
2024-12-06 0:24 ` [PATCH perf/core 2/4] uprobes: decouple return_instance list traversal and freeing Andrii Nakryiko
2024-12-06 9:38 ` [tip: perf/core] uprobes: Decouple " tip-bot2 for Andrii Nakryiko
2024-12-09 10:32 ` tip-bot2 for Andrii Nakryiko
2024-12-09 14:55 ` tip-bot2 for Andrii Nakryiko
2024-12-06 0:24 ` [PATCH perf/core 3/4] uprobes: ensure return_instance is detached from the list before freeing Andrii Nakryiko
2024-12-06 9:38 ` [tip: perf/core] uprobes: Ensure " tip-bot2 for Andrii Nakryiko
2024-12-09 10:32 ` tip-bot2 for Andrii Nakryiko
2024-12-09 14:55 ` tip-bot2 for Andrii Nakryiko
2024-12-06 0:24 ` [PATCH perf/core 4/4] uprobes: reuse return_instances between multiple uretprobes within task Andrii Nakryiko
2024-12-06 9:38 ` [tip: perf/core] uprobes: Reuse " tip-bot2 for Andrii Nakryiko
2024-12-06 14:07 ` [PATCH perf/core 4/4] uprobes: reuse " Jiri Olsa
2024-12-06 18:00 ` Andrii Nakryiko
2024-12-07 0:36 ` Jiri Olsa [this message]
2024-12-06 14:09 ` Jiri Olsa
2024-12-09 10:32 ` [tip: perf/core] uprobes: Reuse " tip-bot2 for Andrii Nakryiko
2024-12-09 14:55 ` tip-bot2 for Andrii Nakryiko
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=Z1OYqdCZXXbNGEE8@krava \
--to=olsajiri@gmail.com \
--cc=andrii.nakryiko@gmail.com \
--cc=andrii@kernel.org \
--cc=bpf@vger.kernel.org \
--cc=kernel-team@meta.com \
--cc=liaochang1@huawei.com \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-trace-kernel@vger.kernel.org \
--cc=mhiramat@kernel.org \
--cc=mingo@kernel.org \
--cc=oleg@redhat.com \
--cc=peterz@infradead.org \
--cc=rostedt@goodmis.org \
/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