From: Shakeel Butt <shakeelb@google.com>
To: Tejun Heo <tj@kernel.org>, Mina Almasry <almasrymina@google.com>
Cc: Yafang Shao <laoar.shao@gmail.com>,
Alexei Starovoitov <ast@kernel.org>,
Daniel Borkmann <daniel@iogearbox.net>,
Andrii Nakryiko <andrii@kernel.org>, Martin Lau <kafai@fb.com>,
Song Liu <songliubraving@fb.com>, Yonghong Song <yhs@fb.com>,
john fastabend <john.fastabend@gmail.com>,
KP Singh <kpsingh@kernel.org>,
Stanislav Fomichev <sdf@google.com>, Hao Luo <haoluo@google.com>,
jolsa@kernel.org, Johannes Weiner <hannes@cmpxchg.org>,
Michal Hocko <mhocko@kernel.org>,
Roman Gushchin <roman.gushchin@linux.dev>,
Muchun Song <songmuchun@bytedance.com>,
Andrew Morton <akpm@linux-foundation.org>,
Zefan Li <lizefan.x@bytedance.com>,
Cgroups <cgroups@vger.kernel.org>,
netdev <netdev@vger.kernel.org>, bpf <bpf@vger.kernel.org>,
Linux MM <linux-mm@kvack.org>,
Yosry Ahmed <yosryahmed@google.com>,
Dan Schatzberg <schatzberg.dan@gmail.com>,
Lennart Poettering <lennart@poettering.net>
Subject: Re: [RFD RESEND] cgroup: Persistent memory usage tracking
Date: Mon, 22 Aug 2022 09:12:25 -0700 [thread overview]
Message-ID: <CALvZod6EHB74L2kJz7=gv3ev3+UTbBX3a1AsRgF2rgesjXCx3w@mail.gmail.com> (raw)
In-Reply-To: <YwNold0GMOappUxc@slm.duckdns.org>
Ccing Mina.
On Mon, Aug 22, 2022 at 4:29 AM Tejun Heo <tj@kernel.org> wrote:
>
> (Sorry, this is a resend. I messed up the header in the first posting.)
>
> Hello,
>
> This thread started on a bpf-specific memory tracking change proposal and
> went south, but a lot of people who would be interested are already cc'd, so
> I'm hijacking it to discuss what to do w/ persistent memory usage tracking.
>
> Cc'ing Mina and Yosry who were involved in the discussions on the similar
> problem re. tmpfs, Dan Schatzberg who has a lot more prod knowledge and
> experience than me, and Lennart for his thoughts from systemd side.
>
> The root problem is that there are resources (almost solely memory
> currently) that outlive a given instance of a, to use systemd-lingo,
> service. Page cache is the most common case.
>
> Let's say there's system.slice/hello.service. When it runs for the first
> time, page cache backing its binary will be charged to hello.service.
> However, when it restarts after e.g. a config change, when the initial
> hello.service cgroup gets destroyed, we reparent the page cache charges to
> the parent system.slice and when the second instance starts, its binary will
> stay charged to system.slice. Over time, some may get reclaimed and
> refaulted into the new hello.service but that's not guaranteed and most hot
> pages likely won't.
>
> The same problem exists for any memory which is not freed synchronously when
> the current instance exits. While this isn't a problem for many cases, it's
> not difficult to imagine situations where the amount of memory which ends up
> getting pushed to the parent is significant, even clear majority, with big
> page cache footprint, persistent tmpfs instances and so on, creating issues
> with accounting accuracy and thus control.
>
> I think there are two broad issues to discuss here:
>
> [1] Can this be solved by layering the instance cgroups under persistent
> entity cgroup?
>
> So, instead of systemd.slice/hello.service, the application runs inside
> something like systemd.slice/hello.service/hello.service.instance and the
> service-level cgroup hello.service is not destroyed as long as it is
> something worth tracking on the system.
>
> The benefits are
>
> a. While requiring changing how userland organizes cgroup hiearchy, it is a
> straight-forward extension of the current architecture and doesn't
> require any conceptual or structural changes. All the accounting and
> control schemes work exactly the same as before. The only difference is
> that we now have a persistent entity representing each service as we want
> to track their persistent resource usages.
>
> b. Per-instance tracking and control is optional. To me, it seems that the
> persistent resource usages would be more meaningful than per-instance and
> tracking down to the persistent usages shouldn't add noticeable runtime
> overheads while keeping per-instance process management niceties and
> allowing use cases to opt-in for per-instance resource tracking and
> control as needed.
>
> The complications are:
>
> a. It requires changing cgroup hierarchy in a very visible way.
>
> b. What should be the lifetime rules for persistent cgroups? Do we keep them
> around forever or maybe they can be created on the first use and kept
> around until the service is removed from the system? When the persistent
> cgroup is removed, do we need to make sure that the remaining resource
> usages are low enough? Note that this problem exists for any approach
> that tries to track persistent usages no matter how it's done.
>
> c. Do we need to worry about nesting overhead? Given that there's no reason
> to enable controllers w/o persisten states for the instance level and the
> nesting overhead is pretty low for memcg, this doesn't seem like a
> problem to me. If this becomes a problem, we just need to fix it.
>
> A couple alternatives discussed are:
>
> a. Userspace keeps reusing the same cgroup for different instances of the
> same service. This simplifies some aspects while making others more
> complicated. e.g. Determining the current instance's CPU or IO usages now
> require the monitoring software remembering what they were when this
> instance started and calculating the deltas. Also, if some use cases want
> to distinguish persistent vs. instance usages (more on this later), this
> isn't gonna work. That said, this definitely is attractive in that it
> miminizes overt user visible changes.
>
> b. Memory is disassociated rather than just reparented on cgroup destruction
> and get re-charged to the next first user. This is attractive in that it
> doesn't require any userspace changes; however, I'm not sure how this
> would work for non-pageable memory usages such as bpf maps. How would we
> detect the next first usage?
>
>
> [2] Whether and how to solve first and second+ instance charge differences.
>
> If we take the layering approach, the first instance will get charged for
> all memory that it uses while the second+ instances likely won't get charged
> for a lot of persistent usages. I don't think there is a consensus on
> whether this needs to be solved and I don't have enough context to form a
> strong opinion. memcg folks are a lot better equipped to make this decision.
>
> Assuming this needs to be solved, here's a braindump to be taken with a big
> pinch of salt:
>
> I have a bit of difficult time imagining a perfect solution given that
> whether a given page cache page is persistent or not would be really
> difficult to know (or maybe all page cache is persistent by default while
> anon is not). However, the problem still seems worthwhile to consider for
> big ticket items such as persistent tmpfs mounts and huge bpf maps as they
> can easily make the differences really big.
>
> If we want to solve this problem, here are options that I can think of:
>
> a. Let userspace put the charges where they belong using the current
> mechanisms. ie. Create persistent entities in the persistent parent
> cgroup while there's no current instance.
>
> Pro: It won't require any major kernel or interface changes. There still
> need to be some tweaking such as allowing tmpfs pages to be always
> charged to the cgroup which created the instance (maybe as long as it's
> an ancestor of the faulting cgroup?) but nothing too invasive.
>
> Con: It may not be flexible enough.
>
> b. Let userspace specify which cgroup to charge for some of constructs like
> tmpfs and bpf maps. The key problems with this approach are
>
> 1. How to grant/deny what can be charged where. We must ensure that a
> descendant can't move charges up or across the tree without the
> ancestors allowing it.
>
> 2. How to specify the cgroup to charge. While specifying the target
> cgroup directly might seem like an obvious solution, it has a couple
> rather serious problems. First, if the descendant is inside a cgroup
> namespace, it might be able to see the target cgroup at all. Second,
> it's an interface which is likely to cause misunderstandings on how it
> can be used. It's too broad an interface.
>
> One solution that I can think of is leveraging the resource domain
> concept which is currently only used for threaded cgroups. All memory
> usages of threaded cgroups are charged to their resource domain cgroup
> which hosts the processes for those threads. The persistent usages have a
> similar pattern, so maybe the service level cgroup can declare that it's
> the encompassing resource domain and the instance cgroup can say whether
> it's gonna charge e.g. the tmpfs instance to its own or the encompassing
> resource domain.
>
> This has the benefit that the user only needs to indicate its intention
> without worrying about how cgroups are composed and what their IDs are.
> It just indicates whether the given resource is persistent and if the
> cgroup hierarchy is set up for that, it gets charged that way and if not
> it can be just charged to itself.
>
> This is a shower thought but, if we allow nesting such domains (and maybe
> name them), we can use it for shared resources too so that co-services
> are put inside a shared slice and shared resources are pushed to the
> slice level.
>
> This became pretty long. I obviously have a pretty strong bias towards
> solving this within the current basic architecture but other than that most
> of these decisions are best made by memcg folks. We can hopefully build some
> consensus on the issue.
>
> Thanks.
>
> --
> tejun
next prev parent reply other threads:[~2022-08-22 16:15 UTC|newest]
Thread overview: 36+ messages / expand[flat|nested] mbox.gz Atom feed top
2022-08-18 14:31 [PATCH bpf-next v2 00/12] bpf: Introduce selectable memcg for bpf map Yafang Shao
2022-08-18 14:31 ` [PATCH bpf-next v2 01/12] cgroup: Update the comment on cgroup_get_from_fd Yafang Shao
2022-08-18 19:11 ` Yosry Ahmed
2022-08-18 14:31 ` [PATCH bpf-next v2 02/12] bpf: Introduce new helper bpf_map_put_memcg() Yafang Shao
2022-08-18 14:31 ` [PATCH bpf-next v2 03/12] bpf: Define bpf_map_{get,put}_memcg for !CONFIG_MEMCG_KMEM Yafang Shao
2022-08-18 14:31 ` [PATCH bpf-next v2 04/12] bpf: Call bpf_map_init_from_attr() immediately after map creation Yafang Shao
2022-08-18 14:31 ` [PATCH bpf-next v2 05/12] bpf: Save memcg in bpf_map_init_from_attr() Yafang Shao
2022-08-18 14:31 ` [PATCH bpf-next v2 06/12] bpf: Use scoped-based charge in bpf_map_area_alloc Yafang Shao
2022-08-18 14:31 ` [PATCH bpf-next v2 07/12] bpf: Introduce new helpers bpf_ringbuf_pages_{alloc,free} Yafang Shao
2022-08-18 17:30 ` Andrii Nakryiko
2022-08-18 14:31 ` [PATCH bpf-next v2 08/12] bpf: Use bpf_map_kzalloc in arraymap Yafang Shao
2022-08-18 14:31 ` [PATCH bpf-next v2 09/12] bpf: Use bpf_map_kvcalloc in bpf_local_storage Yafang Shao
2022-08-18 14:31 ` [PATCH bpf-next v2 10/12] mm, memcg: Add new helper get_obj_cgroup_from_cgroup Yafang Shao
2022-08-18 20:38 ` Shakeel Butt
2022-08-19 1:21 ` Yafang Shao
2022-08-18 14:31 ` [PATCH bpf-next v2 11/12] bpf: Add return value for bpf_map_init_from_attr Yafang Shao
2022-08-18 14:31 ` [PATCH bpf-next v2 12/12] bpf: Introduce selectable memcg for bpf map Yafang Shao
2022-08-18 22:20 ` [PATCH bpf-next v2 00/12] " Tejun Heo
2022-08-18 22:33 ` Tejun Heo
2022-08-19 1:09 ` Yafang Shao
2022-08-19 17:06 ` Tejun Heo
2022-08-20 2:25 ` Yafang Shao
2022-08-22 11:29 ` [RFD RESEND] cgroup: Persistent memory usage tracking Tejun Heo
2022-08-22 16:12 ` Shakeel Butt [this message]
2022-08-22 19:02 ` Mina Almasry
2022-08-22 21:19 ` Johannes Weiner
2022-08-22 21:52 ` Mina Almasry
2022-08-23 3:01 ` Roman Gushchin
2022-08-23 3:14 ` Tejun Heo
2022-08-24 19:02 ` Mina Almasry
2022-08-25 17:59 ` Tejun Heo
2022-08-23 11:08 ` Yafang Shao
2022-08-23 17:12 ` Tejun Heo
2022-08-24 11:57 ` Yafang Shao
2022-08-19 0:59 ` [PATCH bpf-next v2 00/12] bpf: Introduce selectable memcg for bpf map Yafang Shao
2022-08-19 16:45 ` Tejun Heo
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='CALvZod6EHB74L2kJz7=gv3ev3+UTbBX3a1AsRgF2rgesjXCx3w@mail.gmail.com' \
--to=shakeelb@google.com \
--cc=akpm@linux-foundation.org \
--cc=almasrymina@google.com \
--cc=andrii@kernel.org \
--cc=ast@kernel.org \
--cc=bpf@vger.kernel.org \
--cc=cgroups@vger.kernel.org \
--cc=daniel@iogearbox.net \
--cc=hannes@cmpxchg.org \
--cc=haoluo@google.com \
--cc=john.fastabend@gmail.com \
--cc=jolsa@kernel.org \
--cc=kafai@fb.com \
--cc=kpsingh@kernel.org \
--cc=laoar.shao@gmail.com \
--cc=lennart@poettering.net \
--cc=linux-mm@kvack.org \
--cc=lizefan.x@bytedance.com \
--cc=mhocko@kernel.org \
--cc=netdev@vger.kernel.org \
--cc=roman.gushchin@linux.dev \
--cc=schatzberg.dan@gmail.com \
--cc=sdf@google.com \
--cc=songliubraving@fb.com \
--cc=songmuchun@bytedance.com \
--cc=tj@kernel.org \
--cc=yhs@fb.com \
--cc=yosryahmed@google.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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox