Skip to content

Commit b9a6ac4

Browse files
sj-awstorvalds
authored andcommitted
mm/damon: adaptively adjust regions
Even somehow the initial monitoring target regions are well constructed to fulfill the assumption (pages in same region have similar access frequencies), the data access pattern can be dynamically changed. This will result in low monitoring quality. To keep the assumption as much as possible, DAMON adaptively merges and splits each region based on their access frequency. For each ``aggregation interval``, it compares the access frequencies of adjacent regions and merges those if the frequency difference is small. Then, after it reports and clears the aggregated access frequency of each region, it splits each region into two or three regions if the total number of regions will not exceed the user-specified maximum number of regions after the split. In this way, DAMON provides its best-effort quality and minimal overhead while keeping the upper-bound overhead that users set. Link: https://lkml.kernel.org/r/[email protected] Signed-off-by: SeongJae Park <[email protected]> Reviewed-by: Leonard Foerster <[email protected]> Reviewed-by: Fernand Sieber <[email protected]> Acked-by: Shakeel Butt <[email protected]> Cc: Alexander Shishkin <[email protected]> Cc: Amit Shah <[email protected]> Cc: Benjamin Herrenschmidt <[email protected]> Cc: Brendan Higgins <[email protected]> Cc: David Hildenbrand <[email protected]> Cc: David Rientjes <[email protected]> Cc: David Woodhouse <[email protected]> Cc: Fan Du <[email protected]> Cc: Greg Kroah-Hartman <[email protected]> Cc: Greg Thelen <[email protected]> Cc: Ingo Molnar <[email protected]> Cc: Joe Perches <[email protected]> Cc: Jonathan Cameron <[email protected]> Cc: Jonathan Corbet <[email protected]> Cc: Marco Elver <[email protected]> Cc: Markus Boehme <[email protected]> Cc: Maximilian Heyne <[email protected]> Cc: Mel Gorman <[email protected]> Cc: Minchan Kim <[email protected]> Cc: Namhyung Kim <[email protected]> Cc: Peter Zijlstra <[email protected]> Cc: Rik van Riel <[email protected]> Cc: Shuah Khan <[email protected]> Cc: Steven Rostedt (VMware) <[email protected]> Cc: Vladimir Davydov <[email protected]> Cc: Vlastimil Babka <[email protected]> Signed-off-by: Andrew Morton <[email protected]> Signed-off-by: Linus Torvalds <[email protected]>
1 parent f23b8ee commit b9a6ac4

File tree

2 files changed

+237
-17
lines changed

2 files changed

+237
-17
lines changed

include/linux/damon.h

Lines changed: 22 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,9 @@
1212
#include <linux/time64.h>
1313
#include <linux/types.h>
1414

15+
/* Minimal region size. Every damon_region is aligned by this. */
16+
#define DAMON_MIN_REGION PAGE_SIZE
17+
1518
/**
1619
* struct damon_addr_range - Represents an address region of [@start, @end).
1720
* @start: Start address of the region (inclusive).
@@ -39,6 +42,7 @@ struct damon_region {
3942
/**
4043
* struct damon_target - Represents a monitoring target.
4144
* @id: Unique identifier for this target.
45+
* @nr_regions: Number of monitoring target regions of this target.
4246
* @regions_list: Head of the monitoring target regions of this target.
4347
* @list: List head for siblings.
4448
*
@@ -50,6 +54,7 @@ struct damon_region {
5054
*/
5155
struct damon_target {
5256
unsigned long id;
57+
unsigned int nr_regions;
5358
struct list_head regions_list;
5459
struct list_head list;
5560
};
@@ -85,6 +90,8 @@ struct damon_ctx;
8590
* prepared for the next access check.
8691
* @check_accesses should check the accesses to each region that made after the
8792
* last preparation and update the number of observed accesses of each region.
93+
* It should also return max number of observed accesses that made as a result
94+
* of its update. The value will be used for regions adjustment threshold.
8895
* @reset_aggregated should reset the access monitoring results that aggregated
8996
* by @check_accesses.
9097
* @target_valid should check whether the target is still valid for the
@@ -95,7 +102,7 @@ struct damon_primitive {
95102
void (*init)(struct damon_ctx *context);
96103
void (*update)(struct damon_ctx *context);
97104
void (*prepare_access_checks)(struct damon_ctx *context);
98-
void (*check_accesses)(struct damon_ctx *context);
105+
unsigned int (*check_accesses)(struct damon_ctx *context);
99106
void (*reset_aggregated)(struct damon_ctx *context);
100107
bool (*target_valid)(void *target);
101108
void (*cleanup)(struct damon_ctx *context);
@@ -172,7 +179,9 @@ struct damon_callback {
172179
* @primitive: Set of monitoring primitives for given use cases.
173180
* @callback: Set of callbacks for monitoring events notifications.
174181
*
175-
* @region_targets: Head of monitoring targets (&damon_target) list.
182+
* @min_nr_regions: The minimum number of adaptive monitoring regions.
183+
* @max_nr_regions: The maximum number of adaptive monitoring regions.
184+
* @adaptive_targets: Head of monitoring targets (&damon_target) list.
176185
*/
177186
struct damon_ctx {
178187
unsigned long sample_interval;
@@ -191,7 +200,9 @@ struct damon_ctx {
191200
struct damon_primitive primitive;
192201
struct damon_callback callback;
193202

194-
struct list_head region_targets;
203+
unsigned long min_nr_regions;
204+
unsigned long max_nr_regions;
205+
struct list_head adaptive_targets;
195206
};
196207

197208
#define damon_next_region(r) \
@@ -207,28 +218,31 @@ struct damon_ctx {
207218
list_for_each_entry_safe(r, next, &t->regions_list, list)
208219

209220
#define damon_for_each_target(t, ctx) \
210-
list_for_each_entry(t, &(ctx)->region_targets, list)
221+
list_for_each_entry(t, &(ctx)->adaptive_targets, list)
211222

212223
#define damon_for_each_target_safe(t, next, ctx) \
213-
list_for_each_entry_safe(t, next, &(ctx)->region_targets, list)
224+
list_for_each_entry_safe(t, next, &(ctx)->adaptive_targets, list)
214225

215226
#ifdef CONFIG_DAMON
216227

217228
struct damon_region *damon_new_region(unsigned long start, unsigned long end);
218229
inline void damon_insert_region(struct damon_region *r,
219-
struct damon_region *prev, struct damon_region *next);
230+
struct damon_region *prev, struct damon_region *next,
231+
struct damon_target *t);
220232
void damon_add_region(struct damon_region *r, struct damon_target *t);
221-
void damon_destroy_region(struct damon_region *r);
233+
void damon_destroy_region(struct damon_region *r, struct damon_target *t);
222234

223235
struct damon_target *damon_new_target(unsigned long id);
224236
void damon_add_target(struct damon_ctx *ctx, struct damon_target *t);
225237
void damon_free_target(struct damon_target *t);
226238
void damon_destroy_target(struct damon_target *t);
239+
unsigned int damon_nr_regions(struct damon_target *t);
227240

228241
struct damon_ctx *damon_new_ctx(void);
229242
void damon_destroy_ctx(struct damon_ctx *ctx);
230243
int damon_set_attrs(struct damon_ctx *ctx, unsigned long sample_int,
231-
unsigned long aggr_int, unsigned long primitive_upd_int);
244+
unsigned long aggr_int, unsigned long primitive_upd_int,
245+
unsigned long min_nr_reg, unsigned long max_nr_reg);
232246

233247
int damon_start(struct damon_ctx **ctxs, int nr_ctxs);
234248
int damon_stop(struct damon_ctx **ctxs, int nr_ctxs);

0 commit comments

Comments
 (0)