From: Vlastimil Babka <vbabka@suse.cz>
To: Suren Baghdasaryan <surenb@google.com>
Cc: "Liam R. Howlett" <Liam.Howlett@oracle.com>,
Christoph Lameter <cl@linux.com>,
David Rientjes <rientjes@google.com>,
Roman Gushchin <roman.gushchin@linux.dev>,
Hyeonggon Yoo <42.hyeyoo@gmail.com>,
Uladzislau Rezki <urezki@gmail.com>,
linux-mm@kvack.org, linux-kernel@vger.kernel.org,
rcu@vger.kernel.org, maple-tree@lists.infradead.org
Subject: Re: [PATCH RFC v2 06/10] slab: sheaf prefilling for guaranteed allocations
Date: Wed, 12 Mar 2025 18:09:04 +0100 [thread overview]
Message-ID: <4a825090-bdc6-46c5-bd5d-71357a03087a@suse.cz> (raw)
In-Reply-To: <CAJuCfpEBqfhaCQnZFKFkNRhXe0z1k0ZBTDw5BXr=Zu9_s0TfkQ@mail.gmail.com>
On 2/23/25 04:54, Suren Baghdasaryan wrote:
> On Fri, Feb 14, 2025 at 8:27 AM Vlastimil Babka <vbabka@suse.cz> wrote:
>>
>> Add functions for efficient guaranteed allocations e.g. in a critical
>> section that cannot sleep, when the exact number of allocations is not
>> known beforehand, but an upper limit can be calculated.
>>
>> kmem_cache_prefill_sheaf() returns a sheaf containing at least given
>> number of objects.
>>
>> kmem_cache_alloc_from_sheaf() will allocate an object from the sheaf
>> and is guaranteed not to fail until depleted.
>>
>> kmem_cache_return_sheaf() is for giving the sheaf back to the slab
>> allocator after the critical section. This will also attempt to refill
>> it to cache's sheaf capacity for better efficiency of sheaves handling,
>> but it's not stricly necessary to succeed.
>>
>> kmem_cache_refill_sheaf() can be used to refill a previously obtained
>> sheaf to requested size. If the current size is sufficient, it does
>> nothing. If the requested size exceeds cache's sheaf_capacity and the
>> sheaf's current capacity, the sheaf will be replaced with a new one,
>> hence the indirect pointer parameter.
>>
>> kmem_cache_sheaf_size() can be used to query the current size.
>>
>> The implementation supports requesting sizes that exceed cache's
>> sheaf_capacity, but it is not efficient - such sheaves are allocated
>> fresh in kmem_cache_prefill_sheaf() and flushed and freed immediately by
>> kmem_cache_return_sheaf(). kmem_cache_refill_sheaf() might be expecially
>
> s/expecially/especially
>
>> ineffective when replacing a sheaf with a new one of a larger capacity.
>> It is therefore better to size cache's sheaf_capacity accordingly.
>
> If support for sizes exceeding sheaf_capacity adds much complexity
> with no performance benefits, I think it would be ok not to support
> them at all. Users know the capacity of a particular kmem_cache, so
> they can use this API only when their needs are within sheaf_capacity,
> otherwise either size the sheaf appropriately or use slab bulk
> allocation.
As Harry explained, the users (e.g. maple tree) would have to implement the
fallback for unusual situations instead, so it's better to implement it just
once here.
>>
>> Signed-off-by: Vlastimil Babka <vbabka@suse.cz>
>
> Reviewed-by: Suren Baghdasaryan <surenb@google.com>
Thanks.
>> +/*
>> + * Use this to return a sheaf obtained by kmem_cache_prefill_sheaf()
>> + * It tries to refill the sheaf back to the cache's sheaf_capacity
>> + * to avoid handling partially full sheaves.
>> + *
>> + * If the refill fails because gfp is e.g. GFP_NOWAIT, the sheaf is
>> + * instead dissolved
>
> Refilling the sheaf here assumes that in the future we are more likely
> to allocate than to free objects or shrink the slab. If the reverse is
> true then it would make sense to flush the sheaf and add it as an
> empty one into the barn. The fact that flushing can't fail would be
> another advantage... We don't know the future but should we be
> predicting a more costly case?
What the comment doesn't say is we first try to make the sheaf become
pcs->spare without any refill. This is the ideal scenario if nobody
interrupts us between prefill (we grab the spare) and return (we return the
spare).
Also the refill is only attempted if the barn can accept full sheaf.
I have clarified the comment.
Maybe we could make the decision to flush e.g. if the sheaf is below half of
the capacity, but that can be subject to further performance evaluation.
>> + */
>> +void kmem_cache_return_sheaf(struct kmem_cache *s, gfp_t gfp,
>> + struct slab_sheaf *sheaf)
>> +{
>> + struct slub_percpu_sheaves *pcs;
>> + bool refill = false;
>> + struct node_barn *barn;
>> +
>> + if (unlikely(sheaf->capacity != s->sheaf_capacity)) {
>> + sheaf_flush(s, sheaf);
>> + kfree(sheaf);
>> + return;
>> + }
>> +
>> + localtry_lock(&s->cpu_sheaves->lock);
>> + pcs = this_cpu_ptr(s->cpu_sheaves);
>> +
>> + if (!pcs->spare) {
>> + pcs->spare = sheaf;
>> + sheaf = NULL;
>> + } else if (pcs->barn->nr_full >= MAX_FULL_SHEAVES) {
>> + /* racy check */
>> + barn = pcs->barn;
>> + refill = true;
>> + }
>> +
>> + localtry_unlock(&s->cpu_sheaves->lock);
>> +
>> + if (!sheaf)
>> + return;
>> +
>> + /*
>> + * if the barn is full of full sheaves or we fail to refill the sheaf,
>> + * simply flush and free it
>> + */
>> + if (!refill || refill_sheaf(s, sheaf, gfp)) {
>> + sheaf_flush(s, sheaf);
>> + free_empty_sheaf(s, sheaf);
>> + return;
>> + }
>> +
>> + /* we racily determined the sheaf would fit, so now force it */
>> + barn_put_full_sheaf(barn, sheaf, true);
>> +}
>> +
>> +/*
>> + * refill a sheaf previously returned by kmem_cache_prefill_sheaf to at least
>> + * the given size
>> + *
>> + * the sheaf might be replaced by a new one when requesting more than
>> + * s->sheaf_capacity objects if such replacement is necessary, but the refill
>> + * fails (with -ENOMEM), the existing sheaf is left intact
>> + */
>> +int kmem_cache_refill_sheaf(struct kmem_cache *s, gfp_t gfp,
>> + struct slab_sheaf **sheafp, unsigned int size)
>> +{
>> + struct slab_sheaf *sheaf;
>> +
>> + /*
>> + * TODO: do we want to support *sheaf == NULL to be equivalent of
>> + * kmem_cache_prefill_sheaf() ?
>> + */
>> + if (!sheafp || !(*sheafp))
>> + return -EINVAL;
>> +
>> + sheaf = *sheafp;
>> + if (sheaf->size >= size)
>> + return 0;
>> +
>> + if (likely(sheaf->capacity >= size)) {
>> + if (likely(sheaf->capacity == s->sheaf_capacity))
>> + return refill_sheaf(s, sheaf, gfp);
>> +
>> + if (!__kmem_cache_alloc_bulk(s, gfp, sheaf->capacity - sheaf->size,
>> + &sheaf->objects[sheaf->size])) {
>> + return -ENOMEM;
>> + }
>> + sheaf->size = sheaf->capacity;
>> +
>> + return 0;
>> + }
>> +
>> + /*
>> + * We had a regular sized sheaf and need an oversize one, or we had an
>> + * oversize one already but need a larger one now.
>> + * This should be a very rare path so let's not complicate it.
>> + */
>> + sheaf = kmem_cache_prefill_sheaf(s, gfp, size);
>
> WIth all the above I think you always end up refilling up to
> sheaf->capacity. Not sure if we should mention that in the comment for
> this function because your statement about refilling to at least the
> given size is still correct.
OK mentioned it in the comment.
next prev parent reply other threads:[~2025-03-12 17:09 UTC|newest]
Thread overview: 55+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-02-14 16:27 [PATCH RFC v2 00/10] SLUB percpu sheaves Vlastimil Babka
2025-02-14 16:27 ` [PATCH RFC v2 01/10] slab: add opt-in caching layer of " Vlastimil Babka
2025-02-22 22:46 ` Suren Baghdasaryan
2025-02-22 22:56 ` Suren Baghdasaryan
2025-03-12 14:57 ` Vlastimil Babka
2025-03-12 15:14 ` Suren Baghdasaryan
2025-03-17 10:09 ` Vlastimil Babka
2025-02-24 8:04 ` Harry Yoo
2025-03-12 14:59 ` Vlastimil Babka
2025-02-14 16:27 ` [PATCH RFC v2 02/10] slab: add sheaf support for batching kfree_rcu() operations Vlastimil Babka
2025-02-22 23:08 ` Suren Baghdasaryan
2025-03-12 16:19 ` Vlastimil Babka
2025-02-24 8:40 ` Harry Yoo
2025-03-12 16:16 ` Vlastimil Babka
2025-02-14 16:27 ` [PATCH RFC v2 03/10] locking/local_lock: Introduce localtry_lock_t Vlastimil Babka
2025-02-17 14:19 ` Sebastian Andrzej Siewior
2025-02-17 14:35 ` Vlastimil Babka
2025-02-17 15:07 ` Sebastian Andrzej Siewior
2025-02-18 18:41 ` Alexei Starovoitov
2025-02-26 17:00 ` Davidlohr Bueso
2025-02-26 17:15 ` Alexei Starovoitov
2025-02-26 19:28 ` Davidlohr Bueso
2025-02-14 16:27 ` [PATCH RFC v2 04/10] locking/local_lock: add localtry_trylock() Vlastimil Babka
2025-02-14 16:27 ` [PATCH RFC v2 05/10] slab: switch percpu sheaves locking to localtry_lock Vlastimil Babka
2025-02-23 2:33 ` Suren Baghdasaryan
2025-02-24 13:08 ` Harry Yoo
2025-02-14 16:27 ` [PATCH RFC v2 06/10] slab: sheaf prefilling for guaranteed allocations Vlastimil Babka
2025-02-23 3:54 ` Suren Baghdasaryan
2025-02-25 7:30 ` Harry Yoo
2025-03-12 17:09 ` Vlastimil Babka [this message]
2025-02-25 8:00 ` Harry Yoo
2025-03-12 18:16 ` Vlastimil Babka
2025-02-14 16:27 ` [PATCH RFC v2 07/10] slab: determine barn status racily outside of lock Vlastimil Babka
2025-02-23 4:00 ` Suren Baghdasaryan
2025-02-25 8:54 ` Harry Yoo
2025-03-12 18:23 ` Vlastimil Babka
2025-02-14 16:27 ` [PATCH RFC v2 08/10] tools: Add testing support for changes to rcu and slab for sheaves Vlastimil Babka
2025-02-23 4:24 ` Suren Baghdasaryan
2025-02-14 16:27 ` [PATCH RFC v2 09/10] tools: Add sheafs support to testing infrastructure Vlastimil Babka
2025-02-14 16:27 ` [PATCH RFC v2 10/10] maple_tree: use percpu sheaves for maple_node_cache Vlastimil Babka
2025-02-23 4:27 ` Suren Baghdasaryan
2025-02-14 18:28 ` [PATCH RFC v2 00/10] SLUB percpu sheaves Christoph Lameter (Ampere)
2025-02-23 0:19 ` Kent Overstreet
2025-02-23 4:44 ` Suren Baghdasaryan
2025-02-24 1:36 ` Suren Baghdasaryan
2025-02-24 1:43 ` Suren Baghdasaryan
2025-02-24 20:53 ` Vlastimil Babka
2025-02-24 21:12 ` Suren Baghdasaryan
2025-02-25 20:26 ` Suren Baghdasaryan
2025-03-04 10:54 ` Vlastimil Babka
2025-03-04 18:35 ` Suren Baghdasaryan
2025-03-04 19:08 ` Liam R. Howlett
2025-03-14 17:10 ` Suren Baghdasaryan
2025-03-17 11:08 ` Vlastimil Babka
2025-03-17 18:56 ` Suren Baghdasaryan
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=4a825090-bdc6-46c5-bd5d-71357a03087a@suse.cz \
--to=vbabka@suse.cz \
--cc=42.hyeyoo@gmail.com \
--cc=Liam.Howlett@oracle.com \
--cc=cl@linux.com \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-mm@kvack.org \
--cc=maple-tree@lists.infradead.org \
--cc=rcu@vger.kernel.org \
--cc=rientjes@google.com \
--cc=roman.gushchin@linux.dev \
--cc=surenb@google.com \
--cc=urezki@gmail.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