From: Uladzislau Rezki <urezki@gmail.com>
To: rulinhuang <rulin.huang@intel.com>
Cc: akpm@linux-foundation.org, urezki@gmail.com, hch@infradead.org,
lstoakes@gmail.com, linux-mm@kvack.org,
linux-kernel@vger.kernel.org, tim.c.chen@intel.com,
colin.king@intel.com, zhiguo.zhou@intel.com
Subject: Re: [PATCH] mm/vmalloc: lock contention optimization under multi-threading
Date: Wed, 7 Feb 2024 10:24:59 +0100 [thread overview]
Message-ID: <ZcNMa-CFEDNWDO2J@pc636> (raw)
In-Reply-To: <20240207033059.1565623-1-rulin.huang@intel.com>
On Tue, Feb 06, 2024 at 10:30:59PM -0500, rulinhuang wrote:
> When allocating a new memory area where the mapping address range is
> known, it is observed that the vmap_area lock is acquired twice.
> The first acquisition occurs in the alloc_vmap_area() function when
> inserting the vm area into the vm mapping red-black tree. The second
> acquisition occurs in the setup_vmalloc_vm() function when updating the
> properties of the vm, such as flags and address, etc.
> Combine these two operations together in alloc_vmap_area(), which
> improves scalability when the vmap_area lock is contended. By doing so,
> the need to acquire the lock twice can also be eliminated.
> With the above change, tested on intel icelake platform(160 vcpu, kernel
> v6.7), a 6% performance improvement and a 7% reduction in overall
> spinlock hotspot are gained on
> stress-ng/pthread(https://github.com/ColinIanKing/stress-ng), which is
> the stress test of thread creations.
>
> Reviewed-by: "Chen, Tim C" <tim.c.chen@intel.com>
> Reviewed-by: "King, Colin" <colin.king@intel.com>
> Signed-off-by: rulinhuang <rulin.huang@intel.com>
> ---
> mm/vmalloc.c | 31 +++++++++++++++----------------
> 1 file changed, 15 insertions(+), 16 deletions(-)
>
> diff --git a/mm/vmalloc.c b/mm/vmalloc.c
> index d12a17fc0c171..3b1f616e8ecf0 100644
> --- a/mm/vmalloc.c
> +++ b/mm/vmalloc.c
> @@ -1577,13 +1577,13 @@ preload_this_cpu_lock(spinlock_t *lock, gfp_t gfp_mask, int node)
>
> /*
> * Allocate a region of KVA of the specified size and alignment, within the
> - * vstart and vend.
> + * vstart and vend. If vm is passed in, the two will also be bound.
> */
> static struct vmap_area *alloc_vmap_area(unsigned long size,
> unsigned long align,
> unsigned long vstart, unsigned long vend,
> int node, gfp_t gfp_mask,
> - unsigned long va_flags)
> + unsigned long va_flags, struct vm_struct *vm)
> {
> struct vmap_area *va;
> unsigned long freed;
> @@ -1627,9 +1627,12 @@ static struct vmap_area *alloc_vmap_area(unsigned long size,
>
> va->va_start = addr;
> va->va_end = addr + size;
> - va->vm = NULL;
> + va->vm = vm;
> va->flags = va_flags;
>
> + if (vm != NULL)
> + vm->addr = (void *)addr;
> +
> spin_lock(&vmap_area_lock);
> insert_vmap_area(va, &vmap_area_root, &vmap_area_list);
> spin_unlock(&vmap_area_lock);
> @@ -2039,7 +2042,8 @@ static void *new_vmap_block(unsigned int order, gfp_t gfp_mask)
> va = alloc_vmap_area(VMAP_BLOCK_SIZE, VMAP_BLOCK_SIZE,
> VMALLOC_START, VMALLOC_END,
> node, gfp_mask,
> - VMAP_RAM|VMAP_BLOCK);
> + VMAP_RAM|VMAP_BLOCK,
> + NULL);
> if (IS_ERR(va)) {
> kfree(vb);
> return ERR_CAST(va);
> @@ -2394,7 +2398,8 @@ void *vm_map_ram(struct page **pages, unsigned int count, int node)
> struct vmap_area *va;
> va = alloc_vmap_area(size, PAGE_SIZE,
> VMALLOC_START, VMALLOC_END,
> - node, GFP_KERNEL, VMAP_RAM);
> + node, GFP_KERNEL, VMAP_RAM,
> + NULL);
> if (IS_ERR(va))
> return NULL;
>
> @@ -2548,14 +2553,6 @@ static inline void setup_vmalloc_vm_locked(struct vm_struct *vm,
> va->vm = vm;
> }
>
> -static void setup_vmalloc_vm(struct vm_struct *vm, struct vmap_area *va,
> - unsigned long flags, const void *caller)
> -{
> - spin_lock(&vmap_area_lock);
> - setup_vmalloc_vm_locked(vm, va, flags, caller);
> - spin_unlock(&vmap_area_lock);
> -}
> -
> static void clear_vm_uninitialized_flag(struct vm_struct *vm)
> {
> /*
> @@ -2592,14 +2589,16 @@ static struct vm_struct *__get_vm_area_node(unsigned long size,
> if (!(flags & VM_NO_GUARD))
> size += PAGE_SIZE;
>
> - va = alloc_vmap_area(size, align, start, end, node, gfp_mask, 0);
> + area->flags = flags;
> + area->caller = caller;
> + area->size = size;
> +
> + va = alloc_vmap_area(size, align, start, end, node, gfp_mask, 0, area);
> if (IS_ERR(va)) {
> kfree(area);
> return NULL;
> }
>
> - setup_vmalloc_vm(area, va, flags, caller);
> -
> /*
>
Thank you for improving this! That was in my radar quite a long time ago :)
Some comments though. I think that such "partial" way of initializing of
"vm_struct" or "vm" is not optimal because it becomes spread between two
places.
Also, i think that we should not remove the setup_vmalloc_vm() function,
instead we can move it in a place where the VA is not inserted to the
tree, i.e. to initialize before insert.
The "locked" variant can be renamed to setup_vmalloc_vm().
Also, could you please post how you tested this patch and stress-ng
figures? This is really good for other people and folk to know.
Thanks!
--
Uladzislau Rezki
next prev parent reply other threads:[~2024-02-07 9:25 UTC|newest]
Thread overview: 18+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-02-07 3:30 [PATCH] mm/vmalloc: lock contention optimization under multi-threading rulinhuang
2024-02-07 9:24 ` Uladzislau Rezki [this message]
2024-02-09 11:51 ` rulinhuang
2024-02-20 9:05 ` [PATCH v2] " rulinhuang
2024-02-20 19:54 ` Andrew Morton
2024-02-21 3:34 ` rulinhuang
2024-02-20 9:12 ` [PATCH] " rulinhuang
2024-02-21 8:38 ` Uladzislau Rezki
2024-02-21 3:29 ` [PATCH v3] " rulinhuang
2024-02-21 8:36 ` Uladzislau Rezki
2024-02-22 12:09 ` rulinhuang
2024-02-22 12:10 ` rulinhuang
2024-02-22 12:52 ` Uladzislau Rezki
2024-02-22 15:36 ` Baoquan He
2024-02-23 13:09 ` rulinhuang
2024-02-22 12:05 ` [PATCH v4] " rulinhuang
2024-02-23 13:03 ` [PATCH v5] " rulinhuang
2024-02-23 14:03 ` Baoquan He
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=ZcNMa-CFEDNWDO2J@pc636 \
--to=urezki@gmail.com \
--cc=akpm@linux-foundation.org \
--cc=colin.king@intel.com \
--cc=hch@infradead.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-mm@kvack.org \
--cc=lstoakes@gmail.com \
--cc=rulin.huang@intel.com \
--cc=tim.c.chen@intel.com \
--cc=zhiguo.zhou@intel.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.