2023-02-14 03:55:00

by T.J. Alumbaugh

[permalink] [raw]
Subject: [PATCH mm-unstable v1 1/2] mm: multi-gen LRU: clean up sysfs code

This patch cleans up the sysfs code. Specifically,
1. use sysfs_emit(),
2. use __ATTR_RW(), and
3. constify multi-gen LRU struct attribute_group.

Signed-off-by: T.J. Alumbaugh <[email protected]>
---
include/linux/mmzone.h | 2 +-
mm/vmscan.c | 22 +++++++++-------------
2 files changed, 10 insertions(+), 14 deletions(-)

diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h
index 9fb1b03b83b2..bf8786d45b31 100644
--- a/include/linux/mmzone.h
+++ b/include/linux/mmzone.h
@@ -1369,7 +1369,7 @@ typedef struct pglist_data {

#ifdef CONFIG_LRU_GEN
/* kswap mm walk data */
- struct lru_gen_mm_walk mm_walk;
+ struct lru_gen_mm_walk mm_walk;
/* lru_gen_folio list */
struct lru_gen_memcg memcg_lru;
#endif
diff --git a/mm/vmscan.c b/mm/vmscan.c
index d4b9fd1ae0ed..09c064accdb1 100644
--- a/mm/vmscan.c
+++ b/mm/vmscan.c
@@ -5658,14 +5658,14 @@ static void lru_gen_change_state(bool enabled)
* sysfs interface
******************************************************************************/

-static ssize_t show_min_ttl(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
+static ssize_t min_ttl_ms_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
{
- return sprintf(buf, "%u\n", jiffies_to_msecs(READ_ONCE(lru_gen_min_ttl)));
+ return sysfs_emit(buf, "%u\n", jiffies_to_msecs(READ_ONCE(lru_gen_min_ttl)));
}

/* see Documentation/admin-guide/mm/multigen_lru.rst for details */
-static ssize_t store_min_ttl(struct kobject *kobj, struct kobj_attribute *attr,
- const char *buf, size_t len)
+static ssize_t min_ttl_ms_store(struct kobject *kobj, struct kobj_attribute *attr,
+ const char *buf, size_t len)
{
unsigned int msecs;

@@ -5677,11 +5677,9 @@ static ssize_t store_min_ttl(struct kobject *kobj, struct kobj_attribute *attr,
return len;
}

-static struct kobj_attribute lru_gen_min_ttl_attr = __ATTR(
- min_ttl_ms, 0644, show_min_ttl, store_min_ttl
-);
+static struct kobj_attribute lru_gen_min_ttl_attr = __ATTR_RW(min_ttl_ms);

-static ssize_t show_enabled(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
+static ssize_t enabled_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
{
unsigned int caps = 0;

@@ -5698,7 +5696,7 @@ static ssize_t show_enabled(struct kobject *kobj, struct kobj_attribute *attr, c
}

/* see Documentation/admin-guide/mm/multigen_lru.rst for details */
-static ssize_t store_enabled(struct kobject *kobj, struct kobj_attribute *attr,
+static ssize_t enabled_store(struct kobject *kobj, struct kobj_attribute *attr,
const char *buf, size_t len)
{
int i;
@@ -5725,9 +5723,7 @@ static ssize_t store_enabled(struct kobject *kobj, struct kobj_attribute *attr,
return len;
}

-static struct kobj_attribute lru_gen_enabled_attr = __ATTR(
- enabled, 0644, show_enabled, store_enabled
-);
+static struct kobj_attribute lru_gen_enabled_attr = __ATTR_RW(enabled);

static struct attribute *lru_gen_attrs[] = {
&lru_gen_min_ttl_attr.attr,
@@ -5735,7 +5731,7 @@ static struct attribute *lru_gen_attrs[] = {
NULL
};

-static struct attribute_group lru_gen_attr_group = {
+static const struct attribute_group lru_gen_attr_group = {
.name = "lru_gen",
.attrs = lru_gen_attrs,
};
--
2.39.1.581.gbfd45094c4-goog



2023-02-14 03:55:12

by T.J. Alumbaugh

[permalink] [raw]
Subject: [PATCH mm-unstable v1 2/2] mm: multi-gen LRU: improve design doc

This patch improves the design doc. Specifically,
1. add a section for the per-memcg mm_struct list, and
2. add a section for the PID controller.

Signed-off-by: T.J. Alumbaugh <[email protected]>
---
Documentation/mm/multigen_lru.rst | 44 +++++++++++++++++++++++++++----
mm/vmscan.c | 2 +-
2 files changed, 40 insertions(+), 6 deletions(-)

diff --git a/Documentation/mm/multigen_lru.rst b/Documentation/mm/multigen_lru.rst
index 5f1f6ecbb79b..52ed5092022f 100644
--- a/Documentation/mm/multigen_lru.rst
+++ b/Documentation/mm/multigen_lru.rst
@@ -103,7 +103,8 @@ moving across tiers only involves atomic operations on
``folio->flags`` and therefore has a negligible cost. A feedback loop
modeled after the PID controller monitors refaults over all the tiers
from anon and file types and decides which tiers from which types to
-evict or protect.
+evict or protect. The desired effect is to balance refault percentages
+between anon and file types proportional to the swappiness level.

There are two conceptually independent procedures: the aging and the
eviction. They form a closed-loop system, i.e., the page reclaim.
@@ -156,6 +157,27 @@ This time-based approach has the following advantages:
and memory sizes.
2. It is more reliable because it is directly wired to the OOM killer.

+``mm_struct`` list
+------------------
+An ``mm_struct`` list is maintained for each memcg, and an
+``mm_struct`` follows its owner task to the new memcg when this task
+is migrated.
+
+A page table walker iterates ``lruvec_memcg()->mm_list`` and calls
+``walk_page_range()`` with each ``mm_struct`` on this list to scan
+PTEs. When multiple page table walkers iterate the same list, each of
+them gets a unique ``mm_struct``, and therefore they can run in
+parallel.
+
+Page table walkers ignore any misplaced pages, e.g., if an
+``mm_struct`` was migrated, pages left in the previous memcg will be
+ignored when the current memcg is under reclaim. Similarly, page table
+walkers will ignore pages from nodes other than the one under reclaim.
+
+This infrastructure also tracks the usage of ``mm_struct`` between
+context switches so that page table walkers can skip processes that
+have been sleeping since the last iteration.
+
Rmap/PT walk feedback
---------------------
Searching the rmap for PTEs mapping each page on an LRU list (to test
@@ -170,7 +192,7 @@ promotes hot pages. If the scan was done cacheline efficiently, it
adds the PMD entry pointing to the PTE table to the Bloom filter. This
forms a feedback loop between the eviction and the aging.

-Bloom Filters
+Bloom filters
-------------
Bloom filters are a space and memory efficient data structure for set
membership test, i.e., test if an element is not in the set or may be
@@ -186,6 +208,18 @@ is false positive, the cost is an additional scan of a range of PTEs,
which may yield hot pages anyway. Parameters of the filter itself can
control the false positive rate in the limit.

+PID controller
+--------------
+A feedback loop modeled after the Proportional-Integral-Derivative
+(PID) controller monitors refaults over anon and file types and
+decides which type to evict when both types are available from the
+same generation.
+
+The PID controller uses generations rather than the wall clock as the
+time domain because a CPU can scan pages at different rates under
+varying memory pressure. It calculates a moving average for each new
+generation to avoid being permanently locked in a suboptimal state.
+
Memcg LRU
---------
An memcg LRU is a per-node LRU of memcgs. It is also an LRU of LRUs,
@@ -223,9 +257,9 @@ parts:

* Generations
* Rmap walks
-* Page table walks
-* Bloom filters
-* PID controller
+* Page table walks via ``mm_struct`` list
+* Bloom filters for rmap/PT walk feedback
+* PID controller for refault feedback

The aging and the eviction form a producer-consumer model;
specifically, the latter drives the former by the sliding window over
diff --git a/mm/vmscan.c b/mm/vmscan.c
index 09c064accdb1..43e69dc8b4bd 100644
--- a/mm/vmscan.c
+++ b/mm/vmscan.c
@@ -3604,7 +3604,7 @@ static bool iterate_mm_list_nowalk(struct lruvec *lruvec, unsigned long max_seq)
}

/******************************************************************************
- * refault feedback loop
+ * PID controller
******************************************************************************/

/*
--
2.39.1.581.gbfd45094c4-goog


2023-02-17 07:21:15

by Wei Xu

[permalink] [raw]
Subject: Re: [PATCH mm-unstable v1 1/2] mm: multi-gen LRU: clean up sysfs code

Reviewed-by: Wei Xu <[email protected]>

On Mon, Feb 13, 2023 at 7:54 PM T.J. Alumbaugh <[email protected]> wrote:
>
> This patch cleans up the sysfs code. Specifically,

Nit: Remove "This patch" per the "submitting patches" guide.

> 1. use sysfs_emit(),
> 2. use __ATTR_RW(), and
> 3. constify multi-gen LRU struct attribute_group.
>
> Signed-off-by: T.J. Alumbaugh <[email protected]>
> ---
> include/linux/mmzone.h | 2 +-
> mm/vmscan.c | 22 +++++++++-------------
> 2 files changed, 10 insertions(+), 14 deletions(-)
>
> diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h
> index 9fb1b03b83b2..bf8786d45b31 100644
> --- a/include/linux/mmzone.h
> +++ b/include/linux/mmzone.h
> @@ -1369,7 +1369,7 @@ typedef struct pglist_data {
>
> #ifdef CONFIG_LRU_GEN
> /* kswap mm walk data */
> - struct lru_gen_mm_walk mm_walk;
> + struct lru_gen_mm_walk mm_walk;
> /* lru_gen_folio list */
> struct lru_gen_memcg memcg_lru;
> #endif
> diff --git a/mm/vmscan.c b/mm/vmscan.c
> index d4b9fd1ae0ed..09c064accdb1 100644
> --- a/mm/vmscan.c
> +++ b/mm/vmscan.c
> @@ -5658,14 +5658,14 @@ static void lru_gen_change_state(bool enabled)
> * sysfs interface
> ******************************************************************************/
>
> -static ssize_t show_min_ttl(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
> +static ssize_t min_ttl_ms_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
> {
> - return sprintf(buf, "%u\n", jiffies_to_msecs(READ_ONCE(lru_gen_min_ttl)));
> + return sysfs_emit(buf, "%u\n", jiffies_to_msecs(READ_ONCE(lru_gen_min_ttl)));
> }
>
> /* see Documentation/admin-guide/mm/multigen_lru.rst for details */
> -static ssize_t store_min_ttl(struct kobject *kobj, struct kobj_attribute *attr,
> - const char *buf, size_t len)
> +static ssize_t min_ttl_ms_store(struct kobject *kobj, struct kobj_attribute *attr,
> + const char *buf, size_t len)
> {
> unsigned int msecs;
>
> @@ -5677,11 +5677,9 @@ static ssize_t store_min_ttl(struct kobject *kobj, struct kobj_attribute *attr,
> return len;
> }
>
> -static struct kobj_attribute lru_gen_min_ttl_attr = __ATTR(
> - min_ttl_ms, 0644, show_min_ttl, store_min_ttl
> -);
> +static struct kobj_attribute lru_gen_min_ttl_attr = __ATTR_RW(min_ttl_ms);
>
> -static ssize_t show_enabled(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
> +static ssize_t enabled_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
> {
> unsigned int caps = 0;
>
> @@ -5698,7 +5696,7 @@ static ssize_t show_enabled(struct kobject *kobj, struct kobj_attribute *attr, c
> }
>
> /* see Documentation/admin-guide/mm/multigen_lru.rst for details */
> -static ssize_t store_enabled(struct kobject *kobj, struct kobj_attribute *attr,
> +static ssize_t enabled_store(struct kobject *kobj, struct kobj_attribute *attr,
> const char *buf, size_t len)
> {
> int i;
> @@ -5725,9 +5723,7 @@ static ssize_t store_enabled(struct kobject *kobj, struct kobj_attribute *attr,
> return len;
> }
>
> -static struct kobj_attribute lru_gen_enabled_attr = __ATTR(
> - enabled, 0644, show_enabled, store_enabled
> -);
> +static struct kobj_attribute lru_gen_enabled_attr = __ATTR_RW(enabled);
>
> static struct attribute *lru_gen_attrs[] = {
> &lru_gen_min_ttl_attr.attr,
> @@ -5735,7 +5731,7 @@ static struct attribute *lru_gen_attrs[] = {
> NULL
> };
>
> -static struct attribute_group lru_gen_attr_group = {
> +static const struct attribute_group lru_gen_attr_group = {
> .name = "lru_gen",
> .attrs = lru_gen_attrs,
> };
> --
> 2.39.1.581.gbfd45094c4-goog
>
>