19. KSM (Kernel Same-page Merging)

๊ฐœ์š” (Overview)

KSM(Kernel Same-page Merging)์€ ์ปค๋„์ด ์‹คํ–‰ ์ค‘์ธ ํ”„๋กœ์„ธ์Šค๋“ค์˜ ๋™์ผํ•œ ๋‚ด์šฉ์˜ ์ต๋ช… ํŽ˜์ด์ง€๋ฅผ ํƒ์ง€ํ•˜์—ฌ ํ•˜๋‚˜์˜ ๋ฌผ๋ฆฌ ํŽ˜์ด์ง€๋กœ ๋ณ‘ํ•ฉ(merging)ํ•˜๋Š” ๋ฉ”๋ชจ๋ฆฌ ์ค‘๋ณต ์ œ๊ฑฐ ๋ฉ”์ปค๋‹ˆ์ฆ˜์ž…๋‹ˆ๋‹ค. ๊ฐ€์ƒํ™” ํ™˜๊ฒฝ(KVM/QEMU)์—์„œ ์—ฌ๋Ÿฌ ๊ฐ€์ƒ ๋จธ์‹ ์ด ๋™์ผํ•œ ์ปค๋„์ด๋‚˜ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์‹คํ–‰ํ•  ๋•Œ, ๋˜๋Š” ๊ฐ™์€ ํ”„๋กœ์„ธ์Šค๋ฅผ fork()ํ•œ ํ›„ COW๋กœ ๋ถ„๋ฆฌ๋˜์ง€ ์•Š์€ ํŽ˜์ด์ง€๋ฅผ ๋‹ค์‹œ ๋ณ‘ํ•ฉํ•  ๋•Œ ๋ฉ”๋ชจ๋ฆฌ ์‚ฌ์šฉ๋Ÿ‰์„ ํฌ๊ฒŒ ์ ˆ๊ฐํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

KSM์€ ๋ฐฑ๊ทธ๋ผ์šด๋“œ ์ปค๋„ ์Šค๋ ˆ๋“œ์ธ ksmd๊ฐ€ ์ฃผ๊ธฐ์ ์œผ๋กœ ๋ชจ๋“  VM_MERGEABLE ํ”Œ๋ž˜๊ทธ๊ฐ€ ์„ค์ •๋œ VMA๋ฅผ ์Šค์บ”ํ•˜๊ณ , ํŽ˜์ด์ง€ ๋‚ด์šฉ์„ ๋น„๊ตํ•˜์—ฌ stable tree(์“ฐ๊ธฐ ๋ณดํ˜ธ๋œ KSM ํŽ˜์ด์ง€)์™€ unstable tree(์ผ์‹œ์ ์œผ๋กœ ๋ณด๊ด€๋˜๋Š” ํ›„๋ณด ํŽ˜์ด์ง€)์— ์ •๋ ฌํ•ฉ๋‹ˆ๋‹ค. ๋™์ผํ•œ ํŽ˜์ด์ง€๋ฅผ ์ฐพ์œผ๋ฉด write-protect ํ›„ PTE๋ฅผ ๊ต์ฒดํ•˜์—ฌ ๋ฌผ๋ฆฌ ํŽ˜์ด์ง€๋ฅผ ๊ณต์œ ํ•ฉ๋‹ˆ๋‹ค.

์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์€ madvise(..., MADV_MERGEABLE)๋กœ ๋ณ‘ํ•ฉ ํ›„๋ณด๋ฅผ ๋ช…์‹œํ•˜๊ณ , MADV_UNMERGEABLE๋กœ ์ œ์™ธํ•ฉ๋‹ˆ๋‹ค. ์šด์˜์ž๋Š” sysfs๋กœ ksmd์˜ ์‹คํ–‰ ์—ฌ๋ถ€์™€ ์Šค์บ” ์†๋„๋ฅผ ์กฐ์ ˆํ•ฉ๋‹ˆ๋‹ค.

๊ฐ™์€ ์‚ฌ๋ณธ ์—ฌ๋Ÿฌ ๋ถ€๋ฅผ ํ•œ ๊ถŒ์œผ๋กœ ์ •๋ฆฌํ•ด ๋‚˜๋จธ์ง€๋ฅผ ๊ณต์œ ํ•˜๋Š” ๋„์„œ๊ด€ ์‚ฌ๋ณธ ๊ด€๋ฆฌ์™€ ๋น„์Šทํ•ฉ๋‹ˆ๋‹ค. ์Šค์บ”๊ณผ ๋น„๊ต ๋น„์šฉ์ด ์žˆ์œผ๋ฏ€๋กœ CPU ์˜ค๋ฒ„ํ—ค๋“œ๊ฐ€ ์ƒ๊ธฐ๋ฉฐ, ํ•„์š”ํ•œ VMA๋งŒ ๊ณจ๋ผ ์ผœ๋Š” ๊ฒƒ์ด ์ค‘์š”ํ•ฉ๋‹ˆ๋‹ค.

์†Œ์Šค ํŒŒ์ผ ๊ฒฝ๋กœ

mm/ksm.c                    โ† KSM ํ•ต์‹ฌ ๊ตฌํ˜„ (์Šค์บ”, ๋น„๊ต, ๋ณ‘ํ•ฉ, stable/unstable tree)
mm/madvise.c                โ† MADV_MERGEABLE/MADV_UNMERGEABLE ์ฒ˜๋ฆฌ
include/linux/ksm.h         โ† KSM ์™ธ๋ถ€ API ๋ฐ ์ธ๋ผ์ธ ํ•จ์ˆ˜
mm/mm_slot.h                โ† mm_slot ํ•ด์‹œ ํ…Œ์ด๋ธ” ๊ด€๋ฆฌ
include/linux/mm.h          โ† struct mm_struct ๋‚ด ksm ๊ด€๋ จ ํ•„๋“œ

KSM ํ˜ธ์ถœ ํ๋ฆ„

๋น ๋ฅธ ์ ๊ฒ€ ๋ช…๋ น

# KSM ์Šค๋ ˆ๋“œ ์ƒํƒœ ํ™•์ธ
ps aux | grep ksmd

# KSM ๋ณ‘ํ•ฉ ํ†ต๊ณ„ (์ „์ฒด ์‹œ์Šคํ…œ)
cat /sys/kernel/mm/ksm/pages_shared     # stable tree์˜ ๊ณ ์œ  KSM ํŽ˜์ด์ง€ ์ˆ˜
cat /sys/kernel/mm/ksm/pages_sharing    # KSM ํŽ˜์ด์ง€๋ฅผ ๊ณต์œ  ์ค‘์ธ ์ถ”๊ฐ€ ๋งคํ•‘ ์ˆ˜
cat /sys/kernel/mm/ksm/pages_unshared   # unstable tree์˜ ๋ฏธ๋ณ‘ํ•ฉ ํ›„๋ณด ์ˆ˜
cat /sys/kernel/mm/ksm/pages_volatile   # rmap_item ์ค‘ ์–ด๋А ํŠธ๋ฆฌ์—๋„ ์—†๋Š” ์ˆ˜
cat /sys/kernel/mm/ksm/pages_scanned    # ์ด ์Šค์บ”๋œ ํŽ˜์ด์ง€ ์ˆ˜
cat /sys/kernel/mm/ksm/full_scans       # ์ „์ฒด ์Šค์บ” ์™„๋ฃŒ ํšŸ์ˆ˜
cat /sys/kernel/mm/ksm/pages_skipped    # smart scan์œผ๋กœ ๊ฑด๋„ˆ๋›ด ํŽ˜์ด์ง€ ์ˆ˜
cat /sys/kernel/mm/ksm/ksm_zero_pages   # zero page ๋ณ‘ํ•ฉ ์ˆ˜

# KSM ์ˆ˜์ต ๊ณ„์‚ฐ (์ ˆ์•ฝ ๋ฉ”๋ชจ๋ฆฌ - ์˜ค๋ฒ„ํ—ค๋“œ)
cat /sys/kernel/mm/ksm/general_profit

# KSM ์Šค์บ” ํŒŒ๋ผ๋ฏธํ„ฐ ํ™•์ธ/์กฐ์ •
cat /sys/kernel/mm/ksm/pages_to_scan     # ํ•œ ๋ฒˆ์— ์Šค์บ”ํ•  ํŽ˜์ด์ง€ ์ˆ˜ (๊ธฐ๋ณธ 100)
cat /sys/kernel/mm/ksm/sleep_millisecs   # ์Šค์บ” ๊ฐ„ ๋Œ€๊ธฐ ์‹œ๊ฐ„ (๊ธฐ๋ณธ 20ms)
cat /sys/kernel/mm/ksm/run               # 0:์ •์ง€, 1:๋ณ‘ํ•ฉ, 2:๋ณ‘ํ•ฉํ•ด์ œ
cat /sys/kernel/mm/ksm/merge_across_nodes  # NUMA ๋…ธ๋“œ ๊ฐ„ ๋ณ‘ํ•ฉ ํ—ˆ์šฉ ์—ฌ๋ถ€
cat /sys/kernel/mm/ksm/use_zero_pages    # zero page ๋ณ‘ํ•ฉ ํ™œ์„ฑํ™” ์—ฌ๋ถ€
cat /sys/kernel/mm/ksm/smart_scan        # ์Šค๋งˆํŠธ ์Šค์บ” ํ™œ์„ฑํ™” ์—ฌ๋ถ€
cat /sys/kernel/mm/ksm/max_page_sharing  # ํ•˜๋‚˜์˜ KSM ํŽ˜์ด์ง€ ์ตœ๋Œ€ ๊ณต์œ  ์ˆ˜ (๊ธฐ๋ณธ 256)

# KSM advisor ํ™•์ธ/์กฐ์ •
cat /sys/kernel/mm/ksm/advisor_mode                  # none / scan-time
cat /sys/kernel/mm/ksm/advisor_max_cpu               # advisor ์ตœ๋Œ€ CPU%
cat /sys/kernel/mm/ksm/advisor_target_scan_time      # ๋ชฉํ‘œ ์Šค์บ” ์‹œ๊ฐ„(์ดˆ)
echo scan-time | sudo tee /sys/kernel/mm/ksm/advisor_mode
echo none | sudo tee /sys/kernel/mm/ksm/advisor_mode

# KSM ํ™œ์„ฑํ™” (sysfs๋ฅผ ํ†ตํ•œ ์ œ์–ด)
echo 1 | sudo tee /sys/kernel/mm/ksm/run   # ksmd ์‹œ์ž‘
echo 0 | sudo tee /sys/kernel/mm/ksm/run   # ksmd ์ค‘์ง€

# ํ”„๋กœ์„ธ์Šค๋ณ„ KSM ์‚ฌ์šฉ๋Ÿ‰ ํ™•์ธ
cat /proc/<pid>/status | grep KSM
awk '/VmFlags/ && /mg/ {print}' /proc/<pid>/smaps  # mergeable VMA ํ™•์ธ

# per-mm KSM ์ •๋ณด (/proc/<pid>/ksm_stat - ํ•ด๋‹น ์ปค๋„์—์„œ ์ง€์› ์‹œ)
cat /proc/<pid>/ksm_stat 2>/dev/null

# KSM ๊ด€๋ จ ์ปค๋„ ์„ค์ • ํ™•์ธ
zgrep KSM /proc/config.gz 2>/dev/null || grep KSM /boot/config-$(uname -r)

ํ•ต์‹ฌ ์ž๋ฃŒ๊ตฌ์กฐ

KSM ์ž๋ฃŒ๊ตฌ์กฐ ๊ด€๊ณ„๋„

struct ksm_stable_node

stable tree์˜ ๋…ธ๋“œ๋กœ, write-protect๋œ KSM ํŽ˜์ด์ง€๋ฅผ ๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค. ๋™์ผํ•œ ๋‚ด์šฉ์˜ ์—ฌ๋Ÿฌ ๋งคํ•‘์ด ์žˆ์„ ๋•Œ chain/dup ๊ตฌ์กฐ๋กœ ๊ด€๋ฆฌ๋ฉ๋‹ˆ๋‹ค.

// mm/ksm.c:159-185
struct ksm_stable_node {
union {
struct rb_node node;    /* stable tree ๋‚ด rb-tree ๋…ธ๋“œ */
struct {                /* migration list์— ์žˆ์„ ๋•Œ */
struct list_head *head;
struct {
struct hlist_node hlist_dup;  /* chain ๋‚ด dup ์—ฐ๊ฒฐ */
struct list_head list;         /* migrate_nodes ์—ฐ๊ฒฐ */
};
};
};
struct hlist_head hlist;    /* ์ด stable node๋ฅผ ์‚ฌ์šฉํ•˜๋Š” rmap_item ๋ชฉ๋ก */
union {
unsigned long kpfn;     /* KSM ํŽ˜์ด์ง€์˜ ๋ฌผ๋ฆฌ ํ”„๋ ˆ์ž„ ๋ฒˆํ˜ธ */
unsigned long chain_prune_time;  /* chain pruning ๋งˆ์ง€๋ง‰ ์‹œ๊ฐ„ */
};
#define STABLE_NODE_CHAIN -1024  /* chain ๋…ธ๋“œ ํŒ๋ณ„ ๋งˆ์ปค */
int rmap_hlist_len;         /* hlist์˜ rmap_item ์ˆ˜ ๋˜๋Š” STABLE_NODE_CHAIN */
#ifdef CONFIG_NUMA
int nid;                    /* NUMA ๋…ธ๋“œ ID */
#endif
};

struct ksm_rmap_item

๊ฐ€์ƒ ์ฃผ์†Œโ†’๋ฌผ๋ฆฌ ํŽ˜์ด์ง€์˜ ์—ญ๋ฐฉํ–ฅ ๋งคํ•‘(rmap) ํ•ญ๋ชฉ์ž…๋‹ˆ๋‹ค. unstable tree์˜ rb-tree ๋…ธ๋“œ์ด๊ฑฐ๋‚˜ stable tree์˜ hlist ์š”์†Œ๋กœ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค.

// mm/ksm.c:201-221
struct ksm_rmap_item {
struct ksm_rmap_item *rmap_list;  /* mm_slot์˜ ๋‹จ์ผ ์—ฐ๊ฒฐ ๋ฆฌ์ŠคํŠธ */
union {
struct anon_vma *anon_vma;    /* stable tree์— ์žˆ์„ ๋•Œ anon_vma */
#ifdef CONFIG_NUMA
int nid;                      /* unstable tree์— ์žˆ์„ ๋•Œ NUMA node */
#endif
};
struct mm_struct *mm;             /* ์ด rmap_item์ด ์†ํ•œ mm */
unsigned long address;            /* ๊ฐ€์ƒ ์ฃผ์†Œ + ํ”Œ๋ž˜๊ทธ ๋น„ํŠธ */
unsigned int oldchecksum;         /* unstable tree์—์„œ ์ด์ „ ์ฒดํฌ์„ฌ */
rmap_age_t age;                   /* ์Šค์บ” ๋ฐ˜๋ณต ํšŸ์ˆ˜ (์Šค๋งˆํŠธ ์Šค์บ”์šฉ) */
rmap_age_t remaining_skips;       /* ๋‚จ์€ ๊ฑด๋„ˆ๋œ€ ํšŸ์ˆ˜ */
union {
struct rb_node node;          /* unstable tree ๋‚ด rb-tree ๋…ธ๋“œ */
struct {                      /* stable tree์—์„œ ์‚ฌ์šฉ ์‹œ */
struct ksm_stable_node *head;
struct hlist_node hlist;
};
};
};

// ์ฃผ์†Œ ํ•˜์œ„ ๋น„ํŠธ ํ”Œ๋ž˜๊ทธ (mm/ksm.c:223-225)
#define SEQNR_MASK  0x0ff   /* ๋ถˆ์•ˆ์ • ํŠธ๋ฆฌ seqnr */
#define UNSTABLE_FLAG 0x100 /* unstable tree ๋…ธ๋“œ */
#define STABLE_FLAG   0x200 /* stable tree์˜ rmap_item */

struct ksm_mm_slot

์Šค์บ” ์ปค์„œ๊ฐ€ ํ˜„์žฌ ์œ„์น˜ํ•œ mm ์ •๋ณด๋ฅผ ๋‹ด์Šต๋‹ˆ๋‹ค. ํ•ด์‹œ ํ…Œ์ด๋ธ”๋กœ mmโ†’mm_slot ๋น ๋ฅธ ์กฐํšŒ๋ฅผ ์ง€์›ํ•ฉ๋‹ˆ๋‹ค.

// mm/ksm.c:126-129
struct ksm_mm_slot {
struct mm_slot slot;               /* ํ•ด์‹œ + ์—ฐ๊ฒฐ ๋ฆฌ์ŠคํŠธ ๊ด€๋ฆฌ */
struct ksm_rmap_item *rmap_list;   /* ์ด mm์˜ rmap_item ๋ชฉ๋ก ๋จธ๋ฆฌ */
};

// mm/mm_slot.h:15-19
struct mm_slot {
struct hlist_node hash;     /* ํ•ด์‹œ ํ…Œ์ด๋ธ” ์—ฐ๊ฒฐ */
struct list_head mm_node;   /* mm ๋ชฉ๋ก ์—ฐ๊ฒฐ */
struct mm_struct *mm;       /* ๋Œ€์ƒ mm_struct */
};

struct ksm_scan (์Šค์บ” ์ปค์„œ)

์ „์—ญ ์Šค์บ” ์ปค์„œ๋กœ, ํ˜„์žฌ ์–ด๋–ค mm, ์–ด๋–ค ์ฃผ์†Œ, ์–ด๋–ค rmap_list๋ฅผ ์Šค์บ” ์ค‘์ธ์ง€ ์ถ”์ ํ•ฉ๋‹ˆ๋‹ค.

// mm/ksm.c:140-145
struct ksm_scan {
struct ksm_mm_slot *mm_slot;   /* ํ˜„์žฌ ์Šค์บ” ์ค‘์ธ mm_slot */
unsigned long address;          /* ๋‹ค์Œ ์Šค์บ”ํ•  ๊ฐ€์ƒ ์ฃผ์†Œ */
struct ksm_rmap_item **rmap_list; /* ๋‹ค์Œ rmap_item์„ ๊ฐ€๋ฆฌํ‚ค๋Š” ํฌ์ธํ„ฐ */
unsigned long seqnr;            /* ์™„๋ฃŒ๋œ ์ „์ฒด ์Šค์บ” ํšŸ์ˆ˜ */
};

struct advisor_ctx (KSM Advisor)

scan-time advisor๊ฐ€ ์Šค์บ” ์†๋„๋ฅผ ์ ์‘ํ˜•์œผ๋กœ ์กฐ์ ˆํ•˜๊ธฐ ์œ„ํ•œ ์ปจํ…์ŠคํŠธ์ž…๋‹ˆ๋‹ค.

// mm/ksm.c:325-331
struct advisor_ctx {
ktime_t start_scan;         /* ํ˜„์žฌ ์Šค์บ” ์‹œ์ž‘ ์‹œ๊ฐ„ */
unsigned long scan_time;    /* ์ด์ „ ์Šค์บ” ์†Œ์š” ์‹œ๊ฐ„ */
unsigned long change;       /* pages_to_scan ๋ณ€๊ฒฝ ๋น„์œจ (EWMA) */
unsigned long long cpu_time; /* ์ด์ „ ์Šค์บ”์˜ ksmd CPU ์‚ฌ์šฉ ์‹œ๊ฐ„ */
};

์ „์—ญ ํŠธ๋ฆฌ ๋ฐ ์ฃผ์š” ๋ณ€์ˆ˜

// mm/ksm.c:228-248 โ€” stable/unstable tree ๋ฃจํŠธ
static struct rb_root one_stable_tree[1] = { RB_ROOT };
static struct rb_root one_unstable_tree[1] = { RB_ROOT };
static struct rb_root *root_stable_tree = one_stable_tree;
static struct rb_root *root_unstable_tree = one_unstable_tree;

// mm/ksm.c:252-301 โ€” ์ฃผ์š” ํ†ต๊ณ„ ๋ณ€์ˆ˜
static unsigned long ksm_pages_scanned;     // ์Šค์บ”๋œ ํŽ˜์ด์ง€ ์ˆ˜
static unsigned long ksm_pages_shared;      // stable tree ๊ณ ์œ  KSM ํŽ˜์ด์ง€ ์ˆ˜
static unsigned long ksm_pages_sharing;     // KSM ํŽ˜์ด์ง€ ๊ณต์œ  ๋งคํ•‘ ์ˆ˜
static unsigned long ksm_pages_unshared;    // unstable tree ๋ฏธ๋ณ‘ํ•ฉ ์ˆ˜
static unsigned long ksm_rmap_items;        // ์‚ฌ์šฉ ์ค‘ rmap_item ์ˆ˜
static unsigned long ksm_pages_skipped;     // smart scan์œผ๋กœ ๊ฑด๋„ˆ๋›ด ์ˆ˜

ํ•ต์‹ฌ ํ•จ์ˆ˜

1. ksm_scan_thread() โ€” ksmd ๋ฉ”์ธ ์Šค๋ ˆ๋“œ

// mm/ksm.c:2801-2826
static int ksm_scan_thread(void *nothing)

์—ญํ• : ๋ฐฑ๊ทธ๋ผ์šด๋“œ์—์„œ ksm_do_scan()์„ ๋ฐ˜๋ณต ํ˜ธ์ถœํ•˜๋Š” ์ปค๋„ ์Šค๋ ˆ๋“œ์ž…๋‹ˆ๋‹ค. set_user_nice(current, 5)๋กœ ๋‚ฎ์€ ์šฐ์„ ์ˆœ์œ„๋กœ ๋™์ž‘ํ•˜๋ฉฐ, KSM_RUN_MERGE ์ƒํƒœ์ผ ๋•Œ๋งŒ ์Šค์บ”์„ ์ˆ˜ํ–‰ํ•ฉ๋‹ˆ๋‹ค.

๋ถ„๊ธฐ ๋กœ์ง:

  • ksmd_should_run() โ†’ ksm_run & KSM_RUN_MERGE && mm_list ๋น„์–ด์žˆ์ง€ ์•Š์Œ์ด๋ฉด ์Šค์บ” ์‹คํ–‰
  • ์Šค์บ” ํ›„ ksm_thread_sleep_millisecs ๋™์•ˆ ๋Œ€๊ธฐ
  • ๋Œ€๊ธฐ ์ค‘ ksm_thread_sleep_millisecs ๊ฐ’์ด ๋ณ€๊ฒฝ๋˜๋ฉด ์ฆ‰์‹œ ๊นจ์–ด๋‚จ (ksm_iter_wait)
  • 2. ksm_do_scan() โ€” ์Šค์บ” ์›Œ์ปค

    // mm/ksm.c:2780-2794
    static void ksm_do_scan(unsigned int scan_npages)

    ์—ญํ• : scan_npages๋งŒํผ ํŽ˜์ด์ง€๋ฅผ ์Šค์บ”ํ•ฉ๋‹ˆ๋‹ค. ๊ฐ ๋ฐ˜๋ณต์—์„œ scan_get_next_rmap_item()์œผ๋กœ ๋‹ค์Œ ํ›„๋ณด ํŽ˜์ด์ง€๋ฅผ ์–ป๊ณ , cmp_and_merge_page()๋กœ ๋น„๊ต/๋ณ‘ํ•ฉ์„ ์‹œ๋„ํ•ฉ๋‹ˆ๋‹ค.

    ๋ถ„๊ธฐ ๋กœ์ง:

  • freezing(current)์ด๋ฉด ์ฆ‰์‹œ ์ข…๋ฃŒ (๋™๊ฒฐ ์ƒํƒœ)
  • rmap_item์ด NULL์ด๋ฉด ๋” ์ด์ƒ ์Šค์บ”ํ•  ๊ฒƒ์ด ์—†์Œ โ†’ ์ข…๋ฃŒ
  • ์Šค์บ” ํ›„ put_page(page)๋กœ ์ฐธ์กฐ ํ•ด์ œ, ksm_pages_scanned++
  • 3. cmp_and_merge_page() โ€” ํ•ต์‹ฌ ๋น„๊ต/๋ณ‘ํ•ฉ

    // mm/ksm.c:2248-2386
    static void cmp_and_merge_page(struct page *page, struct ksm_rmap_item *rmap_item)

    ์—ญํ• : ๋‹จ์ผ ํŽ˜์ด์ง€์˜ stable tree ๊ฒ€์ƒ‰, checksum ๋น„๊ต, unstable tree ๊ฒ€์ƒ‰/์‚ฝ์ž…, ๋ณ‘ํ•ฉ์„ ์ˆ˜ํ–‰ํ•˜๋Š” ํ•ต์‹ฌ ํ•จ์ˆ˜์ž…๋‹ˆ๋‹ค.

    ๋ถ„๊ธฐ ๋กœ์ง:

    1. ์ด๋ฏธ stable tree์— ์žˆ์œผ๋ฉด โ†’ is_page_sharing_candidate() ํ™•์ธ ํ›„ ์กฐ๊ธฐ ๋ฐ˜ํ™˜

    2. checksum์ด ์ด์ „๊ณผ ๋‹ค๋ฅด๋ฉด โ†’ ํŽ˜์ด์ง€๊ฐ€ ๋นˆ๋ฒˆํžˆ ๋ณ€๊ฒฝ๋จ โ†’ unstable tree์—๋„ ๋„ฃ์ง€ ์•Š์Œ

    3. try_to_merge_with_zero_page() โ†’ zero page ๋ณ‘ํ•ฉ ๊ฐ€๋Šฅํ•˜๋ฉด ๋ณ‘ํ•ฉ ํ›„ ๋ฐ˜ํ™˜

    4. stable_tree_search(page) โ†’ stable tree์—์„œ ๋™์ผ ํŽ˜์ด์ง€ ์ฐพ๊ธฐ

    - ์ฐพ์œผ๋ฉด โ†’ try_to_merge_with_ksm_page()๋กœ ๋ณ‘ํ•ฉ ์‹œ๋„

    5. unstable tree์—์„œ unstable_tree_search_insert() โ†’ ๋™์ผ ํŽ˜์ด์ง€ ์ฐพ์œผ๋ฉด

    - try_to_merge_two_pages()๋กœ ๋‘ ํŽ˜์ด์ง€๋ฅผ ๋ณ‘ํ•ฉ ํ›„ stable tree์— ์‚ฝ์ž…

    4. stable_tree_search() โ€” stable tree ํƒ์ƒ‰

    // mm/ksm.c:1825-2030
    static struct folio *stable_tree_search(struct page *page)

    ์—ญํ• : stable tree์—์„œ ์Šค์บ” ์ค‘์ธ ํŽ˜์ด์ง€์™€ ๋™์ผํ•œ ๋‚ด์šฉ์˜ KSM ํŽ˜์ด์ง€๋ฅผ ์ฐพ์Šต๋‹ˆ๋‹ค. chain/dup ๊ตฌ์กฐ๋ฅผ ์ˆœํšŒํ•˜๋ฉฐ memcmp_pages()๋กœ ๋‚ด์šฉ์„ ๋น„๊ตํ•ฉ๋‹ˆ๋‹ค.

    ๋ถ„๊ธฐ ๋กœ์ง:

  • ์ด๋ฏธ KSM fork๋œ ํŽ˜์ด์ง€๋ฉด โ†’ ์ฆ‰์‹œ ๋ฐ˜ํ™˜
  • tree traversal ์ค‘ stale node ๋ฐœ๊ฒฌ โ†’ ksm_get_folio()๊ฐ€ ์ œ๊ฑฐ โ†’ ๊ฒ€์ƒ‰ ์žฌ์‹œ์ž‘
  • memcmp_pages() == 0 โ†’ ๋™์ผ ํŽ˜์ด์ง€ ๋ฐœ๊ฒฌ
  • - is_page_sharing_candidate() โ†’ ๊ณต์œ  ๊ฐ€๋Šฅํ•˜๋ฉด folio ๋ฐ˜ํ™˜

    - ๊ณต์œ  ๋ถˆ๊ฐ€ โ†’ chain ๋‚ด ๋‹ค๋ฅธ dup ํƒ์ƒ‰ ๋˜๋Š” NULL ๋ฐ˜ํ™˜

    5. unstable_tree_search_insert() โ€” unstable tree ๊ฒ€์ƒ‰/์‚ฝ์ž…

    // mm/ksm.c:2133-2198
    static struct ksm_rmap_item *unstable_tree_search_insert(
    struct ksm_rmap_item *rmap_item,
    struct page *page,
    struct page **tree_pagep)

    ์—ญํ• : unstable tree์—์„œ ๋™์ผ ํŽ˜์ด์ง€๋ฅผ ์ฐพ๊ฑฐ๋‚˜, ์—†์œผ๋ฉด ํ˜„์žฌ rmap_item์„ ์‚ฝ์ž…ํ•ฉ๋‹ˆ๋‹ค. unstable tree๋Š” ๋งค ์ „์ฒด ์Šค์บ” ์™„๋ฃŒ ์‹œ ๋ฆฌ์…‹๋˜๋ฏ€๋กœ ์•ˆ์ „ํ•ฉ๋‹ˆ๋‹ค.

    ๋ถ„๊ธฐ ๋กœ์ง:

  • tree traversal์—์„œ memcmp_pages() == 0 โ†’ ๋™์ผ ํŽ˜์ด์ง€ ๋ฐœ๊ฒฌ
  • - NUMA ๋…ธ๋“œ ๋ถˆ์ผ์น˜ ํ™•์ธ (!ksm_merge_across_nodes && ๋‹ค๋ฅธ ๋…ธ๋“œ)

    - *tree_pagep์— tree_page ์„ค์ • ํ›„ tree_rmap_item ๋ฐ˜ํ™˜

  • ์‚ฝ์ž…: rmap_item->address |= UNSTABLE_FLAG | seqnr, ksm_pages_unshared++
  • 6. write_protect_page() โ€” ํŽ˜์ด์ง€ ์“ฐ๊ธฐ ๋ณดํ˜ธ

    // mm/ksm.c:1272-1361
    static int write_protect_page(struct vm_area_struct *vma, struct folio *folio,
    pte_t *orig_pte)

    ์—ญํ• : ๋ณ‘ํ•ฉ ์ „์— ํŽ˜์ด์ง€๋ฅผ ์“ฐ๊ธฐ ๋ณดํ˜ธํ•ฉ๋‹ˆ๋‹ค. dirty/clean ์ƒํƒœ๊ฐ€ ์„ž์—ฌ ์žˆ์œผ๋ฉด PTE๋ฅผ ๋‹ค์‹œ ๋งž์ถฐ์•ผ ํ•˜๋ฉฐ folio lock์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.

    ๋ถ„๊ธฐ ๋กœ์ง:

  • large folio๋ฉด โ†’ error ๋ฐ˜ํ™˜ (KSM์€ ์ผ๋ฐ˜ ํŽ˜์ด์ง€๋งŒ ์ฒ˜๋ฆฌ)
  • pte_write || pte_dirty || anon_exclusive || mm_tlb_flush_pending โ†’ PTE ํด๋ฆฌ์–ด ํ›„ ์žฌ์„ค์ •
  • folio_mapcount + 1 + swapped != folio_ref_count โ†’ O_DIRECT ์ง„ํ–‰ ์ค‘ โ†’ ์‹คํŒจ
  • anon_exclusive โ†’ folio_try_share_anon_rmap_pte() ์‹คํŒจ ์‹œ โ†’ ์‹คํŒจ
  • 7. ksm_madvise() โ€” VMA ๋ณ‘ํ•ฉ ํ—ˆ์šฉ/ํ•ด์ œ

    // mm/ksm.c:2975-3013
    int ksm_madvise(struct vm_area_struct *vma, unsigned long start,
    unsigned long end, int advice, vm_flags_t *vm_flags)

    ์—ญํ• : MADV_MERGEABLE์™€ MADV_UNMERGEABLE ์š”์ฒญ์„ ์ฒ˜๋ฆฌํ•ฉ๋‹ˆ๋‹ค. MADV_MERGEABLE์€ __ksm_enter(mm)๋กœ ํ•ด๋‹น mm_struct๋ฅผ KSM ๊ด€๋ฆฌ ๋Œ€์ƒ์— ๋„ฃ๊ณ  VM_MERGEABLE์„ ์ผœ๋ฉฐ, MADV_UNMERGEABLE์€ ์ด๋ฏธ ๋ณ‘ํ•ฉ๋œ ํŽ˜์ด์ง€๊ฐ€ ์žˆ์œผ๋ฉด break_ksm()์œผ๋กœ ๋ถ„๋ฆฌํ•œ ๋’ค ํ”Œ๋ž˜๊ทธ๋ฅผ ๋•๋‹ˆ๋‹ค.

    ๋ถ„๊ธฐ ๋กœ์ง:

  • MADV_MERGEABLE โ†’ vma_ksm_compatible() ํ™•์ธ, __ksm_enter(mm) ํ•„์š” ์‹œ ํ˜ธ์ถœ, *vm_flags |= VM_MERGEABLE
  • MADV_UNMERGEABLE โ†’ VM_MERGEABLE๊ฐ€ ์—†์œผ๋ฉด ๋ฌด์‹œ, ์ต๋ช… VMA๋ฉด break_ksm(vma, start, end, true) ํ›„ ํ”Œ๋ž˜๊ทธ ํ•ด์ œ
  • // mm/madvise.c:1416-1422
    case MADV_MERGEABLE:
    case MADV_UNMERGEABLE:
    error = ksm_madvise(vma, range->start, range->end,
    behavior, &new_flags);
    if (error)
    goto out;
    break;

    ํ˜ธ์ถœ ํ๋ฆ„

    ksm_scan_thread()                          โ† ksmd ๋ฉ”์ธ ์Šค๋ ˆ๋“œ
    โ””โ”€ ksm_do_scan(pages_to_scan)            โ† scan_npages๋งŒํผ ๋ฐ˜๋ณต
    โ””โ”€ scan_get_next_rmap_item(&page)   โ† ๋‹ค์Œ ํ›„๋ณด ํŽ˜์ด์ง€/ rmap_item ํš๋“
    โ””โ”€ walk_page_range_vma()       โ† VMA ์ˆœํšŒํ•˜์—ฌ ์ต๋ช… ํŽ˜์ด์ง€ ํƒ์ƒ‰
    โ””โ”€ get_next_rmap_item()        โ† rmap_item ํ• ๋‹น/์กฐํšŒ
    โ””โ”€ should_skip_rmap_item()     โ† smart scan: ๊ฑด๋„ˆ๋›ธ์ง€ ๊ฒฐ์ •
    โ””โ”€ cmp_and_merge_page(page, rmap_item)  โ† ํ•ต์‹ฌ ๋น„๊ต/๋ณ‘ํ•ฉ
    โ”œโ”€ calc_checksum()             โ† xxhash ๊ธฐ๋ฐ˜ ์ฒดํฌ์„ฌ ๊ณ„์‚ฐ
    โ”œโ”€ stable_tree_search(page)    โ† stable tree์—์„œ ๋™์ผ ํŽ˜์ด์ง€ ํƒ์ƒ‰
    โ”‚    โ””โ”€ memcmp_pages()         โ† ํŽ˜์ด์ง€ ๋‚ด์šฉ ๋ฐ”์ดํŠธ ๋น„๊ต
    โ”‚    โ””โ”€ chain_prune()          โ† stale chain/dup ์ •๋ฆฌ
    โ”œโ”€ unstable_tree_search_insert() โ† unstable tree ๊ฒ€์ƒ‰/์‚ฝ์ž…
    โ”‚    โ””โ”€ memcmp_pages()         โ† ํŽ˜์ด์ง€ ๋‚ด์šฉ ๋น„๊ต
    โ”œโ”€ try_to_merge_with_ksm_page() โ† ๊ธฐ์กด KSM ํŽ˜์ด์ง€์™€ ๋ณ‘ํ•ฉ
    โ”‚    โ””โ”€ try_to_merge_one_page()
    โ”‚         โ””โ”€ write_protect_page() โ† PTE ์“ฐ๊ธฐ ๋ณดํ˜ธ
    โ”‚         โ””โ”€ replace_page()    โ† PTE๋ฅผ KSM ํŽ˜์ด์ง€๋กœ ๊ต์ฒด
    โ””โ”€ try_to_merge_two_pages()    โ† ๋‘ ๋ฏธ๋ณ‘ํ•ฉ ํŽ˜์ด์ง€ ๋ณ‘ํ•ฉ
    โ””โ”€ stable_tree_insert()   โ† stable tree์— ์ƒˆ KSM ๋…ธ๋“œ ์‚ฝ์ž…
    โ””โ”€ stable_tree_append()   โ† rmap_item์„ stable node์— ์—ฐ๊ฒฐ

    KSM Stable/Unstable Tree ๋น„๊ต

    ์กฐ๊ฑด๋ณ„ ๋น„๊ต

    KSM ์Šค์บ” ๋ชจ๋“œ ๋น„๊ต

    ํ•ญ๋ชฉKSM_RUN_STOP (0)KSM_RUN_MERGE (1)KSM_RUN_UNMERGE (2)
    ksmd ๋™์ž‘์ค‘์ง€์Šค์บ”/๋ณ‘ํ•ฉ ์ˆ˜ํ–‰๋ณ‘ํ•ฉ ํ•ด์ œ๋งŒ ์ˆ˜ํ–‰
    ํŠธ๋ฆฌ ๋™์ž‘๋ถˆ๋ณ€stable/unstable tree ๊ฐฑ์‹ ๋ชจ๋“  rmap_item์„ unstable์—์„œ ์ œ๊ฑฐ
    COW ๋ฐœ๋™์—†์Œ๋ณ‘ํ•ฉ ์‹œ write-protect ๋ฐœ์ƒbreak_ksm()์œผ๋กœ ๋ชจ๋“  KSM ํŽ˜์ด์ง€ ๋ณ‘ํ•ฉ ํ•ด์ œ
    ํŠธ๋ฆฌ๊ฑฐ`echo 0 > run``echo 1 > run``echo 2 > run`

    Smart Scan vs ์ผ๋ฐ˜ ์Šค์บ”

    ํ•ญ๋ชฉSmart Scan (๊ธฐ๋ณธ ์ผœ์ง)์ผ๋ฐ˜ ์Šค์บ” (๋„๋ฉด)
    ๊ฑด๋„ˆ๋œ€ ๋ฉ”์ปค๋‹ˆ์ฆ˜age/remaining_skips๋กœ ๋นˆ๋ฒˆ ๋ณ€๊ฒฝ ํŽ˜์ด์ง€ ์Šคํ‚ต๋ชจ๋“  ํŽ˜์ด์ง€ ์Šค์บ”
    ๊ฑด๋„ˆ๋œ€ ๊ธฐ์ค€age โ‰ฅ 3๋ถ€ํ„ฐ ์ ์ง„์  ์Šคํ‚ต (1โ†’2โ†’4โ†’8ํšŒ)์—†์Œ
    pages_skipped์ฆ๊ฐ€0 ์œ ์ง€
    ๋Œ€์ƒ`folio_test_ksm()`์ด ์•„๋‹Œ ์ผ๋ฐ˜ ์ต๋ช… ํŽ˜์ด์ง€๋ชจ๋“  anonymous ํŽ˜์ด์ง€
    ์žฅ์ ๋ถˆํ•„์š”ํ•œ ์Šค์บ” ์ตœ์†Œํ™”, CPU ์ ˆ์•ฝ์™„์ „ํ•œ ์Šค์บ” ๋ณด์žฅ

    NUMA ๋ณ‘ํ•ฉ ์ •์ฑ… ๋น„๊ต

    ํ•ญ๋ชฉmerge_across_nodes=1 (๊ธฐ๋ณธ)merge_across_nodes=0
    stable/unstable tree์ „์—ญ 1๊ฐœ์”ฉNUMA node๋ณ„ ๋ณ„๋„ tree
    NUMA ์›๊ฒฉ ๋ณ‘ํ•ฉํ—ˆ์šฉ๋ถˆํ—ˆ (๊ฐ™์€ ๋…ธ๋“œ ๋‚ด์—์„œ๋งŒ ๋ณ‘ํ•ฉ)
    ๋ฉ”๋ชจ๋ฆฌ ์ ˆ๊ฐ์ตœ๋Œ€ (์›๊ฒฉ ํฌํ•จ)locality ์šฐ์„ 
    tree ๊ตฌ์กฐ`root_stable_tree[0]`๋งŒ ์‚ฌ์šฉ`root_stable_tree[nr_node_ids]` ๋ฐฐ์—ด

    Advisor ๋ชจ๋“œ ๋น„๊ต

    ํ•ญ๋ชฉKSM_ADVISOR_NONE (๊ธฐ๋ณธ)KSM_ADVISOR_SCAN_TIME
    pages_to_scan ์ œ์–ด์ˆ˜๋™ (sysfs)์ž๋™ ์ ์‘ํ˜•
    ๋ชฉํ‘œ์—†์Œ`ksm_advisor_target_scan_time` (๊ธฐ๋ณธ 200์ดˆ)
    CPU ์ œํ•œ์—†์Œ`KSM_ADVISOR_MIN_CPU` (10%) ~ `ksm_advisor_max_cpu` (70%)
    EWMA ์ ์šฉ์—†์Œ์Šค์บ” ์‹œ๊ฐ„ ๋ณ€ํ™”๋Ÿ‰์„ EWMA๋กœ ํ‰ํ™œ

    VMA ์ง€์ • ๊ฒฝ๋กœ ๋น„๊ต

    ํ•ญ๋ชฉ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ `madvise`์šด์˜์ž sysfs
    ๋Œ€์ƒ๊ฐœ๋ณ„ VMA์ „์ฒด ksmd ์ •์ฑ…
    ํ•ต์‹ฌ ๋™์ž‘`MADV_MERGEABLE`๋กœ `VM_MERGEABLE` ์„ค์ •, `MADV_UNMERGEABLE`๋กœ ํ•ด์ œ`run`, `pages_to_scan`, `sleep_millisecs`, `advisor_mode` ์กฐ์ •
    ์ปค๋„ ์ง„์ž…์ `mm/madvise.c` โ†’ `ksm_madvise()``mm/ksm.c` sysfs store ํ•จ์ˆ˜
    ํšจ๊ณผ๋ณ‘ํ•ฉ ํ›„๋ณด ์ง€์ •/ํ•ด์ œ์Šค์บ” ์‹คํ–‰, ์†๋„, CPU ์ƒํ•œ ์ œ์–ด

    Stable Tree ๋…ธ๋“œ ์œ ํ˜• ๋น„๊ต

    ํ•ญ๋ชฉ์ผ๋ฐ˜ stable_nodechain stable_nodedup stable_node
    ์—ญํ• KSM ํŽ˜์ด์ง€ 1๊ฐœ๋ฅผ ๋‚˜ํƒ€๋ƒ„๋™์ผ ๋‚ด์šฉ์˜ ์—ฌ๋Ÿฌ KSM ํŽ˜์ด์ง€ ๊ทธ๋ฃนchain ๋‚ด ๊ฐœ๋ณ„ KSM ํŽ˜์ด์ง€
    rmap_hlist_len0 ~ ksm_max_page_sharingSTABLE_NODE_CHAIN (-1024)0 ~ ksm_max_page_sharing
    hlistrmap_item ์—ฐ๊ฒฐdup stable_node ์—ฐ๊ฒฐrmap_item ์—ฐ๊ฒฐ
    rb_tree(rb_node ์‚ฌ์šฉ)(rb_node ์‚ฌ์šฉ)(rb_node ๋ฏธ์‚ฌ์šฉ, hlist_dup๋กœ chain์— ์—ฐ๊ฒฐ)

    KSM ์ˆ˜์ต ๊ณ„์‚ฐ

    KSM์˜ ๋ฉ”๋ชจ๋ฆฌ ์ ˆ๊ฐ ํšจ๊ณผ๋Š” general_profit์œผ๋กœ ์ธก์ •๋ฉ๋‹ˆ๋‹ค:

    general_profit = (pages_sharing + ksm_zero_pages) ร— PAGE_SIZE
    - rmap_items ร— sizeof(struct ksm_rmap_item)
  • ์–‘์ˆ˜: KSM์ด ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ์ ˆ์•ฝํ•˜๊ณ  ์žˆ์Œ (๋ณ‘ํ•ฉ๋œ ํŽ˜์ด์ง€์˜ ๊ณต์œ  ๋ฉ”๋ชจ๋ฆฌ > rmap_item ์˜ค๋ฒ„ํ—ค๋“œ)
  • ์Œ์ˆ˜: rmap_item ์˜ค๋ฒ„ํ—ค๋“œ๊ฐ€ ๋ณ‘ํ•ฉ ์ด์ต๋ณด๋‹ค ํผ โ†’ KSM ๋น„ํ™œ์„ฑ ๊ณ ๋ ค

  • ๊ด€๋ จ ๋ฌธ์„œ

  • 00-overview.html โ€” ๋ฉ”๋ชจ๋ฆฌ ๊ด€๋ฆฌ ๊ฐœ์š” (KSM ์„น์…˜)
  • 03-vma_mmap.html โ€” VMA/mmap (VM_MERGEABLE ํ”Œ๋ž˜๊ทธ)
  • 05-page_reclaim.html โ€” ํŽ˜์ด์ง€ ํšŒ์ˆ˜ (write-protect์™€ ๊ด€๋ จ)
  • 10-hugepage.html โ€” Huge Pages (THP์™€ KSM ์ƒํ˜ธ์ž‘์šฉ)
  • 13-numa.html โ€” NUMA (merge_across_nodes ์ •์ฑ…)

  • ์ฐธ๊ณ : KSM Sysfs ์ธํ„ฐํŽ˜์ด์Šค ์š”์•ฝ

    ํŒŒ์ผ์ฝ๊ธฐ/์“ฐ๊ธฐ์„ค๋ช…๊ธฐ๋ณธ๊ฐ’
    `/sys/kernel/mm/ksm/run`RW0:์ค‘์ง€, 1:๋ณ‘ํ•ฉ, 2:๋ณ‘ํ•ฉํ•ด์ œ0
    `/sys/kernel/mm/ksm/pages_to_scan`RWํ•œ ๋ฒˆ์— ์Šค์บ”ํ•  ํŽ˜์ด์ง€ ์ˆ˜100
    `/sys/kernel/mm/ksm/sleep_millisecs`RW์Šค์บ” ๊ฐ„ ๋Œ€๊ธฐ (ms)20
    `/sys/kernel/mm/ksm/merge_across_nodes`RWNUMA ๊ฐ„ ๋ณ‘ํ•ฉ ํ—ˆ์šฉ1
    `/sys/kernel/mm/ksm/use_zero_pages`RWzero page ๋ณ‘ํ•ฉ0
    `/sys/kernel/mm/ksm/smart_scan`RW์Šค๋งˆํŠธ ์Šค์บ”1
    `/sys/kernel/mm/ksm/max_page_sharing`RW์ตœ๋Œ€ ๊ณต์œ  ๋งคํ•‘ ์ˆ˜256
    `/sys/kernel/mm/ksm/advisor_mode`RWnone / scan-timenone
    `/sys/kernel/mm/ksm/advisor_max_cpu`RW์ตœ๋Œ€ CPU%70
    `/sys/kernel/mm/ksm/advisor_min_pages_to_scan`RW์ตœ์†Œ ์Šค์บ” ํŽ˜์ด์ง€ ์ˆ˜500
    `/sys/kernel/mm/ksm/advisor_max_pages_to_scan`RW์ตœ๋Œ€ ์Šค์บ” ํŽ˜์ด์ง€ ์ˆ˜30000
    `/sys/kernel/mm/ksm/advisor_target_scan_time`RW๋ชฉํ‘œ ์Šค์บ” ์‹œ๊ฐ„ (์ดˆ)200
    `/sys/kernel/mm/ksm/pages_shared`RO๊ณ ์œ  KSM ํŽ˜์ด์ง€ ์ˆ˜-
    `/sys/kernel/mm/ksm/pages_sharing`RO๊ณต์œ  ๋งคํ•‘ ์ˆ˜-
    `/sys/kernel/mm/ksm/pages_unshared`RO๋ฏธ๋ณ‘ํ•ฉ ํ›„๋ณด ์ˆ˜-
    `/sys/kernel/mm/ksm/pages_volatile`RO์–ด๋А ํŠธ๋ฆฌ์—๋„ ์—†๋Š” rmap_item-
    `/sys/kernel/mm/ksm/pages_scanned`RO์ด ์Šค์บ” ํŽ˜์ด์ง€ ์ˆ˜-
    `/sys/kernel/mm/ksm/pages_skipped`RO๊ฑด๋„ˆ๋›ด ํŽ˜์ด์ง€ ์ˆ˜-
    `/sys/kernel/mm/ksm/ksm_zero_pages`ROzero page ๋ณ‘ํ•ฉ ์ˆ˜-
    `/sys/kernel/mm/ksm/full_scans`RO์ „์ฒด ์Šค์บ” ์™„๋ฃŒ ํšŸ์ˆ˜-
    `/sys/kernel/mm/ksm/general_profit`RO๋ฉ”๋ชจ๋ฆฌ ์ˆ˜์ต (bytes)-
    `/sys/kernel/mm/ksm/advisor_mode`RWnone / scan-timenone
    `/sys/kernel/mm/ksm/advisor_max_cpu`RW์ตœ๋Œ€ CPU%70
    `/sys/kernel/mm/ksm/advisor_target_scan_time`RW๋ชฉํ‘œ ์Šค์บ” ์‹œ๊ฐ„ (์ดˆ)200