Re: [PATCH] mm/damon: Rebase DAMON_RECALIM watermarks for NUMA nodes

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Fri, Feb 04, 2022 at 09:06:42AM +0000, SeongJae Park wrote:
> Hello Jonghyeon, thank you for this patch!

Hi, SeeongJae! Thank you for your review.

> 
> On Fri, 4 Feb 2022 15:40:59 +0900 Jonghyeon Kim <tome01@xxxxxxxxxx> wrote:
> 
> > Current DAMON_RECALIM is not compatible the NUMA memory system. To proactively
> > reclaim memory, DAMON_RECLAIM kernel thread(kdamond) has to wake up before
> > kswapd does reclaim memory. However, the current watermark for proactive
> > reclamation is based on entire system free memory. So, though the one memory
> > node is fully used, kdamond is not waked up.
> 
> Good point!
> 
> > 
> > This patch allows kdamond thread to select watermark options for monitoring
> > specific node or whole system free memory.
> 
> Why only specific NUMA node or whole system, instead of each NUMA node?  Are
> you running DARC for only specific NUMA node?  If that's the case, I think
> implementing your own DAMON-based policy in user space might be a better
> choice.  For example, you could implement and use a user-space daemon that
> monitors free memory ratio of each NUMA node and adjusts the watermarks.
> 

I have tested DAMON_RECLAIM for each NUMA node by using a module. But, I felt
that the goal of DAMON_RECLAIM is dealing with the entire system memory or
specific monitoring regions by using module parameters. So, I hoped to add more
options for DAMON_RECLAIM on the NUMA system.

Another thing I considered is the problem of correlation between NUMA node range
and monitoring start/end addresses, such as "What if we monitor target that
spans multiple nodes?".
In that case, I guess we have to decide the policy for watermarks.

> Hope I'm not making you get me wrong.  You found the important limitation of
> DAMON_RECLAIM, thank you!  I really hope DAMON_RECLAIM to evolve to handle the
> case.  I'm just saying this patch looks like specialized for your special case,
> and there could be a better approach for that.
> 

If you agree that each NUMA node is able to have its own DAMON_RECLAIM daemon
threads, I will add that codes in the next patch.


Thanks for your comments,
Jonghyeon

> 
> Thanks,
> SJ
> 
> > 
> > Signed-off-by: Jonghyeon Kim <tome01@xxxxxxxxxx>
> > ---
> >  include/linux/damon.h |  4 +++-
> >  mm/damon/core.c       | 15 +++++++++++----
> >  mm/damon/dbgfs.c      |  3 ++-
> >  mm/damon/reclaim.c    | 12 +++++++++++-
> >  4 files changed, 27 insertions(+), 7 deletions(-)
> > 
> > diff --git a/include/linux/damon.h b/include/linux/damon.h
> > index 114cfb96d37a..3846b985bcb9 100644
> > --- a/include/linux/damon.h
> > +++ b/include/linux/damon.h
> > @@ -220,6 +220,7 @@ struct damos_stat {
> >   * @wmarks:		Watermarks for automated (in)activation of this scheme.
> >   * @stat:		Statistics of this scheme.
> >   * @list:		List head for siblings.
> > + * @node:		NUMA node of target regions.
> >   *
> >   * For each aggregation interval, DAMON finds regions which fit in the
> >   * condition (&min_sz_region, &max_sz_region, &min_nr_accesses,
> > @@ -251,6 +252,7 @@ struct damos {
> >  	struct damos_watermarks wmarks;
> >  	struct damos_stat stat;
> >  	struct list_head list;
> > +	int node;
> >  };
> >  
> >  struct damon_ctx;
> > @@ -477,7 +479,7 @@ struct damos *damon_new_scheme(
> >  		unsigned int min_nr_accesses, unsigned int max_nr_accesses,
> >  		unsigned int min_age_region, unsigned int max_age_region,
> >  		enum damos_action action, struct damos_quota *quota,
> > -		struct damos_watermarks *wmarks);
> > +		struct damos_watermarks *wmarks, int node);
> >  void damon_add_scheme(struct damon_ctx *ctx, struct damos *s);
> >  void damon_destroy_scheme(struct damos *s);
> >  
> > diff --git a/mm/damon/core.c b/mm/damon/core.c
> > index 07449d46d3d3..dfa87cda0266 100644
> > --- a/mm/damon/core.c
> > +++ b/mm/damon/core.c
> > @@ -87,7 +87,7 @@ struct damos *damon_new_scheme(
> >  		unsigned int min_nr_accesses, unsigned int max_nr_accesses,
> >  		unsigned int min_age_region, unsigned int max_age_region,
> >  		enum damos_action action, struct damos_quota *quota,
> > -		struct damos_watermarks *wmarks)
> > +		struct damos_watermarks *wmarks, int node)
> >  {
> >  	struct damos *scheme;
> >  
> > @@ -125,6 +125,8 @@ struct damos *damon_new_scheme(
> >  	scheme->wmarks.low = wmarks->low;
> >  	scheme->wmarks.activated = true;
> >  
> > +	scheme->node = node;
> > +
> >  	return scheme;
> >  }
> >  
> > @@ -936,13 +938,18 @@ static bool kdamond_need_stop(struct damon_ctx *ctx)
> >  	return true;
> >  }
> >  
> > -static unsigned long damos_wmark_metric_value(enum damos_wmark_metric metric)
> > +static unsigned long damos_wmark_metric_value(struct damos *scheme)
> >  {
> >  	struct sysinfo i;
> > +	enum damos_wmark_metric metric = scheme->wmarks.metric;
> > +	int target_node = scheme->node;
> >  
> >  	switch (metric) {
> >  	case DAMOS_WMARK_FREE_MEM_RATE:
> > -		si_meminfo(&i);
> > +		if (target_node == NUMA_NO_NODE)
> > +			si_meminfo(&i);
> > +		else
> > +			si_meminfo_node(&i, target_node);
> >  		return i.freeram * 1000 / i.totalram;
> >  	default:
> >  		break;
> > @@ -961,7 +968,7 @@ static unsigned long damos_wmark_wait_us(struct damos *scheme)
> >  	if (scheme->wmarks.metric == DAMOS_WMARK_NONE)
> >  		return 0;
> >  
> > -	metric = damos_wmark_metric_value(scheme->wmarks.metric);
> > +	metric = damos_wmark_metric_value(scheme);
> >  	/* higher than high watermark or lower than low watermark */
> >  	if (metric > scheme->wmarks.high || scheme->wmarks.low > metric) {
> >  		if (scheme->wmarks.activated)
> > diff --git a/mm/damon/dbgfs.c b/mm/damon/dbgfs.c
> > index 78ff645433c6..3f61cbde7ec4 100644
> > --- a/mm/damon/dbgfs.c
> > +++ b/mm/damon/dbgfs.c
> > @@ -224,7 +224,8 @@ static struct damos **str_to_schemes(const char *str, ssize_t len,
> >  
> >  		pos += parsed;
> >  		scheme = damon_new_scheme(min_sz, max_sz, min_nr_a, max_nr_a,
> > -				min_age, max_age, action, &quota, &wmarks);
> > +				min_age, max_age, action, &quota, &wmarks,
> > +				NUMA_NO_NODE);
> >  		if (!scheme)
> >  			goto fail;
> >  
> > diff --git a/mm/damon/reclaim.c b/mm/damon/reclaim.c
> > index d85e0898f905..ad80f14d164f 100644
> > --- a/mm/damon/reclaim.c
> > +++ b/mm/damon/reclaim.c
> > @@ -189,6 +189,14 @@ module_param(monitor_region_start, ulong, 0600);
> >  static unsigned long monitor_region_end __read_mostly;
> >  module_param(monitor_region_end, ulong, 0600);
> >  
> > +/*
> > + * NUMA node of target to monitor
> > + *
> > + * If node is NUMA_NO_NODE, watermark is based on system entire memory.
> > + */
> > +static int node __read_mostly = NUMA_NO_NODE;
> > +module_param(node, int, 0600);
> > +
> >  /*
> >   * PID of the DAMON thread
> >   *
> > @@ -298,7 +306,9 @@ static struct damos *damon_reclaim_new_scheme(void)
> >  			/* under the quota. */
> >  			&quota,
> >  			/* (De)activate this according to the watermarks. */
> > -			&wmarks);
> > +			&wmarks,
> > +			/* Watermarks is based on this NUMA node */
> > +			node);
> >  
> >  	return scheme;
> >  }
> > -- 
> > 2.17.1
> > 




[Index of Archives]     [Linux ARM Kernel]     [Linux ARM]     [Linux Omap]     [Fedora ARM]     [IETF Annouce]     [Bugtraq]     [Linux OMAP]     [Linux MIPS]     [eCos]     [Asterisk Internet PBX]     [Linux API]

  Powered by Linux