mm/damon/core: introduce nr_accesses_bp
authorSeongJae Park <sj@kernel.org>
Fri, 15 Sep 2023 02:52:48 +0000 (02:52 +0000)
committerAndrew Morton <akpm@linux-foundation.org>
Wed, 4 Oct 2023 17:32:30 +0000 (10:32 -0700)
Add yet another representation of the access rate of each region, namely
nr_accesses_bp.  It is just same to the nr_accesses but represents the
value in basis point (1 in 10,000), and updated at once in every
aggregation interval.  That is, moving_accesses_bp is just nr_accesses *
10000.  This may seems useless at the moment.  However, it will be useful
for representing less than one nr_accesses value that will be needed to
make moving sum-based nr_accesses.

Link: https://lkml.kernel.org/r/20230915025251.72816-6-sj@kernel.org
Signed-off-by: SeongJae Park <sj@kernel.org>
Cc: Brendan Higgins <brendanhiggins@google.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
include/linux/damon.h
mm/damon/core-test.h
mm/damon/core.c

index 487a545..15f24b2 100644 (file)
@@ -40,6 +40,7 @@ struct damon_addr_range {
  * @ar:                        The address range of the region.
  * @sampling_addr:     Address of the sample for the next access check.
  * @nr_accesses:       Access frequency of this region.
+ * @nr_accesses_bp:    @nr_accesses in basis point (0.01%).
  * @list:              List head for siblings.
  * @age:               Age of this region.
  *
@@ -49,6 +50,9 @@ struct damon_addr_range {
  * not be done with direct access but with the helper function,
  * damon_update_region_access_rate().
  *
+ * @nr_accesses_bp is another representation of @nr_accesses in basis point
+ * (1 in 10,000) that updated every aggregation interval.
+ *
  * @age is initially zero, increased for each aggregation interval, and reset
  * to zero again if the access frequency is significantly changed.  If two
  * regions are merged into a new region, both @nr_accesses and @age of the new
@@ -58,6 +62,7 @@ struct damon_region {
        struct damon_addr_range ar;
        unsigned long sampling_addr;
        unsigned int nr_accesses;
+       unsigned int nr_accesses_bp;
        struct list_head list;
 
        unsigned int age;
index c539f0e..79f1f12 100644 (file)
@@ -94,6 +94,7 @@ static void damon_test_aggregate(struct kunit *test)
                for (ir = 0; ir < 3; ir++) {
                        r = damon_new_region(saddr[it][ir], eaddr[it][ir]);
                        r->nr_accesses = accesses[it][ir];
+                       r->nr_accesses_bp = accesses[it][ir] * 10000;
                        damon_add_region(r, t);
                }
                it++;
@@ -147,9 +148,11 @@ static void damon_test_merge_two(struct kunit *test)
        t = damon_new_target();
        r = damon_new_region(0, 100);
        r->nr_accesses = 10;
+       r->nr_accesses_bp = 100000;
        damon_add_region(r, t);
        r2 = damon_new_region(100, 300);
        r2->nr_accesses = 20;
+       r2->nr_accesses_bp = 200000;
        damon_add_region(r2, t);
 
        damon_merge_two_regions(t, r, r2);
@@ -196,6 +199,7 @@ static void damon_test_merge_regions_of(struct kunit *test)
        for (i = 0; i < ARRAY_SIZE(sa); i++) {
                r = damon_new_region(sa[i], ea[i]);
                r->nr_accesses = nrs[i];
+               r->nr_accesses_bp = nrs[i] * 10000;
                damon_add_region(r, t);
        }
 
@@ -297,6 +301,7 @@ static void damon_test_update_monitoring_result(struct kunit *test)
        struct damon_region *r = damon_new_region(3, 7);
 
        r->nr_accesses = 15;
+       r->nr_accesses_bp = 150000;
        r->age = 20;
 
        new_attrs = (struct damon_attrs){
index b005dc1..ce85c00 100644 (file)
@@ -128,6 +128,7 @@ struct damon_region *damon_new_region(unsigned long start, unsigned long end)
        region->ar.start = start;
        region->ar.end = end;
        region->nr_accesses = 0;
+       region->nr_accesses_bp = 0;
        INIT_LIST_HEAD(&region->list);
 
        region->age = 0;
@@ -508,6 +509,7 @@ static void damon_update_monitoring_result(struct damon_region *r,
 {
        r->nr_accesses = damon_nr_accesses_for_new_attrs(r->nr_accesses,
                        old_attrs, new_attrs);
+       r->nr_accesses_bp = r->nr_accesses * 10000;
        r->age = damon_age_for_new_attrs(r->age, old_attrs, new_attrs);
 }
 
@@ -1115,6 +1117,7 @@ static void damon_merge_two_regions(struct damon_target *t,
 
        l->nr_accesses = (l->nr_accesses * sz_l + r->nr_accesses * sz_r) /
                        (sz_l + sz_r);
+       l->nr_accesses_bp = l->nr_accesses * 10000;
        l->age = (l->age * sz_l + r->age * sz_r) / (sz_l + sz_r);
        l->ar.end = r->ar.end;
        damon_destroy_region(r, t);
@@ -1138,6 +1141,8 @@ static void damon_merge_regions_of(struct damon_target *t, unsigned int thres,
                else
                        r->age++;
 
+               r->nr_accesses_bp = r->nr_accesses * 10000;
+
                if (prev && prev->ar.end == r->ar.start &&
                    abs(prev->nr_accesses - r->nr_accesses) <= thres &&
                    damon_sz_region(prev) + damon_sz_region(r) <= sz_limit)
@@ -1186,6 +1191,7 @@ static void damon_split_region_at(struct damon_target *t,
 
        new->age = r->age;
        new->last_nr_accesses = r->last_nr_accesses;
+       new->nr_accesses_bp = r->nr_accesses_bp;
 
        damon_insert_region(new, r, damon_next_region(r), t);
 }