From: Enze Li <lienze@kylinos.cn>
To: sj@kernel.org, akpm@linux-foundation.org
Cc: damon@lists.linux.dev, linux-mm@kvack.org, enze.li@gmx.com,
Enze Li <lienze@kylinos.cn>
Subject: [RFC PATCH 1/2] mm/damon/core: introduce priority concept for DAMON
Date: Mon, 22 Sep 2025 18:10:21 +0800 [thread overview]
Message-ID: <20250922101022.362822-2-lienze@kylinos.cn> (raw)
In-Reply-To: <20250922101022.362822-1-lienze@kylinos.cn>
This patch introduces a priority-based scheme application mechanism to
DAMON, enhancing its ability to prioritize memory management operations
for specific processes. Currently, DAMON applies schemes uniformly
across all monitored processes without regard to their relative
importance. This change allows users to assign a priority value to each
target process, influencing the frequency with which schemes are applied.
The core implementation modifies kdamond_apply_schemes to track and apply
schemes according to user-defined priorities. For instance, if process A
has priority 50 and process B has priority 30, damon_do_apply_schemes
will be called 50 times on A for every 30 times on B. This ratio
ensures that higher-priority processes receive more frequent attention
from DAMON's operations, which can be critical for performance-sensitive
workloads or prioritized tasks.
The change maintains the overall fairness and non-starvation properties
by cycling through targets proportionally. Existing behavior is
preserved for targets without a priority assigned, ensuring backward
compatibility. This provides system administrators with finer control
over how DAMON’s memory optimizations are distributed, making the
subsystem more adaptable to varied use cases and performance
requirements.
Signed-off-by: Enze Li <lienze@kylinos.cn>
---
include/linux/damon.h | 2 +
mm/damon/core.c | 91 ++++++++++++++++++++++++++++++++++++++++++-
2 files changed, 91 insertions(+), 2 deletions(-)
diff --git a/include/linux/damon.h b/include/linux/damon.h
index f13664c62ddd..a6d3ce186fdc 100644
--- a/include/linux/damon.h
+++ b/include/linux/damon.h
@@ -102,6 +102,8 @@ struct damon_target {
unsigned int nr_regions;
struct list_head regions_list;
struct list_head list;
+ unsigned int priority;
+ struct list_head pr_list;
};
/**
diff --git a/mm/damon/core.c b/mm/damon/core.c
index 106ee8b0f2d5..c336914d03cc 100644
--- a/mm/damon/core.c
+++ b/mm/damon/core.c
@@ -15,6 +15,7 @@
#include <linux/slab.h>
#include <linux/string.h>
#include <linux/string_choices.h>
+#include <linux/list_sort.h>
#define CREATE_TRACE_POINTS
#include <trace/events/damon.h>
@@ -28,6 +29,11 @@ static DEFINE_MUTEX(damon_lock);
static int nr_running_ctxs;
static bool running_exclusive_ctxs;
+static LIST_HEAD(priority_list);
+static bool init_priority_list;
+static int priority_level;
+static int priority_tick;
+
static DEFINE_MUTEX(damon_ops_lock);
static struct damon_operations damon_registered_ops[NR_DAMON_OPS];
@@ -474,6 +480,7 @@ struct damon_target *damon_new_target(void)
t->nr_regions = 0;
INIT_LIST_HEAD(&t->regions_list);
INIT_LIST_HEAD(&t->list);
+ t->priority = 0;
return t;
}
@@ -2154,6 +2161,72 @@ static void damos_adjust_quota(struct damon_ctx *c, struct damos *s)
quota->min_score = score;
}
+static int damon_priority_head(void)
+{
+ struct damon_target *t = list_first_entry_or_null(&priority_list,
+ struct damon_target, pr_list);
+
+ return t->priority;
+}
+
+static int damon_priority_find_next(void)
+{
+ struct damon_target *t;
+
+ list_for_each_entry(t, &priority_list, pr_list)
+ if (priority_level > t->priority) {
+ priority_level = t->priority;
+ return t->priority;
+ }
+ return damon_priority_head();
+}
+
+static bool kdamond_targets_priority_enabled(struct damon_ctx *c)
+{
+ struct damon_target *t;
+
+ damon_for_each_target(t, c)
+ if (t->priority > 0)
+ return true;
+ return false;
+}
+
+static int damon_priority_cmp(void *priv, const struct list_head *a,
+ const struct list_head *b)
+{
+ struct damon_target *ta = container_of(a, struct damon_target, pr_list);
+ struct damon_target *tb = container_of(b, struct damon_target, pr_list);
+
+ if (ta->priority < tb->priority)
+ return 1;
+ else
+ return 0;
+}
+
+static bool kdamond_targets_priority_init(struct damon_ctx *c)
+{
+ struct damon_target *t;
+
+ damon_for_each_target(t, c)
+ list_add_tail(&t->pr_list, &priority_list);
+
+ list_for_each_entry(t, &priority_list, pr_list)
+ pr_debug("damon target priority %d %p\n", t->priority, t->pid);
+
+ list_sort(NULL, &priority_list, damon_priority_cmp);
+
+ list_for_each_entry(t, &priority_list, pr_list)
+ pr_debug("damon target priority after sort %d %p\n",
+ t->priority, t->pid);
+
+ init_priority_list = true;
+ priority_level = damon_priority_head();
+ priority_tick = priority_level;
+ pr_debug("damon target priority init level=%d tick=%d\n",
+ priority_level, priority_tick);
+ return true;
+}
+
static void kdamond_apply_schemes(struct damon_ctx *c)
{
struct damon_target *t;
@@ -2162,6 +2235,7 @@ static void kdamond_apply_schemes(struct damon_ctx *c)
unsigned long sample_interval = c->attrs.sample_interval ?
c->attrs.sample_interval : 1;
bool has_schemes_to_apply = false;
+ bool priority_enabled = false;
damon_for_each_scheme(s, c) {
if (c->passed_sample_intervals < s->next_apply_sis)
@@ -2178,10 +2252,23 @@ static void kdamond_apply_schemes(struct damon_ctx *c)
if (!has_schemes_to_apply)
return;
+ priority_enabled = kdamond_targets_priority_enabled(c);
+ if (priority_enabled && !init_priority_list)
+ kdamond_targets_priority_init(c);
+
mutex_lock(&c->walk_control_lock);
damon_for_each_target(t, c) {
- damon_for_each_region_safe(r, next_r, t)
- damon_do_apply_schemes(c, t, r);
+ if (priority_enabled == false ||
+ (priority_enabled == true && t->priority == priority_level &&
+ priority_tick-- > 0)) {
+ if (priority_enabled == true && priority_tick <= 0) {
+ priority_level = damon_priority_find_next();
+ priority_tick = priority_level;
+ }
+ pr_debug("tick() %d(%d)\n", priority_level, priority_tick);
+ damon_for_each_region_safe(r, next_r, t)
+ damon_do_apply_schemes(c, t, r);
+ }
}
damon_for_each_scheme(s, c) {
--
2.51.0
next prev parent reply other threads:[~2025-09-22 10:10 UTC|newest]
Thread overview: 8+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-09-22 10:10 [RFC PATCH 0/2] DAMON: add priority-based scheme application control Enze Li
2025-09-22 10:10 ` Enze Li [this message]
2025-09-22 11:16 ` [RFC PATCH 1/2] mm/damon/core: introduce priority concept for DAMON Gutierrez Asier
2025-09-26 3:57 ` Enze Li
2025-09-22 10:10 ` [RFC PATCH 2/2] mm/damon/sysfs: add priority support for DAMOS targets Enze Li
2025-09-22 13:01 ` [RFC PATCH 0/2] DAMON: add priority-based scheme application control SeongJae Park
2025-09-26 3:23 ` Enze Li
2025-09-26 17:37 ` SeongJae Park
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=20250922101022.362822-2-lienze@kylinos.cn \
--to=lienze@kylinos.cn \
--cc=akpm@linux-foundation.org \
--cc=damon@lists.linux.dev \
--cc=enze.li@gmx.com \
--cc=linux-mm@kvack.org \
--cc=sj@kernel.org \
/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