On Tue, 10 Mar 2020 08:57:47 +0000 Jonathan Cameron <Jonathan.Cameron@xxxxxxxxxx> wrote: > On Mon, 24 Feb 2020 13:30:36 +0100 > SeongJae Park <sjpark@xxxxxxxxxx> wrote: > > > From: SeongJae Park <sjpark@xxxxxxxxx> > > > > At the beginning of the monitoring, DAMON constructs the initial regions > > by evenly splitting the memory mapped address space of the process into > > the user-specified minimal number of regions. In this initial state, > > the assumption of the regions (pages in same region have similar access > > frequencies) is normally not kept and thus the monitoring quality could > > be low. To keep the assumption as much as possible, DAMON adaptively > > merges and splits each region. > > > > 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 regions if the total number > > of regions is smaller than the half of the user-specified maximum number > > of regions. > > > > In this way, DAMON provides its best-effort quality and minimal overhead > > while keeping the bounds users set for their trade-off. > > > > Signed-off-by: SeongJae Park <sjpark@xxxxxxxxx> > > Really minor comments inline. Very helpful comments for me. You are indeed making this much better! Will apply whole your comments below in the next spin. > > > --- > > mm/damon.c | 151 ++++++++++++++++++++++++++++++++++++++++++++++++++--- > > 1 file changed, 144 insertions(+), 7 deletions(-) > > > > diff --git a/mm/damon.c b/mm/damon.c > > index 6bdeb84d89af..1c8bb71bbce9 100644 > > --- a/mm/damon.c > > +++ b/mm/damon.c [...] > > +/* > > + * Merge adjacent regions having similar access frequencies > > + * > > + * t task that merge operation will make change > > + * thres merge regions having '->nr_accesses' diff smaller than this > > + */ > > +static void damon_merge_regions_of(struct damon_task *t, unsigned int thres) > > +{ > > + struct damon_region *r, *prev = NULL, *next; > > + > > + damon_for_each_region_safe(r, next, t) { > > + if (!prev || prev->vm_end != r->vm_start) > > + goto next; > > + if (diff_of(prev->nr_accesses, r->nr_accesses) > thres) > > + goto next; > > if (!prev || prev->vm_end != r->vm_start || > diff_of(prev->nr_accesses, r->nr_accesses) > thres) { > prev = r; > continue; > } > > Seems more logical to my head. Maybe it's just me though. A goto inside a > loop isn't pretty to my mind. Yes, your version seems much prettier to me, either :) > > > + damon_merge_two_regions(prev, r); > > + continue; > > +next: > > + prev = r; > > + } > > +} > > + [...] > > @@ -590,21 +711,29 @@ static int kdamond_fn(void *data) > > struct damon_task *t; > > struct damon_region *r, *next; > > struct mm_struct *mm; > > + unsigned long max_nr_accesses; > > > > pr_info("kdamond (%d) starts\n", ctx->kdamond->pid); > > kdamond_init_regions(ctx); > > while (!kdamond_need_stop(ctx)) { > > + max_nr_accesses = 0; > > damon_for_each_task(ctx, t) { > > mm = damon_get_mm(t); > > if (!mm) > > continue; > > - damon_for_each_region(r, t) > > + damon_for_each_region(r, t) { > > kdamond_check_access(ctx, mm, r); > > + if (r->nr_accesses > max_nr_accesses) > > + max_nr_accesses = r->nr_accesses; > > max_nr_accesses = max(r->nr_accesses, max_nr_accesses) Good point! Thanks, SeongJae Park [...]