Skip to content

Commit fda504f

Browse files
sjp38torvalds
authored andcommitted
mm/damon/core: account age of target regions
Patch series "Implement Data Access Monitoring-based Memory Operation Schemes". Introduction ============ DAMON[1] can be used as a primitive for data access aware memory management optimizations. For that, users who want such optimizations should run DAMON, read the monitoring results, analyze it, plan a new memory management scheme, and apply the new scheme by themselves. Such efforts will be inevitable for some complicated optimizations. However, in many other cases, the users would simply want the system to apply a memory management action to a memory region of a specific size having a specific access frequency for a specific time. For example, "page out a memory region larger than 100 MiB keeping only rare accesses more than 2 minutes", or "Do not use THP for a memory region larger than 2 MiB rarely accessed for more than 1 seconds". To make the works easier and non-redundant, this patchset implements a new feature of DAMON, which is called Data Access Monitoring-based Operation Schemes (DAMOS). Using the feature, users can describe the normal schemes in a simple way and ask DAMON to execute those on its own. [1] https://damonitor.github.io Evaluations =========== DAMOS is accurate and useful for memory management optimizations. An experimental DAMON-based operation scheme for THP, 'ethp', removes 76.15% of THP memory overheads while preserving 51.25% of THP speedup. Another experimental DAMON-based 'proactive reclamation' implementation, 'prcl', reduces 93.38% of residential sets and 23.63% of system memory footprint while incurring only 1.22% runtime overhead in the best case (parsec3/freqmine). NOTE that the experimental THP optimization and proactive reclamation are not for production but only for proof of concepts. Please refer to the showcase web site's evaluation document[1] for detailed evaluation setup and results. [1] https://damonitor.github.io/doc/html/v34/vm/damon/eval.html Long-term Support Trees ----------------------- For people who want to test DAMON but using LTS kernels, there are another couple of trees based on two latest LTS kernels respectively and containing the 'damon/master' backports. - For v5.4.y: https://git.kernel.org/sj/h/damon/for-v5.4.y - For v5.10.y: https://git.kernel.org/sj/h/damon/for-v5.10.y Sequence Of Patches =================== The 1st patch accounts age of each region. The 2nd patch implements the core of the DAMON-based operation schemes feature. The 3rd patch makes the default monitoring primitives for virtual address spaces to support the schemes. From this point, the kernel space users can use DAMOS. The 4th patch exports the feature to the user space via the debugfs interface. The 5th patch implements schemes statistics feature for easier tuning of the schemes and runtime access pattern analysis, and the 6th patch adds selftests for these changes. Finally, the 7th patch documents this new feature. This patch (of 7): DAMON can be used for data access pattern aware memory management optimizations. For that, users should run DAMON, read the monitoring results, analyze it, plan a new memory management scheme, and apply the new scheme by themselves. It would not be too hard, but still require some level of effort. For complicated cases, this effort is inevitable. That said, in many cases, users would simply want to apply an actions to a memory region of a specific size having a specific access frequency for a specific time. For example, "page out a memory region larger than 100 MiB but having a low access frequency more than 10 minutes", or "Use THP for a memory region larger than 2 MiB having a high access frequency for more than 2 seconds". For such optimizations, users will need to first account the age of each region themselves. To reduce such efforts, this implements a simple age account of each region in DAMON. For each aggregation step, DAMON compares the access frequency with that from last aggregation and reset the age of the region if the change is significant. Else, the age is incremented. Also, in case of the merge of regions, the region size-weighted average of the ages is set as the age of merged new region. Link: https://lkml.kernel.org/r/[email protected] Link: https://lkml.kernel.org/r/[email protected] Signed-off-by: SeongJae Park <[email protected]> Cc: Jonathan Cameron <[email protected]> Cc: Amit Shah <[email protected]> Cc: Benjamin Herrenschmidt <[email protected]> Cc: Jonathan Corbet <[email protected]> Cc: David Hildenbrand <[email protected]> Cc: David Woodhouse <[email protected]> Cc: Marco Elver <[email protected]> Cc: Leonard Foerster <[email protected]> Cc: Greg Thelen <[email protected]> Cc: Markus Boehme <[email protected]> Cc: David Rienjes <[email protected]> Cc: Shakeel Butt <[email protected]> Cc: Shuah Khan <[email protected]> Signed-off-by: Andrew Morton <[email protected]> Signed-off-by: Linus Torvalds <[email protected]>
1 parent 7ec1992 commit fda504f

File tree

2 files changed

+23
-0
lines changed

2 files changed

+23
-0
lines changed

include/linux/damon.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,12 +31,22 @@ struct damon_addr_range {
3131
* @sampling_addr: Address of the sample for the next access check.
3232
* @nr_accesses: Access frequency of this region.
3333
* @list: List head for siblings.
34+
* @age: Age of this region.
35+
*
36+
* @age is initially zero, increased for each aggregation interval, and reset
37+
* to zero again if the access frequency is significantly changed. If two
38+
* regions are merged into a new region, both @nr_accesses and @age of the new
39+
* region are set as region size-weighted average of those of the two regions.
3440
*/
3541
struct damon_region {
3642
struct damon_addr_range ar;
3743
unsigned long sampling_addr;
3844
unsigned int nr_accesses;
3945
struct list_head list;
46+
47+
unsigned int age;
48+
/* private: Internal value for age calculation. */
49+
unsigned int last_nr_accesses;
4050
};
4151

4252
/**

mm/damon/core.c

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,9 @@ struct damon_region *damon_new_region(unsigned long start, unsigned long end)
4545
region->nr_accesses = 0;
4646
INIT_LIST_HEAD(&region->list);
4747

48+
region->age = 0;
49+
region->last_nr_accesses = 0;
50+
4851
return region;
4952
}
5053

@@ -444,6 +447,7 @@ static void kdamond_reset_aggregated(struct damon_ctx *c)
444447

445448
damon_for_each_region(r, t) {
446449
trace_damon_aggregated(t, r, damon_nr_regions(t));
450+
r->last_nr_accesses = r->nr_accesses;
447451
r->nr_accesses = 0;
448452
}
449453
}
@@ -461,6 +465,7 @@ static void damon_merge_two_regions(struct damon_target *t,
461465

462466
l->nr_accesses = (l->nr_accesses * sz_l + r->nr_accesses * sz_r) /
463467
(sz_l + sz_r);
468+
l->age = (l->age * sz_l + r->age * sz_r) / (sz_l + sz_r);
464469
l->ar.end = r->ar.end;
465470
damon_destroy_region(r, t);
466471
}
@@ -480,6 +485,11 @@ static void damon_merge_regions_of(struct damon_target *t, unsigned int thres,
480485
struct damon_region *r, *prev = NULL, *next;
481486

482487
damon_for_each_region_safe(r, next, t) {
488+
if (diff_of(r->nr_accesses, r->last_nr_accesses) > thres)
489+
r->age = 0;
490+
else
491+
r->age++;
492+
483493
if (prev && prev->ar.end == r->ar.start &&
484494
diff_of(prev->nr_accesses, r->nr_accesses) <= thres &&
485495
sz_damon_region(prev) + sz_damon_region(r) <= sz_limit)
@@ -527,6 +537,9 @@ static void damon_split_region_at(struct damon_ctx *ctx,
527537

528538
r->ar.end = new->ar.start;
529539

540+
new->age = r->age;
541+
new->last_nr_accesses = r->last_nr_accesses;
542+
530543
damon_insert_region(new, r, damon_next_region(r), t);
531544
}
532545

0 commit comments

Comments
 (0)