UPSTREAM: mm/damon/schemes: implement statistics feature
To tune the DAMON-based operation schemes, knowing how many and how large regions are affected by each of the schemes will be helful. Those stats could be used for not only the tuning, but also monitoring of the working set size and the number of regions, if the scheme does not change the program behavior too much. For the reason, this implements the statistics for the schemes. The total number and size of the regions that each scheme is applied are exported to users via '->stat_count' and '->stat_sz' of 'struct damos'. Admins can also check the number by reading 'schemes' debugfs file. The last two integers now represents the stats. To allow collecting the stats without changing the program behavior, this also adds new scheme action, 'DAMOS_STAT'. Note that 'DAMOS_STAT' is not only making no memory operation actions, but also does not reset the age of regions. Link: https://lkml.kernel.org/r/20211001125604.29660-6-sj@kernel.org Signed-off-by: SeongJae Park <sj@kernel.org> Cc: Amit Shah <amit@kernel.org> Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org> Cc: David Hildenbrand <david@redhat.com> Cc: David Rienjes <rientjes@google.com> Cc: David Woodhouse <dwmw@amazon.com> Cc: Greg Thelen <gthelen@google.com> Cc: Jonathan Cameron <Jonathan.Cameron@huawei.com> Cc: Jonathan Corbet <corbet@lwn.net> Cc: Leonard Foerster <foersleo@amazon.de> Cc: Marco Elver <elver@google.com> Cc: Markus Boehme <markubo@amazon.de> Cc: Shakeel Butt <shakeelb@google.com> Cc: Shuah Khan <shuah@kernel.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> (cherry picked from commit 2f0b548c9f03a78f4ce6ab48986e3108028936a6) Bug: 228223814 Signed-off-by: Hailong Tu <tuhailong@oppo.com> Change-Id: Id485ee13922bd769075a77e7263380db32a15544
This commit is contained in:

committed by
Hailong Tu

parent
5203491dbb
commit
ef678357b3
@@ -78,6 +78,7 @@ struct damon_target {
|
|||||||
* @DAMOS_PAGEOUT: Call ``madvise()`` for the region with MADV_PAGEOUT.
|
* @DAMOS_PAGEOUT: Call ``madvise()`` for the region with MADV_PAGEOUT.
|
||||||
* @DAMOS_HUGEPAGE: Call ``madvise()`` for the region with MADV_HUGEPAGE.
|
* @DAMOS_HUGEPAGE: Call ``madvise()`` for the region with MADV_HUGEPAGE.
|
||||||
* @DAMOS_NOHUGEPAGE: Call ``madvise()`` for the region with MADV_NOHUGEPAGE.
|
* @DAMOS_NOHUGEPAGE: Call ``madvise()`` for the region with MADV_NOHUGEPAGE.
|
||||||
|
* @DAMOS_STAT: Do nothing but count the stat.
|
||||||
*/
|
*/
|
||||||
enum damos_action {
|
enum damos_action {
|
||||||
DAMOS_WILLNEED,
|
DAMOS_WILLNEED,
|
||||||
@@ -85,6 +86,7 @@ enum damos_action {
|
|||||||
DAMOS_PAGEOUT,
|
DAMOS_PAGEOUT,
|
||||||
DAMOS_HUGEPAGE,
|
DAMOS_HUGEPAGE,
|
||||||
DAMOS_NOHUGEPAGE,
|
DAMOS_NOHUGEPAGE,
|
||||||
|
DAMOS_STAT, /* Do nothing but only record the stat */
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -96,9 +98,13 @@ enum damos_action {
|
|||||||
* @min_age_region: Minimum age of target regions.
|
* @min_age_region: Minimum age of target regions.
|
||||||
* @max_age_region: Maximum age of target regions.
|
* @max_age_region: Maximum age of target regions.
|
||||||
* @action: &damo_action to be applied to the target regions.
|
* @action: &damo_action to be applied to the target regions.
|
||||||
|
* @stat_count: Total number of regions that this scheme is applied.
|
||||||
|
* @stat_sz: Total size of regions that this scheme is applied.
|
||||||
* @list: List head for siblings.
|
* @list: List head for siblings.
|
||||||
*
|
*
|
||||||
* Note that both the minimums and the maximums are inclusive.
|
* For each aggregation interval, DAMON applies @action to monitoring target
|
||||||
|
* regions fit in the condition and updates the statistics. Note that both
|
||||||
|
* the minimums and the maximums are inclusive.
|
||||||
*/
|
*/
|
||||||
struct damos {
|
struct damos {
|
||||||
unsigned long min_sz_region;
|
unsigned long min_sz_region;
|
||||||
@@ -108,6 +114,8 @@ struct damos {
|
|||||||
unsigned int min_age_region;
|
unsigned int min_age_region;
|
||||||
unsigned int max_age_region;
|
unsigned int max_age_region;
|
||||||
enum damos_action action;
|
enum damos_action action;
|
||||||
|
unsigned long stat_count;
|
||||||
|
unsigned long stat_sz;
|
||||||
struct list_head list;
|
struct list_head list;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -103,6 +103,8 @@ struct damos *damon_new_scheme(
|
|||||||
scheme->min_age_region = min_age_region;
|
scheme->min_age_region = min_age_region;
|
||||||
scheme->max_age_region = max_age_region;
|
scheme->max_age_region = max_age_region;
|
||||||
scheme->action = action;
|
scheme->action = action;
|
||||||
|
scheme->stat_count = 0;
|
||||||
|
scheme->stat_sz = 0;
|
||||||
INIT_LIST_HEAD(&scheme->list);
|
INIT_LIST_HEAD(&scheme->list);
|
||||||
|
|
||||||
return scheme;
|
return scheme;
|
||||||
@@ -544,9 +546,12 @@ static void damon_do_apply_schemes(struct damon_ctx *c,
|
|||||||
continue;
|
continue;
|
||||||
if (r->age < s->min_age_region || s->max_age_region < r->age)
|
if (r->age < s->min_age_region || s->max_age_region < r->age)
|
||||||
continue;
|
continue;
|
||||||
|
s->stat_count++;
|
||||||
|
s->stat_sz += sz;
|
||||||
if (c->primitive.apply_scheme)
|
if (c->primitive.apply_scheme)
|
||||||
c->primitive.apply_scheme(c, t, r, s);
|
c->primitive.apply_scheme(c, t, r, s);
|
||||||
r->age = 0;
|
if (s->action != DAMOS_STAT)
|
||||||
|
r->age = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -106,11 +106,11 @@ static ssize_t sprint_schemes(struct damon_ctx *c, char *buf, ssize_t len)
|
|||||||
|
|
||||||
damon_for_each_scheme(s, c) {
|
damon_for_each_scheme(s, c) {
|
||||||
rc = scnprintf(&buf[written], len - written,
|
rc = scnprintf(&buf[written], len - written,
|
||||||
"%lu %lu %u %u %u %u %d\n",
|
"%lu %lu %u %u %u %u %d %lu %lu\n",
|
||||||
s->min_sz_region, s->max_sz_region,
|
s->min_sz_region, s->max_sz_region,
|
||||||
s->min_nr_accesses, s->max_nr_accesses,
|
s->min_nr_accesses, s->max_nr_accesses,
|
||||||
s->min_age_region, s->max_age_region,
|
s->min_age_region, s->max_age_region,
|
||||||
s->action);
|
s->action, s->stat_count, s->stat_sz);
|
||||||
if (!rc)
|
if (!rc)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
@@ -159,6 +159,7 @@ static bool damos_action_valid(int action)
|
|||||||
case DAMOS_PAGEOUT:
|
case DAMOS_PAGEOUT:
|
||||||
case DAMOS_HUGEPAGE:
|
case DAMOS_HUGEPAGE:
|
||||||
case DAMOS_NOHUGEPAGE:
|
case DAMOS_NOHUGEPAGE:
|
||||||
|
case DAMOS_STAT:
|
||||||
return true;
|
return true;
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
|
@@ -705,6 +705,8 @@ int damon_va_apply_scheme(struct damon_ctx *ctx, struct damon_target *t,
|
|||||||
case DAMOS_NOHUGEPAGE:
|
case DAMOS_NOHUGEPAGE:
|
||||||
madv_action = MADV_NOHUGEPAGE;
|
madv_action = MADV_NOHUGEPAGE;
|
||||||
break;
|
break;
|
||||||
|
case DAMOS_STAT:
|
||||||
|
return 0;
|
||||||
default:
|
default:
|
||||||
pr_warn("Wrong action %d\n", scheme->action);
|
pr_warn("Wrong action %d\n", scheme->action);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
Reference in New Issue
Block a user