lkml.org 
[lkml]   [2020]   [Jun]   [17]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH v6 3/6] mm/workingset: extend the workingset detection for anon LRU
    Date
    From: Joonsoo Kim <iamjoonsoo.kim@lge.com>

    In the following patch, workingset detection will be applied to
    anonymous LRU. To prepare it, this patch adds some code to
    distinguish/handle the both LRUs.

    v6: do not introduce a new nonresident_age for anon LRU since
    we need to use *unified* nonresident_age to implement workingset
    detection for anon LRU.

    Acked-by: Johannes Weiner <hannes@cmpxchg.org>
    Signed-off-by: Joonsoo Kim <iamjoonsoo.kim@lge.com>
    ---
    include/linux/mmzone.h | 16 +++++++++++-----
    mm/memcontrol.c | 16 +++++++++++-----
    mm/vmscan.c | 15 ++++++++++-----
    mm/vmstat.c | 9 ++++++---
    mm/workingset.c | 8 +++++---
    5 files changed, 43 insertions(+), 21 deletions(-)

    diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h
    index f6f8849..8e9d0b9 100644
    --- a/include/linux/mmzone.h
    +++ b/include/linux/mmzone.h
    @@ -179,9 +179,15 @@ enum node_stat_item {
    NR_ISOLATED_ANON, /* Temporary isolated pages from anon lru */
    NR_ISOLATED_FILE, /* Temporary isolated pages from file lru */
    WORKINGSET_NODES,
    - WORKINGSET_REFAULT,
    - WORKINGSET_ACTIVATE,
    - WORKINGSET_RESTORE,
    + WORKINGSET_REFAULT_BASE,
    + WORKINGSET_REFAULT_ANON = WORKINGSET_REFAULT_BASE,
    + WORKINGSET_REFAULT_FILE,
    + WORKINGSET_ACTIVATE_BASE,
    + WORKINGSET_ACTIVATE_ANON = WORKINGSET_ACTIVATE_BASE,
    + WORKINGSET_ACTIVATE_FILE,
    + WORKINGSET_RESTORE_BASE,
    + WORKINGSET_RESTORE_ANON = WORKINGSET_RESTORE_BASE,
    + WORKINGSET_RESTORE_FILE,
    WORKINGSET_NODERECLAIM,
    NR_ANON_MAPPED, /* Mapped anonymous pages */
    NR_FILE_MAPPED, /* pagecache pages mapped into pagetables.
    @@ -259,8 +265,8 @@ struct lruvec {
    unsigned long file_cost;
    /* Non-resident age, driven by LRU movement */
    atomic_long_t nonresident_age;
    - /* Refaults at the time of last reclaim cycle */
    - unsigned long refaults;
    + /* Refaults at the time of last reclaim cycle, anon=0, file=1 */
    + unsigned long refaults[2];
    /* Various lruvec state flags (enum lruvec_flags) */
    unsigned long flags;
    #ifdef CONFIG_MEMCG
    diff --git a/mm/memcontrol.c b/mm/memcontrol.c
    index 0b38b6a..2127dd1 100644
    --- a/mm/memcontrol.c
    +++ b/mm/memcontrol.c
    @@ -1425,12 +1425,18 @@ static char *memory_stat_format(struct mem_cgroup *memcg)
    seq_buf_printf(&s, "%s %lu\n", vm_event_name(PGMAJFAULT),
    memcg_events(memcg, PGMAJFAULT));

    - seq_buf_printf(&s, "workingset_refault %lu\n",
    - memcg_page_state(memcg, WORKINGSET_REFAULT));
    - seq_buf_printf(&s, "workingset_activate %lu\n",
    - memcg_page_state(memcg, WORKINGSET_ACTIVATE));
    + seq_buf_printf(&s, "workingset_refault_anon %lu\n",
    + memcg_page_state(memcg, WORKINGSET_REFAULT_ANON));
    + seq_buf_printf(&s, "workingset_refault_file %lu\n",
    + memcg_page_state(memcg, WORKINGSET_REFAULT_FILE));
    + seq_buf_printf(&s, "workingset_activate_anon %lu\n",
    + memcg_page_state(memcg, WORKINGSET_ACTIVATE_ANON));
    + seq_buf_printf(&s, "workingset_activate_file %lu\n",
    + memcg_page_state(memcg, WORKINGSET_ACTIVATE_FILE));
    seq_buf_printf(&s, "workingset_restore %lu\n",
    - memcg_page_state(memcg, WORKINGSET_RESTORE));
    + memcg_page_state(memcg, WORKINGSET_RESTORE_ANON));
    + seq_buf_printf(&s, "workingset_restore %lu\n",
    + memcg_page_state(memcg, WORKINGSET_RESTORE_FILE));
    seq_buf_printf(&s, "workingset_nodereclaim %lu\n",
    memcg_page_state(memcg, WORKINGSET_NODERECLAIM));

    diff --git a/mm/vmscan.c b/mm/vmscan.c
    index 4745e88..3caa35f 100644
    --- a/mm/vmscan.c
    +++ b/mm/vmscan.c
    @@ -2695,7 +2695,10 @@ static void shrink_node(pg_data_t *pgdat, struct scan_control *sc)
    if (!sc->force_deactivate) {
    unsigned long refaults;

    - if (inactive_is_low(target_lruvec, LRU_INACTIVE_ANON))
    + refaults = lruvec_page_state(target_lruvec,
    + WORKINGSET_ACTIVATE_ANON);
    + if (refaults != target_lruvec->refaults[0] ||
    + inactive_is_low(target_lruvec, LRU_INACTIVE_ANON))
    sc->may_deactivate |= DEACTIVATE_ANON;
    else
    sc->may_deactivate &= ~DEACTIVATE_ANON;
    @@ -2706,8 +2709,8 @@ static void shrink_node(pg_data_t *pgdat, struct scan_control *sc)
    * rid of any stale active pages quickly.
    */
    refaults = lruvec_page_state(target_lruvec,
    - WORKINGSET_ACTIVATE);
    - if (refaults != target_lruvec->refaults ||
    + WORKINGSET_ACTIVATE_FILE);
    + if (refaults != target_lruvec->refaults[1] ||
    inactive_is_low(target_lruvec, LRU_INACTIVE_FILE))
    sc->may_deactivate |= DEACTIVATE_FILE;
    else
    @@ -2984,8 +2987,10 @@ static void snapshot_refaults(struct mem_cgroup *target_memcg, pg_data_t *pgdat)
    unsigned long refaults;

    target_lruvec = mem_cgroup_lruvec(target_memcg, pgdat);
    - refaults = lruvec_page_state(target_lruvec, WORKINGSET_ACTIVATE);
    - target_lruvec->refaults = refaults;
    + refaults = lruvec_page_state(target_lruvec, WORKINGSET_ACTIVATE_ANON);
    + target_lruvec->refaults[0] = refaults;
    + refaults = lruvec_page_state(target_lruvec, WORKINGSET_ACTIVATE_FILE);
    + target_lruvec->refaults[1] = refaults;
    }

    /*
    diff --git a/mm/vmstat.c b/mm/vmstat.c
    index 80c9b62..8843e75 100644
    --- a/mm/vmstat.c
    +++ b/mm/vmstat.c
    @@ -1149,9 +1149,12 @@ const char * const vmstat_text[] = {
    "nr_isolated_anon",
    "nr_isolated_file",
    "workingset_nodes",
    - "workingset_refault",
    - "workingset_activate",
    - "workingset_restore",
    + "workingset_refault_anon",
    + "workingset_refault_file",
    + "workingset_activate_anon",
    + "workingset_activate_file",
    + "workingset_restore_anon",
    + "workingset_restore_file",
    "workingset_nodereclaim",
    "nr_anon_pages",
    "nr_mapped",
    diff --git a/mm/workingset.c b/mm/workingset.c
    index fc16d97c..8395e60 100644
    --- a/mm/workingset.c
    +++ b/mm/workingset.c
    @@ -6,6 +6,7 @@
    */

    #include <linux/memcontrol.h>
    +#include <linux/mm_inline.h>
    #include <linux/writeback.h>
    #include <linux/shmem_fs.h>
    #include <linux/pagemap.h>
    @@ -280,6 +281,7 @@ void *workingset_eviction(struct page *page, struct mem_cgroup *target_memcg)
    */
    void workingset_refault(struct page *page, void *shadow)
    {
    + bool file = page_is_file_lru(page);
    struct mem_cgroup *eviction_memcg;
    struct lruvec *eviction_lruvec;
    unsigned long refault_distance;
    @@ -346,7 +348,7 @@ void workingset_refault(struct page *page, void *shadow)
    memcg = page_memcg(page);
    lruvec = mem_cgroup_lruvec(memcg, pgdat);

    - inc_lruvec_state(lruvec, WORKINGSET_REFAULT);
    + inc_lruvec_state(lruvec, WORKINGSET_REFAULT_BASE + file);

    /*
    * Compare the distance to the existing workingset size. We
    @@ -364,7 +366,7 @@ void workingset_refault(struct page *page, void *shadow)

    SetPageActive(page);
    workingset_age_nonresident(lruvec, hpage_nr_pages(page));
    - inc_lruvec_state(lruvec, WORKINGSET_ACTIVATE);
    + inc_lruvec_state(lruvec, WORKINGSET_ACTIVATE_BASE + file);

    /* Page was active prior to eviction */
    if (workingset) {
    @@ -373,7 +375,7 @@ void workingset_refault(struct page *page, void *shadow)
    spin_lock_irq(&page_pgdat(page)->lru_lock);
    lru_note_cost_page(page);
    spin_unlock_irq(&page_pgdat(page)->lru_lock);
    - inc_lruvec_state(lruvec, WORKINGSET_RESTORE);
    + inc_lruvec_state(lruvec, WORKINGSET_RESTORE_BASE + file);
    }
    out:
    rcu_read_unlock();
    --
    2.7.4
    \
     
     \ /
      Last update: 2020-06-17 07:27    [W:3.082 / U:0.032 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site