[PATCH 03/11] xen/page_alloc: Add static per-node counts of free pages

Alejandro Vallejo posted 11 patches 9 months, 1 week ago
[PATCH 03/11] xen/page_alloc: Add static per-node counts of free pages
Posted by Alejandro Vallejo 9 months, 1 week ago
These are effectively the sum of free memory in all zones of each node.
It's an optimization to avoid doing that operation frequently in
following patches that introduce exact-node claims.

Signed-off-by: Alejandro Vallejo <alejandro.vallejo@cloud.com>
---
 xen/common/page_alloc.c | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/xen/common/page_alloc.c b/xen/common/page_alloc.c
index 49c3258169db..733b0300a767 100644
--- a/xen/common/page_alloc.c
+++ b/xen/common/page_alloc.c
@@ -485,6 +485,9 @@ static unsigned long node_need_scrub[MAX_NUMNODES];
 static unsigned long *avail[MAX_NUMNODES];
 static long total_avail_pages;
 
+/* Per-node counts of free pages */
+static unsigned long pernode_avail_pages[MAX_NUMNODES];
+
 static DEFINE_SPINLOCK(heap_lock);
 static long outstanding_claims; /* total outstanding claims by all domains */
 
@@ -1033,6 +1036,7 @@ static struct page_info *alloc_heap_pages(
 
     ASSERT(avail[node][zone] >= request);
     avail[node][zone] -= request;
+    pernode_avail_pages[node] -= request;
     total_avail_pages -= request;
     ASSERT(total_avail_pages >= 0);
 
@@ -1191,6 +1195,8 @@ static int reserve_offlined_page(struct page_info *head)
             continue;
 
         avail[node][zone]--;
+        ASSERT(pernode_avail_pages[node] > 0);
+        pernode_avail_pages[node]--;
         total_avail_pages--;
         ASSERT(total_avail_pages >= 0);
 
@@ -1515,6 +1521,7 @@ static void free_heap_pages(
     }
 
     avail[node][zone] += 1 << order;
+    pernode_avail_pages[node] += 1 << order;
     total_avail_pages += 1 << order;
     if ( need_scrub )
     {
-- 
2.48.1
Re: [PATCH 03/11] xen/page_alloc: Add static per-node counts of free pages
Posted by Jan Beulich 6 months, 1 week ago
On 14.03.2025 18:24, Alejandro Vallejo wrote:
> --- a/xen/common/page_alloc.c
> +++ b/xen/common/page_alloc.c
> @@ -485,6 +485,9 @@ static unsigned long node_need_scrub[MAX_NUMNODES];
>  static unsigned long *avail[MAX_NUMNODES];
>  static long total_avail_pages;
>  
> +/* Per-node counts of free pages */
> +static unsigned long pernode_avail_pages[MAX_NUMNODES];

Performance-wise I find concerning any addition of yet another array like
this one, which - unlike e.g. avail[] - is randomly written from all nodes.
I think we either need to introduce per_node() paralleling per_cpu(), or
(less desirable, but perhaps easier to carry out) data structures need to
be introduced to make sure one particular cache line would only ever be
written from a single node. As it's visible from patch context:
node_need_scrub[] could/should move there, too, for example.

Jan
Re: [PATCH 03/11] xen/page_alloc: Add static per-node counts of free pages
Posted by Roger Pau Monné 6 months, 2 weeks ago
On Fri, Mar 14, 2025 at 05:24:54PM +0000, Alejandro Vallejo wrote:
> These are effectively the sum of free memory in all zones of each node.
> It's an optimization to avoid doing that operation frequently in
> following patches that introduce exact-node claims.
> 
> Signed-off-by: Alejandro Vallejo <alejandro.vallejo@cloud.com>
> ---
>  xen/common/page_alloc.c | 7 +++++++
>  1 file changed, 7 insertions(+)
> 
> diff --git a/xen/common/page_alloc.c b/xen/common/page_alloc.c
> index 49c3258169db..733b0300a767 100644
> --- a/xen/common/page_alloc.c
> +++ b/xen/common/page_alloc.c
> @@ -485,6 +485,9 @@ static unsigned long node_need_scrub[MAX_NUMNODES];
>  static unsigned long *avail[MAX_NUMNODES];
>  static long total_avail_pages;
>  
> +/* Per-node counts of free pages */
> +static unsigned long pernode_avail_pages[MAX_NUMNODES];
> +
>  static DEFINE_SPINLOCK(heap_lock);
>  static long outstanding_claims; /* total outstanding claims by all domains */
>  
> @@ -1033,6 +1036,7 @@ static struct page_info *alloc_heap_pages(
>  
>      ASSERT(avail[node][zone] >= request);
>      avail[node][zone] -= request;
> +    pernode_avail_pages[node] -= request;

Since it's done for the per-zone tracking, you might as well add:

ASSERT(pernode_avail_pages[node] >= request);

here?

Thanks, Roger.