From: Qi Zheng <qi.zheng@linux.dev>
To: Konstantin Khorenko <khorenko@virtuozzo.com>,
Andrew Morton <akpm@linux-foundation.org>,
Dave Chinner <david@fromorbit.com>,
Roman Gushchin <roman.gushchin@linux.dev>,
Muchun Song <muchun.song@linux.dev>,
Johannes Weiner <hannes@cmpxchg.org>,
Michal Hocko <mhocko@kernel.org>,
Shakeel Butt <shakeel.butt@linux.dev>
Cc: linux-mm@kvack.org, linux-kernel@vger.kernel.org,
cgroups@vger.kernel.org
Subject: Re: [PATCH v3] mm/shrinker: allocate shrinker_info_unit from a dedicated kmem_cache
Date: Tue, 20 Oct 2026 10:14:54 +0800 [thread overview]
Message-ID: <f8d85b59-971d-4397-a785-b4ab4d301874@linux.dev> (raw)
In-Reply-To: <20261019-vstor-144715-shrinker_info_unit-kmem_cache-v3-1-0fb061e09bf4@virtuozzo.com>
On 10/20/26 12:11 AM, Konstantin Khorenko wrote:
> shrinker_info_unit holds BITS_PER_LONG atomic_long_t of deferred work
> plus a one-word bitmap, 520 bytes on 64-bit. kzalloc_node() takes it
> from kmalloc-1k, so almost half of every unit is padding.
>
> Allocate the units from a cache of their own, sized to the unit. The
> cache is not cache-line aligned: the counters of a unit already share
> cache lines between shrinkers, and aligning the unit would only keep
> neighbouring units off each other's boundary line, at the cost of part
> of the saving.
>
> Suggested-by: Andrew Morton <akpm@linux-foundation.org>
> Assisted-by: LLM
> Signed-off-by: Konstantin Khorenko <khorenko@virtuozzo.com>
> ---
> This is v3 of patch 1/2 of "mm/shrinker: make per-memcg shrinker units
> cheaper", sent on its own as Andrew asked in the v2 thread.
>
> Patch 2/2 of v1-v2, "mm/shrinker: allocate the per-memcg shrinker units
> on demand", is not part of this posting. It is the change that makes a
> memcg pay only for the shrinkers it uses, and it is discussed separately
> in the v2 thread.
>
> Tested on a 4-CPU, single-node VM with the test from the earlier cover
> letters: 8000 tmpfs mounts, then 2000 empty memory cgroups. The units
> move from kmalloc-1k to the new cache, 31 per order-2 slab, and the
> unreclaimable slab per cgroup goes from 144 KB to 87 KB. Removing the
> cgroups and dropping the caches returns the cache to its earlier size.
>
> memory.reclaim on a cgroup still frees its objects on 140 ext4
> superblocks, and cgroups making their first objects while mounts keep
> raising shrinker_nr_max leave nothing in dmesg, also with
> slub_debug=FZPU on the cache. selftests/cgroup test_memcontrol passes.
> test_kmem_memcg_deletion also fails without the patch, by a similar
> margin.
>
> Changes in v3:
> - Allocate the unit from a dedicated kmem_cache instead of shrinking it
> to 63 ids so that it fits kmalloc-512 (Andrew Morton, Muchun Song).
> New subject, since the unit keeps its size.
> - Link to v2: https://patch.msgid.link/20261014-b4-prep-vstor-144715-size-shrinker_info_unit-to-a-power-of-two-v2-0-51af2aedbe6c@virtuozzo.com
>
> Changes in v2:
> - Patch 1: check the unit size with BUILD_BUG_ON(!is_power_of_2())
> in shrinker_unit_alloc() instead of an open-coded static_assert()
> in the header (Muchun Song).
> - Link to v1: https://patch.msgid.link/20261012-b4-prep-vstor-144715-size-shrinker_info_unit-to-a-power-of-two-v1-0-5a7608393b7a@virtuozzo.com
> ---
> include/linux/memcontrol.h | 1 +
> mm/memcontrol.c | 2 ++
> mm/shrinker.c | 11 +++++++++--
> 3 files changed, 12 insertions(+), 2 deletions(-)
Reviewed-by: Qi Zheng <qi.zheng@linux.dev>
Thanks,
Qi
>
> diff --git a/include/linux/memcontrol.h b/include/linux/memcontrol.h
> index 7d1c0ce189a88..b5a89594c263c 100644
> --- a/include/linux/memcontrol.h
> +++ b/include/linux/memcontrol.h
> @@ -1675,6 +1675,7 @@ static inline u64 mem_cgroup_get_socket_pressure(struct mem_cgroup *memcg)
> }
> #endif
>
> +void shrinker_unit_cache_init(void);
> int alloc_shrinker_info(struct mem_cgroup *memcg);
> void free_shrinker_info(struct mem_cgroup *memcg);
> void set_shrinker_bit(struct mem_cgroup *memcg, int nid, int shrinker_id);
> diff --git a/mm/memcontrol.c b/mm/memcontrol.c
> index 856a7d07586cc..7a817181168ed 100644
> --- a/mm/memcontrol.c
> +++ b/mm/memcontrol.c
> @@ -5717,6 +5717,8 @@ int __init mem_cgroup_init(void)
> memcg_pn_cachep = KMEM_CACHE(mem_cgroup_per_node,
> SLAB_PANIC | SLAB_HWCACHE_ALIGN);
>
> + shrinker_unit_cache_init();
> +
> return 0;
> }
>
> diff --git a/mm/shrinker.c b/mm/shrinker.c
> index 7ec2a9704f6f2..4fb424e721bca 100644
> --- a/mm/shrinker.c
> +++ b/mm/shrinker.c
> @@ -12,6 +12,12 @@ DEFINE_MUTEX(shrinker_mutex);
>
> #ifdef CONFIG_MEMCG
> static int shrinker_nr_max;
> +static struct kmem_cache *shrinker_unit_cachep;
> +
> +void __init shrinker_unit_cache_init(void)
> +{
> + shrinker_unit_cachep = KMEM_CACHE(shrinker_info_unit, SLAB_PANIC);
> +}
>
> static inline int shrinker_unit_size(int nr_items)
> {
> @@ -33,7 +39,7 @@ static inline void shrinker_unit_free(struct shrinker_info *info, int start)
> if (!unit[i])
> break;
>
> - kfree(unit[i]);
> + kmem_cache_free(shrinker_unit_cachep, unit[i]);
> unit[i] = NULL;
> }
> }
> @@ -47,7 +53,8 @@ static inline int shrinker_unit_alloc(struct shrinker_info *new,
> int i;
>
> for (i = start; i < nr; i++) {
> - unit = kzalloc_node(sizeof(*unit), GFP_KERNEL, nid);
> + unit = kmem_cache_alloc_node(shrinker_unit_cachep,
> + GFP_KERNEL | __GFP_ZERO, nid);
> if (!unit) {
> shrinker_unit_free(new, start);
> return -ENOMEM;
>
> ---
> base-commit: a5ebb76233b79db01e82e061173cb73c6d2b5c6b
> change-id: 20261016-vstor-144715-shrinker_info_unit-kmem_cache-69ea3f78b635
>
> Best regards,
> --
> Konstantin Khorenko <khorenko@virtuozzo.com>
>
next prev parent reply other threads:[~2026-10-20 2:15 UTC|newest]
Thread overview: 4+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-10-19 16:11 [PATCH v3] mm/shrinker: allocate shrinker_info_unit from a dedicated kmem_cache Konstantin Khorenko
2026-10-19 17:58 ` Harry Yoo
2026-10-20 2:14 ` Qi Zheng [this message]
2026-10-20 2:32 ` Muchun Song
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=f8d85b59-971d-4397-a785-b4ab4d301874@linux.dev \
--to=qi.zheng@linux.dev \
--cc=akpm@linux-foundation.org \
--cc=cgroups@vger.kernel.org \
--cc=david@fromorbit.com \
--cc=hannes@cmpxchg.org \
--cc=khorenko@virtuozzo.com \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-mm@kvack.org \
--cc=mhocko@kernel.org \
--cc=muchun.song@linux.dev \
--cc=roman.gushchin@linux.dev \
--cc=shakeel.butt@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 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.