๏ปฟ# vmpressure ๐
๊ด๋ จ ์์ค:mm/vmpressure.c,include/linux/vmpressure.h,mm/vmscan.c,mm/memcontrol.c
๊ฐ์ (Overview)
vmpressure๋ Linux ์ปค๋์ ๋ฉ๋ชจ๋ฆฌ ์๋ ฅ ์๋ฆผ ํ๋ ์์ํฌ๋ก, vmscan ๋ฆฌํด๋ ์ด๋จธ๊ฐ ์ค์บ/ํ์ํ ํ์ด์ง ๋น์จ์ ๊ธฐ๋ฐ์ผ๋ก ์ฌ์ฉ์ ๊ณต๊ฐ์ ๋ฉ๋ชจ๋ฆฌ ์๋ ฅ ์์ค์ ํต๋ณดํฉ๋๋ค. ๋ฆฌํด๋ ์ด๋จธ๊ฐ ํ์ด์ง๋ฅผ ๋ง์ด ์ค์บํ์ง๋ง ์ ๊ฒ ํ์ํ๋ฉด ๋ฉ๋ชจ๋ฆฌ ์๋ ฅ์ด ๋๋ค๋ ๋ป์ด๋ฉฐ, ์ด ์ ๋ณด๋ฅผ eventfd๋ฅผ ํตํด ์ฌ์ฉ์ ํ๋ก์ธ์ค์ ์ ๋ฌํฉ๋๋ค. cgroup v2์์๋ ๋ชจ๋ memcg์ ๋ํด ๊ธฐ๋ณธ์ผ๋ก ํ์ฑํ๋๋ฉฐ, PSI(Pressure Stall Information)์ ํจ๊ป ๋ฉ๋ชจ๋ฆฌ ์๋ ฅ ๋ชจ๋ํฐ๋ง์ ์ด์ค ๊ฒฝ๋ก๋ฅผ ๊ตฌ์ฑํฉ๋๋ค.
์ผ์ ๋น์ : vmpressure๋ ์๋ ฅ์ฅ์ ์์ ๋ฐธ๋ธ์ ๊ฐ์ต๋๋ค. ๋ฐฅ์ฅ ์์ ์๋ ฅ(๋ฉ๋ชจ๋ฆฌ ์ฌ์ฉ๋)์ด ์ผ์ ์์ค ์ด์์ผ๋ก ๋์์ง๋ฉด ๋ฐธ๋ธ๊ฐ ์๋ํ์ฌ ์ฌ์ฉ์์๊ฒ "์๋ ฅ์ด ๋์์ง๊ณ ์๋ค"๊ณ ์๋ ค์ค๋๋ค. low๋ ์ฆ๊ธฐ๊ฐ ์ด์ง ๋๊ธฐ ์์ํ ๋, medium์ ๋ณธ๊ฒฉ์ ์ผ๋ก ๊น์ด ๋ ๋, critical์ ํฐ์ง๊ธฐ ์ง์ ์ ์ํ ์์ค์ ๋๋ค.
vmpressure๋ ์ธ ๊ฐ์ง ์๋ ฅ ์์ค(low/medium/critical)๊ณผ ์ธ ๊ฐ์ง ์๋ฆผ ๋ชจ๋(default/hierarchy/local)๋ฅผ ์ ๊ณตํฉ๋๋ค. ์ค์บ/ํ์ ๋น์จ ๊ณ์ฐ์ SWAP_CLUSTER_MAX * 16 ์๋์ฐ(๊ธฐ๋ณธ 512ํ์ด์ง โ 2MB)์์ ์ํ๋๋ฉฐ, ๋ฆฌํด๋ ์ด๋จธ์ ์ค์บ ์ฐ์ ์์(prio) ๋ณํ๋ฅผ ๊ฐ์งํ์ฌ critical ๋ ๋ฒจ์ ๋ณด์กฐ์ ์ผ๋ก ํ์งํฉ๋๋ค. ์ด ๋ฌธ์์์๋ vmpressure์ ํต์ฌ ์๋ฃ๊ตฌ์กฐ, ์๊ณ ๋ฆฌ์ฆ, ์๋ฆผ ๋ฉ์ปค๋์ฆ, memcg ํตํฉ์ ๋ถ์ํฉ๋๋ค.
์์ค ํ์ผ ๊ฒฝ๋ก
mm/vmpressure.c โ ๋ฉ์ธ ๊ตฌํ (481์ค)
include/linux/vmpressure.h โ struct vmpressure, API ์ ์ธ (52์ค)
mm/vmscan.c โ vmpressure() ํธ์ถ ์ง์ (4๊ณณ)
mm/memcontrol.c โ memcg_to_vmpressure(), ์ด๊ธฐํ/์ ๋ฆฌ
mm/memcontrol-v1.c โ cgroup v1 ์ด๋ฒคํธ ๋ฑ๋ก
๋น ๋ฅธ ์ ๊ฒ ๋ช ๋ น
# 1. vmpressure ๊ด๋ จ ์ปค๋ ์ฌ๋ณผ ํ์ธ
cat /proc/kallsyms | grep -E "vmpressure|memcg_to_vmpressure"
# 2. memcg ์ด๋ฒคํธ vmpressure ๋ฑ๋ก ์ฌ๋ถ ํ์ธ
ls /sys/fs/cgroup/memory/*.event 2>/dev/null; cat /sys/fs/cgroup/cgroup.events 2>/dev/null
# 3. vmpressure ์๊ณ๊ฐ ํ์ธ (์ปค๋ ์์)
cat /proc/kallsyms | grep -E "vmpressure_level_med|vmpressure_level_critical"
# 4. PSI ํต๊ณ์ vmpressure ๋น๊ต
cat /proc/pressure/memory
# 5. vmscan์์ vmpressure ํธ์ถ๋ถ grep
grep -rn "vmpressure\b" mm/vmscan.c
# 6. memcg vmpressure ์ด๊ธฐํ ํ์ธ
grep -rn "vmpressure_init\|vmpressure_cleanup" mm/memcontrol.c
# 7. cgroup v1 vs v2 ์ด๋ฒคํธ ๋ฉ์ปค๋์ฆ ๋น๊ต
grep -rn "vmpressure_register_event\|vmpressure_unregister_event" mm/
# 8. vmpressure ์๋์ฐ ํฌ๊ธฐ ํ์ธ (SWAP_CLUSTER_MAX * 16)
cat /proc/kallsyms | grep -E "vmpressure_win"
# 9. cgroup v2 memory ์ด๋ฒคํธ ํ์ผ ํ์ธ
ls /sys/fs/cgroup/*.events 2>/dev/null | head -5
# 10. ์ค์บ ์ฐ์ ์์ ์๊ณ๊ฐ ํ์ธ (prio โค 3 = LRU 12.5% ์ค์บ)
cat /proc/kallsyms | grep -E "vmpressure_level_critical_prio"
# 11. vmscan.c์์ proactive ํ๋๊ทธ์ ํจ๊ป vmpressure ํธ์ถ ์ฌ๋ถ ํ์ธ
grep -n "proactive.*vmpressure\|vmpressure.*proactive" mm/vmscan.c
# 12. mem_cgroup_set_socket_pressure() ํธ์ถ๋ถ ํ์ธ
grep -rn "socket_pressure" mm/memcontrol.c
ํต์ฌ ์๋ฃ๊ตฌ์กฐ
struct vmpressure
memcg๋น ํ๋์ vmpressure ๊ตฌ์กฐ์ฒด๊ฐ ์กด์ฌํฉ๋๋ค. ์ค์บ/ํ์ ์นด์ดํฐ์ ์ด๋ฒคํธ ์๋ฆผ ๋ฆฌ์คํธ๋ฅผ ๊ด๋ฆฌํฉ๋๋ค.
// include/linux/vmpressure.h:13-28
struct vmpressure {
/* ๋ ๊ฑฐ์ cgroup ๋ชจ๋ (tree=true)์ฉ ์ค์บ/ํ์ ์นด์ดํฐ */
unsigned long scanned; /* memcg ์์ฒด ์ค์บ ํ์ด์ง ์ */
unsigned long reclaimed; /* memcg ์์ฒด ํ์ ํ์ด์ง ์ */
/* ํธ๋ฆฌ ์ ์ฒด ํตํฉ ๋ชจ๋ (tree=true)์ฉ ์นด์ดํฐ */
unsigned long tree_scanned; /* ์๋ธํธ๋ฆฌ ์ ์ฒด ์ค์บ ํ์ด์ง ์ */
unsigned long tree_reclaimed; /* ์๋ธํธ๋ฆฌ ์ ์ฒด ํ์ ํ์ด์ง ์ */
spinlock_t sr_lock; /* scanned/reclaimed ๋๊ธฐํ ๋ฝ */
struct list_head events; /* vmpressure_event ์ฐ๊ฒฐ ๋ฆฌ์คํธ */
struct mutex events_lock; /* ์ด๋ฒคํธ ๋ฆฌ์คํธ ๋ณดํธ ๋ฎคํ
์ค */
struct work_struct work; /* ์ง์ฐ๋ ์ด๋ฒคํธ ์๋ฆผ ์ํฌํ ์์
*/
};
struct vmpressure_event
์ฌ์ฉ์๊ฐ eventfd๋ฅผ ํตํด ๋ฑ๋กํ ์๋ฆผ ๊ตฌ๋
์
๋๋ค. memcg์ memory.pressure_level ์ธํฐํ์ด์ค์ ์ฐ๋๋ฉ๋๋ค.
// mm/vmpressure.c:150-155
struct vmpressure_event {
struct eventfd_ctx *efd; /* ์๋ฆผ ๋์ eventfd ์ปจํ
์คํธ */
enum vmpressure_levels level; /* ํธ๋ฆฌ๊ฑฐ ์ต์ ์๋ ฅ ์์ค */
enum vmpressure_modes mode; /* ์๋ฆผ ์ ํ ๋ชจ๋ */
struct list_head node; /* vmpressure.events ์ฐ๊ฒฐ ๋
ธ๋ */
};
enum vmpressure_levels
์๋ ฅ ์์ค์ ์ค์บ/ํ์ ๋น์จ์ ๋ฐ๋ผ ์ธ ๋จ๊ณ๋ก ๋ถ๋ฅ๋ฉ๋๋ค.
// mm/vmpressure.c:85-90
enum vmpressure_levels {
VMPRESSURE_LOW = 0, /* ํ์ ํจ์จ ์ํธ (< 60%) */
VMPRESSURE_MEDIUM, /* ์ฃผ์ ์์ค (โฅ 60%) */
VMPRESSURE_CRITICAL, /* ์ํ ์์ค (โฅ 95%) */
VMPRESSURE_NUM_LEVELS,
};
enum vmpressure_modes
์๋ฆผ ๋ชจ๋๋ ์ด๋ฒคํธ์ ์ ํ ๋ฒ์๋ฅผ ๊ฒฐ์ ํฉ๋๋ค.
// mm/vmpressure.c:92-97
enum vmpressure_modes {
VMPRESSURE_NO_PASSTHROUGH = 0, /* ๊ธฐ๋ณธ: ํ์ฌ memcg๋ง ์๋ฆผ */
VMPRESSURE_HIERARCHY, /* ์์ memcg๋ก ์๋ฆผ ์ ํ */
VMPRESSURE_LOCAL, /* ๋ก์ปฌ: ์กฐ์์ ์๋ฆผ ๋ฌด์ */
VMPRESSURE_NUM_MODES,
};
์๋ ฅ ์๊ณ๊ฐ ์์
// mm/vmpressure.c:38,46-47,68
static const unsigned long vmpressure_win = SWAP_CLUSTER_MAX * 16; /* ์๋์ฐ: 512ํ์ด์ง โ 2MB */
static const unsigned int vmpressure_level_med = 60; /* medium ์๊ณ๊ฐ */
static const unsigned int vmpressure_level_critical = 95; /* critical ์๊ณ๊ฐ */
static const unsigned int vmpressure_level_critical_prio = ilog2(100 / 10); /* prio โค 3 */
ํต์ฌ ํจ์
vmpressure() โ ์ค์บ/ํ์ ๋น์จ ๊ธฐ๋ฐ ์๋ ฅ ๊ณ์ฐ (๋ฉ์ธ ์ํธ๋ฆฌ)
vmscan ๋ฆฌํด๋ ์ด๋จธ๊ฐ ๊ฐ ํ์ ์ฌ์ดํด์์ ํธ์ถํฉ๋๋ค. ๋ ๊ฐ์ง ๊ฒฝ๋ก๋ก ๋์ํฉ๋๋ค.
// mm/vmpressure.c:239-322
void vmpressure(gfp_t gfp, struct mem_cgroup *memcg, bool tree,
unsigned long scanned, unsigned long reclaimed)
{
/* memcg ๋นํ์ฑํ ์ ๋ฌด์ */
if (mem_cgroup_disabled())
return;
/* cgroup v1 legacy ๋ชจ๋์์ tree=false๋ ๋ฌด์ (์ธ_kernel ์ฌ์ฉ์ ์์) */
if (!cgroup_subsys_on_dfl(memory_cgrp_subsys) && !tree)
return;
vmpr = memcg_to_vmpressure(memcg);
/* DMA ๋ฑ ์ฌ์ฉ์ ๋์์ด ๋ถ๊ฐ๋ฅํ ์์ญ์ ์๋ ฅ์ ๋ฌด์ */
if (!(gfp & (__GFP_HIGHMEM | __GFP_MOVABLE | __GFP_IO | __GFP_FS)))
return;
/* ์ค์บ๋ ํ์ด์ง๊ฐ 0์ด๋ฉด ์์ง ์์ ์ (prio ์์น ์ ์ฌํธ์ถ๋จ) */
if (!scanned)
return;
if (tree) {
/* tree ๋ชจ๋: ์๋ธํธ๋ฆฌ ์ ์ฒด ํตํฉ โ ์ํฌํ์์ ์ง์ฐ ์๋ฆผ */
spin_lock(&vmpr->sr_lock);
scanned = vmpr->tree_scanned += scanned;
vmpr->tree_reclaimed += reclaimed;
spin_unlock(&vmpr->sr_lock);
if (scanned < vmpressure_win)
return;
schedule_work(&vmpr->work); /* ์๋์ฐ ๋๋ฌ ์ ์ํฌํ ์ค์ผ์ค */
} else {
/* non-tree ๋ชจ๋: ์ธ_kernel ์๋ฆผ (์์ผ ํ ๋น๊ธฐ ๋ฑ) */
if (!memcg || mem_cgroup_is_root(memcg))
return;
spin_lock(&vmpr->sr_lock);
scanned = vmpr->scanned += scanned;
reclaimed = vmpr->reclaimed += reclaimed;
if (scanned < vmpressure_win) {
spin_unlock(&vmpr->sr_lock);
return;
}
vmpr->scanned = vmpr->reclaimed = 0;
spin_unlock(&vmpr->sr_lock);
level = vmpressure_calc_level(scanned, reclaimed);
if (level > VMPRESSURE_LOW)
mem_cgroup_set_socket_pressure(memcg);
}
}
๋ถ๊ธฐ ๋ก์ง:
1. cgroup_subsys_on_dfl() โ cgroup v2์ด๋ฉด ๋ชจ๋ ๋ชจ๋ ํ์ฉ, v1์ด๋ฉด tree=true๋ง ํ์ฉ
2. GFP ํ๋๊ทธ ๊ฒ์ฌ โ DMA ์ ์ฉ ํ์ด์ง ํ์ ์ ์ฌ์ฉ์ ์๋ฆผ ๋ถํ์
3. tree ํ๋๊ทธ โ tree ๋ชจ๋: ์ํฌํ ์ง์ฐ ์๋ฆผ, non-tree: ์ฆ์ ์์ผ ์๋ฆผ
vmpressure_prio() โ ์ค์บ ์ฐ์ ์์ ๊ธฐ๋ฐ critical ํ์ง
๋ฆฌํด๋ ์ด๋จธ์ ์ค์บ ๊น์ด๊ฐ ๊ธฐ์ค ์ดํ๋ก ๋ด๋ ค๊ฐ๋ฉด critical์ ๊ฐ์ ํฉ๋๋ค.
// mm/vmpressure.c:335-352
void vmpressure_prio(gfp_t gfp, struct mem_cgroup *memcg, int prio)
{
/* prio > 3์ด๋ฉด ์์ง ์ถฉ๋ถํ ๊น์ด ์ค์บํ์ง ์์ โ ๋ฌด์ */
if (prio > vmpressure_level_critical_prio)
return;
/* prio โค 3์ด๋ฉด LRU์ ์ฝ 12.5% ์ค์บ โ critical ๊ฐ์ ์๋ฆผ */
vmpressure(gfp, memcg, true, vmpressure_win, 0);
}
์ฐธ๊ณ : vmpressure_level_critical_prio = ilog2(10) = 3. ๋ฆฌํด๋ ์ด๋จธ๋ lru_size >> prio ํ์ด์ง๋ฅผ ์ค์บํ๋ฏ๋ก, prio=3์ด๋ฉด LRU์ 12.5%๋ฅผ ์ค์บํ ์
์
๋๋ค.
vmpressure_calc_level() โ ์ค์บ/ํ์ ๋น์จ ๊ณ์ฐ
์๋ ฅ ํผ์ผํธ๋ฅผ ๊ณ์ฐํ๊ณ ์์ค์ ํ์ ํฉ๋๋ค.
// mm/vmpressure.c:120-148
static enum vmpressure_levels vmpressure_calc_level(unsigned long scanned,
unsigned long reclaimed)
{
unsigned long scale = scanned + reclaimed;
unsigned long pressure = 0;
/* slab ๋ฑ์์ reclaimed > scanned ๊ฐ๋ฅ โ ์ด ๊ฒฝ์ฐ pressure = 0 */
if (reclaimed >= scanned)
goto out;
/* ์๋ ฅ = (์ค์บ๋ ๊ฒ ์ค ํ์ ์คํจํ ๋น์จ) ร 100 */
pressure = scale - (reclaimed * scale / scanned);
pressure = pressure * 100 / scale;
out:
return vmpressure_level(pressure); /* 60/95 ์๊ณ๊ฐ์ผ๋ก ํ์ */
}
vmpressure_work_fn() โ ์ง์ฐ๋ ์ด๋ฒคํธ ์๋ฆผ ์ฒ๋ฆฌ
์ํฌํ์์ ์คํ๋๋ฉฐ, ์๋์ฐ ๋๋ฌ ํ ์์ memcg๊น์ง ์ ํํฉ๋๋ค.
// mm/vmpressure.c:180-216
static void vmpressure_work_fn(struct work_struct *work)
{
struct vmpressure *vmpr = work_to_vmpressure(work);
spin_lock(&vmpr->sr_lock);
scanned = vmpr->tree_scanned;
if (!scanned) {
spin_unlock(&vmpr->sr_lock);
return;
}
reclaimed = vmpr->tree_reclaimed;
vmpr->tree_scanned = 0; /* ์นด์ดํฐ ์ด๊ธฐํ */
vmpr->tree_reclaimed = 0;
spin_unlock(&vmpr->sr_lock);
level = vmpressure_calc_level(scanned, reclaimed);
/* ํ์ฌ memcg โ ๋ถ๋ชจ memcg ์์๋ก ์ด๋ฒคํธ ์ ํ */
do {
if (vmpressure_event(vmpr, level, ancestor, signalled))
signalled = true;
ancestor = true; /* ์ดํ ๋ฐ๋ณต๋ถํฐ๋ ancestor=true */
} while ((vmpr = vmpressure_parent(vmpr)));
}
vmpressure_register_event() โ eventfd ์๋ฆผ ๊ตฌ๋ ๋ฑ๋ก
cgroup์ memory.pressure_level ์ธํฐํ์ด์ค์์ ํธ์ถ๋ฉ๋๋ค.
// mm/vmpressure.c:374-422
int vmpressure_register_event(struct mem_cgroup *memcg,
struct eventfd_ctx *eventfd, const char *args)
{
/* args ํ์ฑ: "critical,hierarchy" ๊ฐ์ ์ผํ ๊ตฌ๋ถ ๋ฌธ์์ด */
token = strsep(&spec, ",");
level = match_string(vmpressure_str_levels, VMPRESSURE_NUM_LEVELS, token);
token = strsep(&spec, ",");
if (token)
mode = match_string(vmpressure_str_modes, VMPRESSURE_NUM_MODES, token);
ev = kzalloc_obj(*ev);
ev->efd = eventfd;
ev->level = level;
ev->mode = mode;
mutex_lock(&vmpr->events_lock);
list_add(&ev->node, &vmpr->events);
mutex_unlock(&vmpr->events_lock);
}
ํธ์ถ ํ๋ฆ
[์ฌ์ฉ์็ฉบ้ด] epoll_wait() / eventfd_read()
โ eventfd_signal()
[์ปค๋: ์ด๋ฒคํธ ์๋ฆผ]
vmpressure_event()
โ vmpressure_work_fn() โ schedule_work() โ vmpressure(tree=true)
โ vmpressure() non-tree โ mem_cgroup_set_socket_pressure()
[์ปค๋: ๋ฆฌํด๋ ์ด ๊ฒฝ๋ก โ MGLRU]
vmscan.c: shrink_one() (L4931)
โโ vmpressure(gfp, memcg, false, scanned, reclaimed) โ non-tree ์๋ฆผ
[์ปค๋: ๋ฆฌํด๋ ์ด ๊ฒฝ๋ก โ ๊ธฐ์กด LRU]
vmscan.c: shrink_node_memcgs() (L6027)
โโ vmpressure(gfp, memcg, false, scanned, reclaimed) โ non-tree ์๋ฆผ
vmscan.c: shrink_node() (L6069)
โโ vmpressure(gfp, memcg, true, scanned, reclaimed) โ tree ์๋ฆผ
[์ปค๋: ์ฐ์ ์์ ๋ณํ ๊ฐ์ง]
vmscan.c: do_try_to_free_pages() (L6359)
โโ vmpressure_prio(gfp, memcg, prio)
โโ vmpressure(gfp, memcg, true, vmpressure_win, 0)
[์ด๊ธฐํ/์ ๋ฆฌ]
memcontrol.c: mem_cgroup_css_alloc() (L3792)
โโ vmpressure_init(&memcg->vmpressure)
โโ INIT_WORK(&vmpr->work, vmpressure_work_fn)
memcontrol.c: mem_cgroup_css_free() (L3967)
โโ vmpressure_cleanup(&memcg->vmpressure)
โโ flush_work(&vmpr->work)
์กฐ๊ฑด๋ณ ๋น๊ต
์๋ ฅ ์์ค ํ์ ๊ธฐ์ค
| ์์ค | ์ค์บ/ํ์ ๋น์จ | ์๋ฏธ | ์ฌ์ฉ์ ์๋ฆผ |
|---|---|---|---|
| `LOW` | < 60% ํ์ ์คํจ | ๋ฆฌํด๋ ์ด๋จธ๊ฐ ์ถฉ๋ถํ ํ์ ์ค | ์๋ฆผ ์์ |
| `MEDIUM` | 60%~95% ํ์ ์คํจ | ๋ฉ๋ชจ๋ฆฌ ํ๋ณด ์ด๋ ค์ ์์ | eventfd ์ ํธ |
| `CRITICAL` | โฅ 95% ํ์ ์คํจ ๋๋ prio โค 3 | ๋ฉ๋ชจ๋ฆฌ ๋ถ์กฑ ์๋ฐ | eventfd ์ ํธ |
์๋ฆผ ๋ชจ๋ ๋น๊ต
| ๋ชจ๋ | ํ์ฌ memcg | ๋ถ๋ชจ memcg | ์ฉ๋ |
|---|---|---|---|
| `default` (NO_PASSTHROUGH) | ์๋ฆผ | ์๋ฆผ (signalled=false์ผ ๋๋ง) | ์ผ๋ฐ ์ฌ์ฉ์ ์ฑ |
| `hierarchy` | ์๋ฆผ | ์๋ฆผ (์กฐ์๋) | ๊ณ์ธต์ ๋ชจ๋ํฐ๋ง |
| `local` | ์๋ฆผ | ๋ฌด์ | ํน์ memcg๋ง ์ถ์ |
tree ๋ชจ๋ vs non-tree ๋ชจ๋
| ํญ๋ชฉ | tree=true | tree=false |
|---|---|---|
| ๋์ | cgroup subtree ์ ์ฒด | ๋จ์ผ memcg |
| ์นด์ดํฐ | `tree_scanned/reclaimed` | `scanned/reclaimed` |
| ์๋ฆผ ๋ฐฉ์ | ์ํฌํ ์ง์ฐ (์๋์ฐ ๋๋ฌ ํ) | ์ฆ์ ๊ณ์ฐ |
| ์ฌ์ฉ์ ์๋ฆผ | eventfd ์๊ทธ๋ | `mem_cgroup_set_socket_pressure()` |
| cgroup ๋ฒ์ | v1, v2 ๋ชจ๋ | v2๋ง |
| ํธ์ถ ์ง์ | `shrink_node()` (tree ๊ฒฝ๋ก) | `shrink_one()`, `shrink_node_memcgs()` (๋น-ํธ๋ฆฌ ๊ฒฝ๋ก) |
vmscan ํธ์ถ ์ง์
| ํ์ผ:๋ผ์ธ | ํธ์ถ ํจ์ | ๋ชจ๋ | ํธ์ถ ์ปจํ ์คํธ |
|---|---|---|---|
| `vmscan.c:4931` | `vmpressure()` | `false` (non-tree) | `shrink_one()` โ MGLRU ๊ฒฝ๋ก |
| `vmscan.c:6027` | `vmpressure()` | `false` (non-tree) | `shrink_node_memcgs()` โ ๊ธฐ์กด LRU ๊ฒฝ๋ก |
| `vmscan.c:6069` | `vmpressure()` | `true` (tree) | `shrink_node()` โ ์๋ธํธ๋ฆฌ ์ ์ฒด |
| `vmscan.c:6359` | `vmpressure_prio()` | `true` | `do_try_to_free_pages()` โ ์ฐ์ ์์ ๋ณํ |
cgroup v1 vs v2 ๋์ ๋น๊ต
| ํญ๋ชฉ | cgroup v1 | cgroup v2 |
|---|---|---|
| tree=true ํธ์ถ | ํ์ฉ | ํ์ฉ |
| tree=false ํธ์ถ | ๋ฌด์ (`!cgroup_subsys_on_dfl()` ์ฒดํฌ) | ํ์ฉ |
| ์ด๋ฒคํธ ๋ฑ๋ก | `memory.pressure_level` (๋ณ๋) | `memory.pressure_level` (๊ธฐ๋ณธ) |
| in-kernel ์ฌ์ฉ์ | ์์ | ์์ผ ํ ๋น๊ธฐ ๋ฑ |
| memcg ๋ฃจํธ | `mem_cgroup_is_root()` โ non-tree ๋ฌด์ | ๋์ผ |
PSI(Pressure Stall Information)์์ ๊ด๊ณ
Linux 4.20์์ ๋์ ๋ PSI๋ ์๊ฐ ๊ธฐ๋ฐ์ ๋ฉ๋ชจ๋ฆฌ ์๋ ฅ ์ธก์ ๋ฐ๋ฉด, vmpressure๋ ์ค์บ/ํ์ ๋น์จ ๊ธฐ๋ฐ์ ๋๋ค. ๋ ์์คํ ์ ์๋ก ๋ณด์์ ์ผ๋ก ๋์ํฉ๋๋ค:
memcg v2์์๋ PSI์ vmpressure๊ฐ ๋ชจ๋ ํ์ฑํ๋๋ฉฐ, memory.pressure_level (vmpressure)๊ณผ /proc/pressure/memory (PSI)๊ฐ ๊ฐ๊ฐ ๋ค๋ฅธ ๊ด์ ์์ ๋ฉ๋ชจ๋ฆฌ ์๋ ฅ์ ์ ๊ณตํฉ๋๋ค.
| ํญ๋ชฉ | vmpressure | PSI |
|---|---|---|
| ์ธก์ ๋จ์ | ํ์ ์คํจ ๋น์จ (%) | ๋๊ธฐ ์๊ฐ (ฮผs) |
| ํธ๋ฆฌ๊ฑฐ | ๋ฆฌํด๋ ์ด๋จธ ์ค์บ/ํ์ | ํ๋ก์ธ์ค ๋๊ธฐ |
| ์๋ฆผ ๋ฐฉ์ | eventfd | ํ์ผ ์ฝ๊ธฐ (`/proc/pressure/memory`) |
| ๋์ ์ปค๋ | 3.11 | 4.20 |