Skip to content

Commit f04b0fe

Browse files
sjp38akpm00
authored andcommitted
mm/damon/core: implement intervals auto-tuning
Implement the DAMON sampling and aggregation intervals auto-tuning mechanism as briefly described on 'struct damon_intervals_goal'. The core part for deciding the direction and amount of the changes is implemented reusing the feedback loop function which is being used for DAMOS quotas auto-tuning. Unlike the DAMOS quotas auto-tuning use case, limit the maximum decreasing amount after the adjustment to 50% of the current value, though. This is because the intervals have no good merits at rapid reductions since it could unnecessarily increase the monitoring overhead. Link: https://lkml.kernel.org/r/[email protected] Signed-off-by: SeongJae Park <[email protected]> Cc: Jonathan Corbet <[email protected]> Signed-off-by: Andrew Morton <[email protected]>
1 parent 1eb3471 commit f04b0fe

File tree

2 files changed

+92
-0
lines changed

2 files changed

+92
-0
lines changed

include/linux/damon.h

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -713,6 +713,17 @@ struct damon_attrs {
713713
struct damon_intervals_goal intervals_goal;
714714
unsigned long min_nr_regions;
715715
unsigned long max_nr_regions;
716+
/* private: internal use only */
717+
/*
718+
* @aggr_interval to @sample_interval ratio.
719+
* Core-external components call damon_set_attrs() with &damon_attrs
720+
* that this field is unset. In the case, damon_set_attrs() sets this
721+
* field of resulting &damon_attrs. Core-internal components such as
722+
* kdamond_tune_intervals() calls damon_set_attrs() with &damon_attrs
723+
* that this field is set. In the case, damon_set_attrs() just keep
724+
* it.
725+
*/
726+
unsigned long aggr_samples;
716727
};
717728

718729
/**
@@ -761,6 +772,11 @@ struct damon_ctx {
761772
* update
762773
*/
763774
unsigned long next_ops_update_sis;
775+
/*
776+
* number of sample intervals that should be passed before next
777+
* intervals tuning
778+
*/
779+
unsigned long next_intervals_tune_sis;
764780
/* for waiting until the execution of the kdamond_fn is started */
765781
struct completion kdamond_started;
766782
/* for scheme quotas prioritization */

mm/damon/core.c

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -664,6 +664,10 @@ int damon_set_attrs(struct damon_ctx *ctx, struct damon_attrs *attrs)
664664
if (attrs->sample_interval > attrs->aggr_interval)
665665
return -EINVAL;
666666

667+
/* calls from core-external doesn't set this. */
668+
if (!attrs->aggr_samples)
669+
attrs->aggr_samples = attrs->aggr_interval / sample_interval;
670+
667671
ctx->next_aggregation_sis = ctx->passed_sample_intervals +
668672
attrs->aggr_interval / sample_interval;
669673
ctx->next_ops_update_sis = ctx->passed_sample_intervals +
@@ -1301,6 +1305,65 @@ static void kdamond_reset_aggregated(struct damon_ctx *c)
13011305
}
13021306
}
13031307

1308+
static unsigned long damon_get_intervals_score(struct damon_ctx *c)
1309+
{
1310+
struct damon_target *t;
1311+
struct damon_region *r;
1312+
unsigned long sz_region, max_access_events = 0, access_events = 0;
1313+
unsigned long target_access_events;
1314+
unsigned long goal_bp = c->attrs.intervals_goal.access_bp;
1315+
1316+
damon_for_each_target(t, c) {
1317+
damon_for_each_region(r, t) {
1318+
sz_region = damon_sz_region(r);
1319+
max_access_events += sz_region * c->attrs.aggr_samples;
1320+
access_events += sz_region * r->nr_accesses;
1321+
}
1322+
}
1323+
target_access_events = max_access_events * goal_bp / 10000;
1324+
return access_events * 10000 / target_access_events;
1325+
}
1326+
1327+
static unsigned long damon_feed_loop_next_input(unsigned long last_input,
1328+
unsigned long score);
1329+
1330+
static unsigned long damon_get_intervals_adaptation_bp(struct damon_ctx *c)
1331+
{
1332+
unsigned long score_bp, adaptation_bp;
1333+
1334+
score_bp = damon_get_intervals_score(c);
1335+
adaptation_bp = damon_feed_loop_next_input(100000000, score_bp) /
1336+
10000;
1337+
/*
1338+
* adaptaion_bp ranges from 1 to 20,000. Avoid too rapid reduction of
1339+
* the intervals by rescaling [1,10,000] to [5000, 10,000].
1340+
*/
1341+
if (adaptation_bp <= 10000)
1342+
adaptation_bp = 5000 + adaptation_bp / 2;
1343+
return adaptation_bp;
1344+
}
1345+
1346+
static void kdamond_tune_intervals(struct damon_ctx *c)
1347+
{
1348+
unsigned long adaptation_bp;
1349+
struct damon_attrs new_attrs;
1350+
struct damon_intervals_goal *goal;
1351+
1352+
adaptation_bp = damon_get_intervals_adaptation_bp(c);
1353+
if (adaptation_bp == 10000)
1354+
return;
1355+
1356+
new_attrs = c->attrs;
1357+
goal = &c->attrs.intervals_goal;
1358+
new_attrs.sample_interval = min(goal->max_sample_us,
1359+
c->attrs.sample_interval * adaptation_bp / 10000);
1360+
new_attrs.sample_interval = max(goal->min_sample_us,
1361+
new_attrs.sample_interval);
1362+
new_attrs.aggr_interval = new_attrs.sample_interval *
1363+
c->attrs.aggr_samples;
1364+
damon_set_attrs(c, &new_attrs);
1365+
}
1366+
13041367
static void damon_split_region_at(struct damon_target *t,
13051368
struct damon_region *r, unsigned long sz_r);
13061369

@@ -2209,6 +2272,8 @@ static void kdamond_init_intervals_sis(struct damon_ctx *ctx)
22092272
ctx->next_aggregation_sis = ctx->attrs.aggr_interval / sample_interval;
22102273
ctx->next_ops_update_sis = ctx->attrs.ops_update_interval /
22112274
sample_interval;
2275+
ctx->next_intervals_tune_sis = ctx->next_aggregation_sis *
2276+
ctx->attrs.intervals_goal.aggrs;
22122277

22132278
damon_for_each_scheme(scheme, ctx) {
22142279
apply_interval = scheme->apply_interval_us ?
@@ -2293,6 +2358,17 @@ static int kdamond_fn(void *data)
22932358
sample_interval = ctx->attrs.sample_interval ?
22942359
ctx->attrs.sample_interval : 1;
22952360
if (ctx->passed_sample_intervals >= next_aggregation_sis) {
2361+
if (ctx->attrs.intervals_goal.aggrs &&
2362+
ctx->passed_sample_intervals >=
2363+
ctx->next_intervals_tune_sis) {
2364+
ctx->next_intervals_tune_sis +=
2365+
ctx->attrs.aggr_samples *
2366+
ctx->attrs.intervals_goal.aggrs;
2367+
kdamond_tune_intervals(ctx);
2368+
sample_interval = ctx->attrs.sample_interval ?
2369+
ctx->attrs.sample_interval : 1;
2370+
2371+
}
22962372
ctx->next_aggregation_sis = next_aggregation_sis +
22972373
ctx->attrs.aggr_interval / sample_interval;
22982374

0 commit comments

Comments
 (0)