All of lore.kernel.org
 help / color / mirror / Atom feed
From: Uladzislau Rezki <urezki@gmail.com>
To: Chen Wandun <chenwandun@huawei.com>
Cc: akpm@linux-foundation.org, shakeelb@google.com,
	npiggin@gmail.com, linux-mm@kvack.org,
	linux-kernel@vger.kernel.org, edumazet@google.com,
	wangkefeng.wang@huawei.com, guohanjun@huawei.com
Subject: Re: [PATCH] mm/vmalloc: introduce alloc_pages_bulk_array_mempolicy to accelerate memory allocation
Date: Sat, 16 Oct 2021 18:27:00 +0200	[thread overview]
Message-ID: <20211016162700.GA1914@pc638.lan> (raw)
In-Reply-To: <20211014092952.1500982-1-chenwandun@huawei.com>

On Thu, Oct 14, 2021 at 05:29:52PM +0800, Chen Wandun wrote:
> It will cause significant performance regressions in some situations
> as Andrew mentioned in [1]. The main situation is vmalloc, vmalloc
> will allocate pages with NUMA_NO_NODE by default, that will result
> in alloc page one by one;
> 
> In order to solve this, __alloc_pages_bulk and mempolicy should be
> considered at the same time.
> 
> 1) If node is specified in memory allocation request, it will alloc
> all pages by __alloc_pages_bulk.
> 
> 2) If interleaving allocate memory, it will cauculate how many pages
> should be allocated in each node, and use __alloc_pages_bulk to alloc
> pages in each node.
> 
> [1]: https://lore.kernel.org/lkml/CALvZod4G3SzP3kWxQYn0fj+VgG-G3yWXz=gz17+3N57ru1iajw@mail.gmail.com/t/#m750c8e3231206134293b089feaa090590afa0f60
> 
> Signed-off-by: Chen Wandun <chenwandun@huawei.com>
> ----------------
> based on "[PATCH] mm/vmalloc: fix numa spreading for large hash tables"
> ---
>  include/linux/gfp.h |  4 +++
>  mm/mempolicy.c      | 76 +++++++++++++++++++++++++++++++++++++++++++++
>  mm/vmalloc.c        | 19 +++---------
>  3 files changed, 85 insertions(+), 14 deletions(-)
> 
> diff --git a/include/linux/gfp.h b/include/linux/gfp.h
> index 558299cb2970..b976c4177299 100644
> --- a/include/linux/gfp.h
> +++ b/include/linux/gfp.h
> @@ -531,6 +531,10 @@ unsigned long __alloc_pages_bulk(gfp_t gfp, int preferred_nid,
>  				struct list_head *page_list,
>  				struct page **page_array);
>  
> +unsigned long alloc_pages_bulk_array_mempolicy(gfp_t gfp,
> +				unsigned long nr_pages,
> +				struct page **page_array);
> +
>  /* Bulk allocate order-0 pages */
>  static inline unsigned long
>  alloc_pages_bulk_list(gfp_t gfp, unsigned long nr_pages, struct list_head *list)
> diff --git a/mm/mempolicy.c b/mm/mempolicy.c
> index 9f8cd1457829..f456c5eb8d10 100644
> --- a/mm/mempolicy.c
> +++ b/mm/mempolicy.c
> @@ -2196,6 +2196,82 @@ struct page *alloc_pages(gfp_t gfp, unsigned order)
>  }
>  EXPORT_SYMBOL(alloc_pages);
>  
> +unsigned long alloc_pages_bulk_array_interleave(gfp_t gfp,
> +		struct mempolicy *pol, unsigned long nr_pages,
> +		struct page **page_array)
> +{
> +	int nodes;
> +	unsigned long nr_pages_per_node;
> +	int delta;
> +	int i;
> +	unsigned long nr_allocated;
> +	unsigned long total_allocated = 0;
> +
> +	nodes = nodes_weight(pol->nodes);
> +	nr_pages_per_node = nr_pages / nodes;
> +	delta = nr_pages - nodes * nr_pages_per_node;
> +
> +	for (i = 0; i < nodes; i++) {
> +		if (delta) {
> +			nr_allocated = __alloc_pages_bulk(gfp,
> +					interleave_nodes(pol), NULL,
> +					nr_pages_per_node + 1, NULL,
> +					page_array);
> +			delta--;
> +		} else {
> +			nr_allocated = __alloc_pages_bulk(gfp,
> +					interleave_nodes(pol), NULL,
> +					nr_pages_per_node, NULL, page_array);
> +		}
> +
> +		page_array += nr_allocated;
> +		total_allocated += nr_allocated;
> +	}
> +
> +	return total_allocated;
> +}
> +
> +unsigned long alloc_pages_bulk_array_preferred_many(gfp_t gfp, int nid,
> +		struct mempolicy *pol, unsigned long nr_pages,
> +		struct page **page_array)
> +{
> +	gfp_t preferred_gfp;
> +	unsigned long nr_allocated = 0;
> +
> +	preferred_gfp = gfp | __GFP_NOWARN;
> +	preferred_gfp &= ~(__GFP_DIRECT_RECLAIM | __GFP_NOFAIL);
> +
> +	nr_allocated  = __alloc_pages_bulk(preferred_gfp, nid, &pol->nodes,
> +					   nr_pages, NULL, page_array);
> +
> +	if (nr_allocated < nr_pages)
> +		nr_allocated += __alloc_pages_bulk(gfp, numa_node_id(), NULL,
> +				nr_pages - nr_allocated, NULL,
> +				page_array + nr_allocated);
> +	return nr_allocated;
> +}
> +
> +unsigned long alloc_pages_bulk_array_mempolicy(gfp_t gfp,
> +		unsigned long nr_pages, struct page **page_array)
> +{
> +	struct mempolicy *pol = &default_policy;
> +
> +	if (!in_interrupt() && !(gfp & __GFP_THISNODE))
> +		pol = get_task_policy(current);
> +
> +	if (pol->mode == MPOL_INTERLEAVE)
> +		return alloc_pages_bulk_array_interleave(gfp, pol,
> +							 nr_pages, page_array);
> +
> +	if (pol->mode == MPOL_PREFERRED_MANY)
> +		return alloc_pages_bulk_array_preferred_many(gfp,
> +				numa_node_id(), pol, nr_pages, page_array);
> +
> +	return __alloc_pages_bulk(gfp, policy_node(gfp, pol, numa_node_id()),
> +				  policy_nodemask(gfp, pol), nr_pages, NULL,
> +				  page_array);
> +}
> +
>  struct folio *folio_alloc(gfp_t gfp, unsigned order)
>  {
>  	struct page *page = alloc_pages(gfp | __GFP_COMP, order);
> diff --git a/mm/vmalloc.c b/mm/vmalloc.c
> index b7ac4a8fe2b3..49adba793f3c 100644
> --- a/mm/vmalloc.c
> +++ b/mm/vmalloc.c
> @@ -2856,23 +2856,14 @@ vm_area_alloc_pages(gfp_t gfp, int nid,
>  			 */
>  			nr_pages_request = min(100U, nr_pages - nr_allocated);
>  
> -			if (nid == NUMA_NO_NODE) {
> -				for (i = 0; i < nr_pages_request; i++) {
> -					page = alloc_page(gfp);
> -					if (page)
> -						pages[nr_allocated + i] = page;
> -					else {
> -						nr = i;
> -						break;
> -					}
> -				}
> -				if (i >= nr_pages_request)
> -					nr = nr_pages_request;
> -			} else {
> +			if (nid == NUMA_NO_NODE)
> +				nr = alloc_pages_bulk_array_mempolicy(gfp,
> +							nr_pages_request,
> +							pages + nr_allocated);
> +			else
>  				nr = alloc_pages_bulk_array_node(gfp, nid,
>  							nr_pages_request,
>  							pages + nr_allocated);
> -			}
>  			nr_allocated += nr;
>  			cond_resched();
>  
> -- 
> 2.25.1
> 
Now it looks much more correct.

Reviewed-by: Uladzislau Rezki (Sony) <urezki@gmail.com>

--
Vlad Rezki


  parent reply	other threads:[~2021-10-16 16:27 UTC|newest]

Thread overview: 16+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-09-28 12:10 [PATCH] mm/vmalloc: fix numa spreading for large hash tables Chen Wandun
2021-09-28 22:33 ` Andrew Morton
2021-10-14  8:50   ` Chen Wandun
2021-10-13 21:46 ` Shakeel Butt
2021-10-14  8:59   ` Chen Wandun
2021-10-15  1:34     ` Nicholas Piggin
2021-10-15  2:31       ` Chen Wandun
2021-10-15  7:11         ` Nicholas Piggin
2021-10-15 11:51           ` Eric Dumazet
2021-10-18  8:45             ` Chen Wandun
2021-10-16 16:46           ` Uladzislau Rezki
2021-10-14  9:29 ` [PATCH] mm/vmalloc: introduce alloc_pages_bulk_array_mempolicy to accelerate memory allocation Chen Wandun
2021-10-15 21:13   ` Andrew Morton
2021-10-16 16:27   ` Uladzislau Rezki [this message]
2021-10-14 10:01 ` [PATCH] mm/vmalloc: fix numa spreading for large hash tables Uladzislau Rezki
2021-10-15  2:20   ` Chen Wandun

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=20211016162700.GA1914@pc638.lan \
    --to=urezki@gmail.com \
    --cc=akpm@linux-foundation.org \
    --cc=chenwandun@huawei.com \
    --cc=edumazet@google.com \
    --cc=guohanjun@huawei.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-mm@kvack.org \
    --cc=npiggin@gmail.com \
    --cc=shakeelb@google.com \
    --cc=wangkefeng.wang@huawei.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.