Skip to content

Commit 4376807

Browse files
Yu Zhaoakpm00
authored andcommitted
mm/mglru: reclaim offlined memcgs harder
In the effort to reduce zombie memcgs [1], it was discovered that the memcg LRU doesn't apply enough pressure on offlined memcgs. Specifically, instead of rotating them to the tail of the current generation (MEMCG_LRU_TAIL) for a second attempt, it moves them to the next generation (MEMCG_LRU_YOUNG) after the first attempt. Not applying enough pressure on offlined memcgs can cause them to build up, and this can be particularly harmful to memory-constrained systems. On Pixel 8 Pro, launching apps for 50 cycles: Before After Change Zombie memcgs 45 35 -22% [1] https://lore.kernel.org/CABdmKX2M6koq4Q0Cmp_-=wbP0Qa190HdEGGaHfxNS05gAkUtPA@mail.gmail.com/ Link: https://lkml.kernel.org/r/[email protected] Fixes: e4dde56 ("mm: multi-gen LRU: per-node lru_gen_folio lists") Signed-off-by: Yu Zhao <[email protected]> Reported-by: T.J. Mercier <[email protected]> Tested-by: T.J. Mercier <[email protected]> Cc: Charan Teja Kalla <[email protected]> Cc: Hillf Danton <[email protected]> Cc: Jaroslav Pulchart <[email protected]> Cc: Kairui Song <[email protected]> Cc: Kalesh Singh <[email protected]> Cc: <[email protected]> Signed-off-by: Andrew Morton <[email protected]>
1 parent 8aa4206 commit 4376807

File tree

2 files changed

+20
-12
lines changed

2 files changed

+20
-12
lines changed

include/linux/mmzone.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -519,10 +519,10 @@ void lru_gen_look_around(struct page_vma_mapped_walk *pvmw);
519519
* 1. Exceeding the soft limit, which triggers MEMCG_LRU_HEAD;
520520
* 2. The first attempt to reclaim a memcg below low, which triggers
521521
* MEMCG_LRU_TAIL;
522-
* 3. The first attempt to reclaim a memcg below reclaimable size threshold,
523-
* which triggers MEMCG_LRU_TAIL;
524-
* 4. The second attempt to reclaim a memcg below reclaimable size threshold,
525-
* which triggers MEMCG_LRU_YOUNG;
522+
* 3. The first attempt to reclaim a memcg offlined or below reclaimable size
523+
* threshold, which triggers MEMCG_LRU_TAIL;
524+
* 4. The second attempt to reclaim a memcg offlined or below reclaimable size
525+
* threshold, which triggers MEMCG_LRU_YOUNG;
526526
* 5. Attempting to reclaim a memcg below min, which triggers MEMCG_LRU_YOUNG;
527527
* 6. Finishing the aging on the eviction path, which triggers MEMCG_LRU_YOUNG;
528528
* 7. Offlining a memcg, which triggers MEMCG_LRU_OLD.

mm/vmscan.c

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4598,7 +4598,12 @@ static bool should_run_aging(struct lruvec *lruvec, unsigned long max_seq,
45984598
}
45994599

46004600
/* try to scrape all its memory if this memcg was deleted */
4601-
*nr_to_scan = mem_cgroup_online(memcg) ? (total >> sc->priority) : total;
4601+
if (!mem_cgroup_online(memcg)) {
4602+
*nr_to_scan = total;
4603+
return false;
4604+
}
4605+
4606+
*nr_to_scan = total >> sc->priority;
46024607

46034608
/*
46044609
* The aging tries to be lazy to reduce the overhead, while the eviction
@@ -4719,22 +4724,17 @@ static int shrink_one(struct lruvec *lruvec, struct scan_control *sc)
47194724
bool success;
47204725
unsigned long scanned = sc->nr_scanned;
47214726
unsigned long reclaimed = sc->nr_reclaimed;
4722-
int seg = lru_gen_memcg_seg(lruvec);
47234727
struct mem_cgroup *memcg = lruvec_memcg(lruvec);
47244728
struct pglist_data *pgdat = lruvec_pgdat(lruvec);
47254729

4726-
/* see the comment on MEMCG_NR_GENS */
4727-
if (!lruvec_is_sizable(lruvec, sc))
4728-
return seg != MEMCG_LRU_TAIL ? MEMCG_LRU_TAIL : MEMCG_LRU_YOUNG;
4729-
47304730
mem_cgroup_calculate_protection(NULL, memcg);
47314731

47324732
if (mem_cgroup_below_min(NULL, memcg))
47334733
return MEMCG_LRU_YOUNG;
47344734

47354735
if (mem_cgroup_below_low(NULL, memcg)) {
47364736
/* see the comment on MEMCG_NR_GENS */
4737-
if (seg != MEMCG_LRU_TAIL)
4737+
if (lru_gen_memcg_seg(lruvec) != MEMCG_LRU_TAIL)
47384738
return MEMCG_LRU_TAIL;
47394739

47404740
memcg_memory_event(memcg, MEMCG_LOW);
@@ -4750,7 +4750,15 @@ static int shrink_one(struct lruvec *lruvec, struct scan_control *sc)
47504750

47514751
flush_reclaim_state(sc);
47524752

4753-
return success ? MEMCG_LRU_YOUNG : 0;
4753+
if (success && mem_cgroup_online(memcg))
4754+
return MEMCG_LRU_YOUNG;
4755+
4756+
if (!success && lruvec_is_sizable(lruvec, sc))
4757+
return 0;
4758+
4759+
/* one retry if offlined or too small */
4760+
return lru_gen_memcg_seg(lruvec) != MEMCG_LRU_TAIL ?
4761+
MEMCG_LRU_TAIL : MEMCG_LRU_YOUNG;
47544762
}
47554763

47564764
#ifdef CONFIG_MEMCG

0 commit comments

Comments
 (0)