DAMON (Data Access Monitor)

๊ด€๋ จ ์†Œ์Šค: mm/damon/ ๋””๋ ‰ํ† ๋ฆฌ (core.c, reclaim.c, lru_sort.c, vaddr.c, paddr.c, ops-common.c, modules-common.c, sysfs.c)
๊ด€๋ จ ๋ฌธ์„œ: ํŽ˜์ด์ง€ ํšŒ์ˆ˜ (vmscan) ยท ํŽ˜์ด์ง€ Migration ยท ๋ฉ”๋ชจ๋ฆฌ ๊ด€๋ฆฌ ๊ฐœ์š”

๊ฐœ์š” (Overview)

DAMON(Data Access Monitor)๋Š” Linux 5.15์—์„œ SeongJae Park์ด ๋„์ž…ํ•œ ๋ฉ”๋ชจ๋ฆฌ ์ ‘๊ทผ ํŒจํ„ด ๋ชจ๋‹ˆํ„ฐ๋ง ํ”„๋ ˆ์ž„์›Œํฌ์ž…๋‹ˆ๋‹ค. ๋ฌผ๋ฆฌ ๋˜๋Š” ๊ฐ€์ƒ ์ฃผ์†Œ ๊ณต๊ฐ„์„ ์ƒ˜ํ”Œ๋ง ๊ธฐ๋ฐ˜์œผ๋กœ ๋ชจ๋‹ˆํ„ฐ๋งํ•˜์—ฌ ํ•ซ/์ฝœ๋“œ ์˜์—ญ์„ ๊ตฌ๋ถ„ํ•˜๊ณ , ์ ‘๊ทผ ํŒจํ„ด์— ๊ธฐ๋ฐ˜ํ•œ ์ž๋™ํ™”๋œ ๋ฉ”๋ชจ๋ฆฌ ๊ด€๋ฆฌ ์ž‘์—…(DAMOS: Data Access Monitoring-based Operation Scheme)์„ ์ˆ˜ํ–‰ํ•ฉ๋‹ˆ๋‹ค. ์˜ค๋ฒ„ํ—ค๋“œ๊ฐ€ 1% ๋ฏธ๋งŒ์œผ๋กœ ๋‚ฎ์•„ ํ”„๋กœ๋•์…˜ ์‹œ์Šคํ…œ์—์„œ๋„ ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.

DAMON์˜ ํ•ต์‹ฌ ์„ค๊ณ„ ์›์น™์€ "์ •ํ™•ํ•œ ๋ชจ๋‹ˆํ„ฐ๋ง์€ ๋ถˆํ•„์š”ํ•˜๊ณ , ์ถฉ๋ถ„ํžˆ ์ •ํ™•ํ•œ ์ถ”์ •์ด๋ฉด ๋œ๋‹ค"์ž…๋‹ˆ๋‹ค. ์ „์ฒด ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ์ •๋ฐ€ ์ถ”์ ํ•˜๋Š” ๋Œ€์‹  ์ƒ˜ํ”Œ๋ง๊ณผ ์˜์—ญ(region)์˜ ์ ์‘์  ๋ณ‘ํ•ฉ/๋ถ„ํ• ์„ ํ†ตํ•ด ๋†’์€ ์ •ํ™•๋„์™€ ๋‚ฎ์€ ์˜ค๋ฒ„ํ—ค๋“œ๋ฅผ ๋™์‹œ์— ๋‹ฌ์„ฑํ•ฉ๋‹ˆ๋‹ค. ๋‚ด์žฅ ๋ชจ๋“ˆ์ธ damon_reclaim(์ฝœ๋“œ ํŽ˜์ด์ง€ ์ž๋™ ํšŒ์ˆ˜)๊ณผ damon_lru_sort(LRU ๋ฆฌ์ŠคํŠธ ์ž๋™ ์ •๋ ฌ)๊ฐ€ ๋Œ€ํ‘œ์ ์ธ ํ™œ์šฉ ์‚ฌ๋ก€์ž…๋‹ˆ๋‹ค.

๋„์„œ๊ด€์œผ๋กœ ๋น„์œ ํ•˜๋ฉด, DAMON์€ ๋ชจ๋“  ์ฑ…์˜ ๋Œ€์ถœ ๊ธฐ๋ก์„ ์ผ์ผ์ด ์„ธ์ง€ ์•Š๊ณ  ์ž์ฃผ ์ฐพ๋Š” ์„œ๊ฐ€๋งŒ ๋น ๋ฅด๊ฒŒ ํ‘œ์‹œํ•ด ์šฐ์„  ์ •๋ฆฌํ•˜๋Š” ๋ฐฉ์‹์— ๊ฐ€๊น์Šต๋‹ˆ๋‹ค. ํ˜„์žฅ์—์„œ๋Š” damo ๊ฐ™์€ ์‚ฌ์šฉ์ž ๊ณต๊ฐ„ ๋„๊ตฌ๋กœ ๋Œ€์ƒ๊ณผ ์Šคํ‚ด์„ ๋‹ค๋ฃจ๊ณ , DAMOS_MIGRATE_HOT/DAMOS_MIGRATE_COLD๋Š” NUMA ํ‹ฐ์–ด๋ง๊ณผ ํ•จ๊ป˜ ํ•ซ ๋ฐ์ดํ„ฐ ์ด๋™์— ํ™œ์šฉ๋ฉ๋‹ˆ๋‹ค. ์ด๋Ÿฐ ํ๋ฆ„์€ MGLRU๋‚˜ ๋ฉ”๋ชจ๋ฆฌ ํ‹ฐ์–ด๋ง ๋ฌธ์„œ์™€ ๊ฐ™์ด ๋ณด๋ฉด ๋” ๋˜๋ ทํ•ด์ง‘๋‹ˆ๋‹ค.

# ์†Œ์Šค ํŒŒ์ผ ๊ฒฝ๋กœ
mm/damon/core.c          โ€” ํ•ต์‹ฌ ๋ชจ๋‹ˆํ„ฐ๋ง ๋ฃจํ”„, ์˜์—ญ ๊ด€๋ฆฌ, DAMOS ๋กœ์ง
mm/damon/reclaim.c       โ€” DAMON ๊ธฐ๋ฐ˜ ํŽ˜์ด์ง€ ํšŒ์ˆ˜ ๋ชจ๋“ˆ
mm/damon/lru_sort.c      โ€” DAMON ๊ธฐ๋ฐ˜ LRU ์ •๋ ฌ ๋ชจ๋“ˆ
mm/damon/vaddr.c         โ€” ๊ฐ€์ƒ ์ฃผ์†Œ ๊ณต๊ฐ„ ๋ชจ๋‹ˆํ„ฐ๋ง ์—ฐ์‚ฐ
mm/damon/paddr.c         โ€” ๋ฌผ๋ฆฌ ์ฃผ์†Œ ๊ณต๊ฐ„ ๋ชจ๋‹ˆํ„ฐ๋ง ์—ฐ์‚ฐ
mm/damon/ops-common.c    โ€” ๊ณตํ†ต ์—ฐ์‚ฐ (PTE young/clear, folio ์ฒ˜๋ฆฌ)
mm/damon/sysfs.c         โ€” sysfs ์ธํ„ฐํŽ˜์ด์Šค
mm/damon/modules-common.c โ€” ๋ชจ๋“ˆ ๊ณตํ†ต ์œ ํ‹ธ๋ฆฌํ‹ฐ
include/linux/damon.h     โ€” ํ•ต์‹ฌ ์ž๋ฃŒ๊ตฌ์กฐ ๋ฐ API ์ •์˜

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

# DAMON sysfs ์ธํ„ฐํŽ˜์ด์Šค ํ™•์ธ
ls /sys/kernel/mm/damon/

# DAMON_RECLAIM ํ™œ์„ฑํ™”
echo Y > /sys/module/damon_reclaim/parameters/enabled

# DAMON_RECLAIM ํŒŒ๋ผ๋ฏธํ„ฐ ํ™•์ธ
cat /sys/module/damon_reclaim/parameters/min_age
cat /sys/module/damon_reclaim/parameters/monitor_region_start
cat /sys/module/damon_reclaim/parameters/monitor_region_end

# DAMON_LRU_SORT ํ™œ์„ฑํ™” (์ปค๋„ 6.0+)
echo Y > /sys/module/damon_lru_sort/parameters/enabled

# kdamond ์Šค๋ ˆ๋“œ ํ™•์ธ
ps aux | grep kdamond

# DAMON tracepoint ์ด๋ฒคํŠธ ํ™•์ธ
sudo perf list | grep damon

# DAMOS ํ†ต๊ณ„ ํ™•์ธ (sysfs)
cat /sys/kernel/mm/damon/admin/kdamonds/nr_kdamonds
ls /sys/kernel/mm/damon/admin/kdamonds/0/contexts/

# ๋ฉ”๋ชจ๋ฆฌ ์••๋ ฅ ํ™•์ธ (PSI)
cat /proc/pressure/memory

# ๋ฌผ๋ฆฌ ์ฃผ์†Œ ์˜์—ญ ํ™•์ธ (DAMON_RECLAIM ๋Œ€์ƒ)
sudo cat /proc/iomem | head -20

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

DAMON ํ•ต์‹ฌ ์ž๋ฃŒ๊ตฌ์กฐ ๊ด€๊ณ„๋„

struct damon_region

๋ชจ๋‹ˆํ„ฐ๋ง ๋Œ€์ƒ ๋ฉ”๋ชจ๋ฆฌ ์˜์—ญ์„ ๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค. ๊ฐ ์˜์—ญ์€ ์‹œ์ž‘/๋ ์ฃผ์†Œ, ์ ‘๊ทผ ๋นˆ๋„, ๋‚˜์ด(age)๋ฅผ ์ถ”์ ํ•ฉ๋‹ˆ๋‹ค.

/* include/linux/damon.h:76-86 */
struct damon_region {
	struct damon_addr_range ar;        /* ์‹œ์ž‘ ์ฃผ์†Œ (inclusive), ๋ ์ฃผ์†Œ (exclusive) */
	unsigned long sampling_addr;       /* ๋‹ค์Œ ์ ‘๊ทผ ํ™•์ธ์„ ์œ„ํ•œ ์ƒ˜ํ”Œ๋ง ์ฃผ์†Œ */
	unsigned int nr_accesses;          /* ํ˜„์žฌ ์ง‘๊ณ„ ๊ตฌ๊ฐ„์—์„œ์˜ ์ ‘๊ทผ ํšŸ์ˆ˜ */
	unsigned int nr_accesses_bp;       /* ์ ‘๊ทผ ๋นˆ๋„ (basis point, 1/10000) */
	struct list_head list;             /* ํ˜•์ œ ์˜์—ญ ์—ฐ๊ฒฐ์šฉ ๋ฆฌ์ŠคํŠธ */

	unsigned int age;                  /* ์ ‘๊ทผ ํŒจํ„ด ์œ ์ง€ ์‹œ๊ฐ„ (์ง‘๊ณ„ ๊ตฌ๊ฐ„ ๋‹จ์œ„) */
	unsigned int last_nr_accesses;     /* ์ด์ „ ์ง‘๊ณ„ ๊ตฌ๊ฐ„์˜ ์ ‘๊ทผ ํšŸ์ˆ˜ */
};

ํ•„๋“œ ์„ค๋ช…:

  • ar: ์˜์—ญ์˜ ๋ฌผ๋ฆฌ/๊ฐ€์ƒ ์ฃผ์†Œ ๋ฒ”์œ„ [start, end)
  • sampling_addr: ๋งค ์ƒ˜ํ”Œ๋ง ๊ตฌ๊ฐ„๋งˆ๋‹ค ๋žœ๋ค์œผ๋กœ ์„ ํƒ๋˜๋Š” ํ™•์ธ ๋Œ€์ƒ ์ฃผ์†Œ
  • nr_accesses: ํ˜„์žฌ aggr_interval ๋‚ด์—์„œ ์ ‘๊ทผ์ด ๊ฐ์ง€๋œ ์ƒ˜ํ”Œ๋ง ํšŸ์ˆ˜. aggr_interval๋งˆ๋‹ค 0์œผ๋กœ ๋ฆฌ์…‹๋จ
  • nr_accesses_bp: nr_accesses๋ฅผ basis point๋กœ ํ‘œํ˜„ํ•œ ๊ฐ’. ์ด๋™ ํ•ฉ(moving sum) ๋ฐฉ์‹์œผ๋กœ ์—…๋ฐ์ดํŠธ๋˜์–ด, aggr_interval์ด ๋„ˆ๋ฌด ๊ธธ ๋•Œ๋„ ์ฆ‰์‹œ ์ ‘๊ทผ ์ •๋ณด๋ฅผ ์–ป์„ ์ˆ˜ ์žˆ์Œ
  • age: ์ธ์ ‘ ์˜์—ญ ๋ณ‘ํ•ฉ ์‹œ ๊ฐ€์ค‘ํ‰๊ท ์œผ๋กœ ๊ณ„์‚ฐ๋จ. ์ ‘๊ทผ ํŒจํ„ด์ด ๋ณ€ํ•˜๋ฉด 0์œผ๋กœ ๋ฆฌ์…‹
  • struct damon_target

    ๋ชจ๋‹ˆํ„ฐ๋ง ๋Œ€์ƒ(ํ”„๋กœ์„ธ์Šค์˜ ๊ฐ€์ƒ ์ฃผ์†Œ ๊ณต๊ฐ„ ๋˜๋Š” ๋ฌผ๋ฆฌ ์ฃผ์†Œ ๊ณต๊ฐ„ ์ „์ฒด)์„ ๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค.

    /* include/linux/damon.h:105-111 */
    struct damon_target {
    	struct pid *pid;                    /* ๋Œ€์ƒ ํ”„๋กœ์„ธ์Šค์˜ PID (๋ฌผ๋ฆฌ ์ฃผ์†Œ๋Š” NULL) */
    	unsigned int nr_regions;            /* ์ด ๋Œ€์ƒ์˜ ์˜์—ญ ์ˆ˜ */
    	struct list_head regions_list;      /* damon_region ์—ฐ๊ฒฐ ๋ฆฌ์ŠคํŠธ ํ—ค๋“œ */
    	struct list_head list;              /* ๋‹ค๋ฅธ ๋Œ€์ƒ๊ณผ์˜ ์—ฐ๊ฒฐ์šฉ ๋ฆฌ์ŠคํŠธ */
    	bool obsolete;                      /* commit ์‹œ ํ๊ธฐ ๋Œ€์ƒ ํ‘œ์‹œ */
    };

    struct damos (DAMOS Scheme)

    ๋ฐ์ดํ„ฐ ์ ‘๊ทผ ๋ชจ๋‹ˆํ„ฐ๋ง ๊ธฐ๋ฐ˜ ๋™์ž‘ ๊ณ„ํš์„ ์ •์˜ํ•ฉ๋‹ˆ๋‹ค. ์ ‘๊ทผ ํŒจํ„ด ์กฐ๊ฑด์— ๋งž๋Š” ์˜์—ญ์— ํŠน์ • ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•˜๋Š” ๊ทœ์น™์ž…๋‹ˆ๋‹ค.

    /* include/linux/damon.h:545-580 */
    struct damos {
    	struct damos_access_pattern pattern; /* ๋Œ€์ƒ ์ ‘๊ทผ ํŒจํ„ด (ํฌ๊ธฐ, ์ ‘๊ทผ ๋นˆ๋„, ๋‚˜์ด ๋ฒ”์œ„) */
    	enum damos_action action;            /* ์ ์šฉํ•  ๋™์ž‘ (PAGEOUT, COLD, HUGEPAGE ๋“ฑ) */
    	unsigned long apply_interval_us;     /* ๋™์ž‘ ์ ์šฉ ์ฃผ๊ธฐ (๋งˆ์ดํฌ๋กœ์ดˆ) */
    	/* ๋‚ด๋ถ€ ์‚ฌ์šฉ ํ•„๋“œ */
    	unsigned long next_apply_sis;        /* ๋‹ค์Œ ์ ์šฉ ์‹œ์  (์ƒ˜ํ”Œ๋ง ๊ตฌ๊ฐ„ ๊ธฐ์ค€) */
    	bool walk_completed;                 /* DAMOS walk ์™„๋ฃŒ ์—ฌ๋ถ€ */
    	bool core_filters_allowed;           /* ์ฝ”์–ด ํ•„ํ„ฐ ํ†ต๊ณผ ์—ฌ๋ถ€ */
    	/* ๊ณต๊ฐœ ํ•„๋“œ */
    	struct damos_quota quota;            /* ์ž์› ์ œํ•œ (์‹œ๊ฐ„/ํฌ๊ธฐ) */
    	struct damos_watermarks wmarks;      /* ์›Œํ„ฐ๋งˆํฌ ๊ธฐ๋ฐ˜ ์ž๋™ ํ™œ์„ฑํ™”/๋น„ํ™œ์„ฑํ™” */
    	struct list_head core_filters;       /* ์ฝ”์–ด ๋ ˆ์ด์–ด ํ•„ํ„ฐ ๋ชฉ๋ก */
    	struct list_head ops_filters;        /* ์—ฐ์‚ฐ ๋ ˆ์ด์–ด ํ•„ํ„ฐ ๋ชฉ๋ก */
    	void *last_applied;                  /* ๋งˆ์ง€๋ง‰ ์ ์šฉ๋œ ์—ฐ์‚ฐ ๋Œ€์ƒ (์ค‘๋ณต ๋ฐฉ์ง€) */
    	struct damos_stat stat;              /* ์ ์šฉ ํ†ต๊ณ„ */
    	struct list_head list;               /* ๋‹ค๋ฅธ ์Šคํ‚ด๊ณผ์˜ ์—ฐ๊ฒฐ์šฉ ๋ฆฌ์ŠคํŠธ */
    };

    struct damon_ctx

    ๋ชจ๋‹ˆํ„ฐ๋ง ์ปจํ…์ŠคํŠธ. ํ•˜๋‚˜์˜ kdamond ์Šค๋ ˆ๋“œ๊ฐ€ ๊ด€๋ฆฌํ•˜๋Š” ์ตœ์ƒ์œ„ ๊ฐ์ฒด์ž…๋‹ˆ๋‹ค.

    /* include/linux/damon.h:780 ๊ธฐ์ค€ ํ•ต์‹ฌ ํ•„๋“œ */
    struct damon_ctx {
    	struct damon_attrs attrs;            /* ๋ชจ๋‹ˆํ„ฐ๋ง ์†์„ฑ (์ƒ˜ํ”Œ/์ง‘๊ณ„/์—ฐ์‚ฐ ์—…๋ฐ์ดํŠธ ์ฃผ๊ธฐ) */
    	unsigned long passed_sample_intervals; /* ๊ฒฝ๊ณผํ•œ ์ƒ˜ํ”Œ๋ง ๊ตฌ๊ฐ„ ์ˆ˜ */
    	unsigned long next_aggregation_sis;  /* ๋‹ค์Œ ์ง‘๊ณ„ ์‹œ์  */
    	unsigned long next_ops_update_sis;   /* ๋‹ค์Œ ์—ฐ์‚ฐ ์—…๋ฐ์ดํŠธ ์‹œ์  */
    	/* kdamond ์Šค๋ ˆ๋“œ ๊ด€๋ฆฌ */
    	struct task_struct *kdamond;         /* ๋ชจ๋‹ˆํ„ฐ๋ง ์Šค๋ ˆ๋“œ */
    	struct mutex kdamond_lock;
    	/* DAMOS ํ˜ธ์ถœ ์ œ์–ด */
    	struct list_head call_controls;      /* damon_call ์š”์ฒญ ๋ชฉ๋ก */
    	/* ๋Œ€์ƒ ๋ฐ ์Šคํ‚ด */
    	struct list_head adaptive_targets;   /* damon_target ๋ชฉ๋ก */
    	struct list_head schemes;            /* damos ์Šคํ‚ด ๋ชฉ๋ก */
    	/* ์—ฐ์‚ฐ (๊ฐ€์ƒ/๋ฌผ๋ฆฌ ์ฃผ์†Œ๋ณ„ ๊ตฌํ˜„) */
    	struct damon_operations ops;
    };

    struct damos_access_pattern

    DAMOS๊ฐ€ ์˜์—ญ์— ๋™์ž‘์„ ์ ์šฉํ•˜๊ธฐ ์œ„ํ•œ ์ ‘๊ทผ ํŒจํ„ด ํ•„ํ„ฐ์ž…๋‹ˆ๋‹ค.

    /* include/linux/damon.h:468-475 */
    struct damos_access_pattern {
    	unsigned long min_sz_region;     /* ์ตœ์†Œ ์˜์—ญ ํฌ๊ธฐ */
    	unsigned long max_sz_region;     /* ์ตœ๋Œ€ ์˜์—ญ ํฌ๊ธฐ */
    	unsigned int min_nr_accesses;    /* ์ตœ์†Œ ์ ‘๊ทผ ๋นˆ๋„ */
    	unsigned int max_nr_accesses;    /* ์ตœ๋Œ€ ์ ‘๊ทผ ๋นˆ๋„ */
    	unsigned int min_age_region;     /* ์ตœ์†Œ ๋‚˜์ด */
    	unsigned long max_age_region;    /* ์ตœ๋Œ€ ๋‚˜์ด */
    };

    struct damos_watermarks

    ์‹œ์Šคํ…œ ์ƒํƒœ์— ๋”ฐ๋ฅธ DAMOS ์Šคํ‚ด์˜ ์ž๋™ ํ™œ์„ฑํ™”/๋น„ํ™œ์„ฑํ™”๋ฅผ ์ œ์–ดํ•ฉ๋‹ˆ๋‹ค.

    /* include/linux/damon.h:317-326 */
    struct damos_watermarks {
    	enum damos_wmark_metric metric;  /* ์›Œํ„ฐ๋งˆํฌ ๋ฉ”ํŠธ๋ฆญ (FREE_MEM_RATE ๋“ฑ) */
    	unsigned long interval;          /* ํ™•์ธ ์ฃผ๊ธฐ (๋งˆ์ดํฌ๋กœ์ดˆ) */
    	unsigned long high;              /* ์ƒํ•œ์„  โ€” ์ดˆ๊ณผ ์‹œ ๋น„ํ™œ์„ฑํ™” */
    	unsigned long mid;               /* ์ค‘๊ฐ„์„  โ€” ์ดํ•˜์ผ ๋•Œ ํ™œ์„ฑํ™” ๊ฐ€๋Šฅ */
    	unsigned long low;               /* ํ•˜ํ•œ์„  โ€” ๋ฏธ๋งŒ ์‹œ ๋น„ํ™œ์„ฑํ™” */
    	bool activated;                  /* ํ˜„์žฌ ํ™œ์„ฑํ™” ์ƒํƒœ */
    };

    struct damos_quota

    DAMOS ๋™์ž‘์˜ ๊ณต๊ฒฉ์„ฑ์„ ์ œ์–ดํ•˜๋Š” ์ž์› ์ œํ•œ์ž…๋‹ˆ๋‹ค.

    /* include/linux/damon.h:258-285 */
    struct damos_quota {
    	unsigned long reset_interval;    /* ์ถฉ์ „ ๋ฆฌ์…‹ ์ฃผ๊ธฐ (๋ฐ€๋ฆฌ์ดˆ) */
    	unsigned long ms;                /* ์ตœ๋Œ€ ์‚ฌ์šฉ ๊ฐ€๋Šฅ ์‹œ๊ฐ„ (๋ฐ€๋ฆฌ์ดˆ) */
    	unsigned long sz;                /* ์ตœ๋Œ€ ์ ์šฉ ๊ฐ€๋Šฅ ํฌ๊ธฐ (๋ฐ”์ดํŠธ) */
    	struct list_head goals;          /* ์ฟผํ„ฐ ์ž๋™ ์กฐ์ ˆ ๋ชฉํ‘œ ๋ชฉ๋ก */
    	unsigned long esz;               /* ์œ ํšจ ํฌ๊ธฐ ์ฟผํ„ฐ (๋‚ด๋ถ€ ๊ณ„์‚ฐ) */
    	unsigned int weight_sz;          /* ํฌ๊ธฐ ๊ฐ€์ค‘์น˜ (์šฐ์„ ์ˆœ์œ„) */
    	unsigned int weight_nr_accesses; /* ์ ‘๊ทผ ๋นˆ๋„ ๊ฐ€์ค‘์น˜ */
    	unsigned int weight_age;         /* ๋‚˜์ด ๊ฐ€์ค‘์น˜ */
    };

    struct damon_operations

    ๋ชจ๋‹ˆํ„ฐ๋ง ๋Œ€์ƒ ์ฃผ์†Œ ๊ณต๊ฐ„ ์ข…๋ฅ˜๋ณ„ ์—ฐ์‚ฐ ๊ตฌํ˜„์ฒด์ž…๋‹ˆ๋‹ค.

    /* include/linux/damon.h:643-656 */
    struct damon_operations {
    	enum damon_ops_id id;             /* ์—ฐ์‚ฐ ์„ธํŠธ ID (VADDR, FVADDR, PADDR) */
    	void (*init)(struct damon_ctx *context);                    /* ์ดˆ๊ธฐํ™” */
    	void (*update)(struct damon_ctx *context);                  /* ๋Œ€์ƒ ์—…๋ฐ์ดํŠธ */
    	void (*prepare_access_checks)(struct damon_ctx *context);  /* ์ ‘๊ทผ ๊ฒ€์‚ฌ ์ค€๋น„ */
    	unsigned int (*check_accesses)(struct damon_ctx *context);  /* ์ ‘๊ทผ ๊ฒ€์‚ฌ ์‹คํ–‰ */
    	int (*get_scheme_score)(struct damon_ctx *context,
    			struct damon_target *t, struct damon_region *r,
    			struct damos *scheme);
    	unsigned long (*apply_scheme)(struct damon_ctx *context,
    			struct damon_target *t, struct damon_region *r,
    			struct damos *scheme, unsigned long *sz_filter_passed);
    	bool (*target_valid)(struct damon_target *t);               /* ๋Œ€์ƒ ์œ ํšจ์„ฑ ๊ฒ€์‚ฌ */
    	void (*cleanup_target)(struct damon_target *t);             /* ๋Œ€์ƒ ์ •๋ฆฌ */
    };

    enum damos_action

    DAMOS๊ฐ€ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ๋Š” ๋™์ž‘ ๋ชฉ๋ก์ž…๋‹ˆ๋‹ค.

    /* include/linux/damon.h:135-147 */
    enum damos_action {
    	DAMOS_WILLNEED,     /* madvise(MADV_WILLNEED) โ€” ์‚ฌ์ „ ๋กœ๋“œ */
    	DAMOS_COLD,         /* madvise(MADV_COLD) โ€” ์ฝœ๋“œ ํ‘œ์‹œ */
    	DAMOS_PAGEOUT,      /* ํŽ˜์ด์ง€ ํšŒ์ˆ˜ (swap out) */
    	DAMOS_HUGEPAGE,     /* madvise(MADV_HUGEPAGE) โ€” THP ์œ ๋„ */
    	DAMOS_NOHUGEPAGE,   /* madvise(MADV_NOHUGEPAGE) โ€” THP ์–ต์ œ */
    	DAMOS_LRU_PRIO,     /* LRU ์šฐ์„ ์ˆœ์œ„ ์ƒํ–ฅ */
    	DAMOS_LRU_DEPRIO,   /* LRU ์šฐ์„ ์ˆœ์œ„ ํ•˜ํ–ฅ */
    	DAMOS_MIGRATE_HOT,  /* ํ•ซ ์˜์—ญ ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜ */
    	DAMOS_MIGRATE_COLD, /* ์ฝœ๋“œ ์˜์—ญ ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜ */
    	DAMOS_STAT,         /* ํ†ต๊ณ„๋งŒ ๊ธฐ๋ก (๋™์ž‘ ์—†์Œ) */
    	NR_DAMOS_ACTIONS,
    };

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

    kdamond_fn() โ€” ๋ชจ๋‹ˆํ„ฐ๋ง ๋ฐ๋ชฌ ๋ฉ”์ธ ๋ฃจํ”„

    kdamond ์Šค๋ ˆ๋“œ์˜ ํ•ต์‹ฌ ๋ฃจํ”„์ž…๋‹ˆ๋‹ค. ์ƒ˜ํ”Œ๋ง โ†’ ์ ‘๊ทผ ๊ฒ€์‚ฌ โ†’ ์˜์—ญ ๋ณ‘ํ•ฉ/๋ถ„ํ•  โ†’ DAMOS ์ ์šฉ์„ ๋ฐ˜๋ณตํ•ฉ๋‹ˆ๋‹ค.

    /* mm/damon/core.c:2746-2850 */
    static int kdamond_fn(void *data)
    {
    	struct damon_ctx *ctx = data;
    	/* ... ์ดˆ๊ธฐํ™” ... */
    
    	while (!kdamond_need_stop(ctx)) {
    		/* ์›Œํ„ฐ๋งˆํฌ ๊ธฐ๋ฐ˜ ํ™œ์„ฑํ™” ๋Œ€๊ธฐ */
    		if (kdamond_wait_activation(ctx))
    			break;
    
    		/* 1๋‹จ๊ณ„: ์ ‘๊ทผ ๊ฒ€์‚ฌ ์ค€๋น„ (PTE dirty/young ๋น„ํŠธ ๋ฆฌ์…‹ ๋“ฑ) */
    		if (ctx->ops.prepare_access_checks)
    			ctx->ops.prepare_access_checks(ctx);
    
    		/* ์ƒ˜ํ”Œ๋ง ๊ตฌ๊ฐ„๋งŒํผ ๋Œ€๊ธฐ */
    		kdamond_usleep(sample_interval);
    		ctx->passed_sample_intervals++;
    
    		/* 2๋‹จ๊ณ„: ์ ‘๊ทผ ๊ฒ€์‚ฌ (PTE dirty/young ๋น„ํŠธ ํ™•์ธ) */
    		if (ctx->ops.check_accesses)
    			max_nr_accesses = ctx->ops.check_accesses(ctx);
    
    		/* 3๋‹จ๊ณ„: ์ง‘๊ณ„ ๊ตฌ๊ฐ„ ๊ฒฝ๊ณผ ์‹œ ์ธ์ ‘ ์˜์—ญ ๋ณ‘ํ•ฉ */
    		if (ctx->passed_sample_intervals >= next_aggregation_sis)
    			kdamond_merge_regions(ctx, max_nr_accesses / 10, sz_limit);
    
    		/* 4๋‹จ๊ณ„: DAMOS ์Šคํ‚ด ์ ์šฉ */
    		kdamond_call(ctx, false);
    		if (!list_empty(&ctx->schemes))
    			kdamond_apply_schemes(ctx);
    
    		/* 5๋‹จ๊ณ„: ์ง‘๊ณ„ ๋ฆฌ์…‹ ๋ฐ ์˜์—ญ ๋ถ„ํ•  */
    		if (ctx->passed_sample_intervals >= next_aggregation_sis) {
    			kdamond_reset_aggregated(ctx);
    			kdamond_split_regions(ctx);
    		}
    
    		/* 6๋‹จ๊ณ„: ์—ฐ์‚ฐ ์—…๋ฐ์ดํŠธ (VMA ๋ณ€๊ฒฝ ๋ฐ˜์˜ ๋“ฑ) */
    		if (ctx->passed_sample_intervals >= next_ops_update_sis) {
    			if (ctx->ops.update)
    				ctx->ops.update(ctx);
    		}
    	}
    	/* ... ์ •๋ฆฌ ... */
    }

    ๋™์ž‘ ํ๋ฆ„ ์š”์•ฝ:

    1. prepare_access_checks: ์ƒ˜ํ”Œ ์ฃผ์†Œ์˜ PTE dirty/young ๋น„ํŠธ๋ฅผ ๋ฆฌ์…‹

    2. sample_interval๋งŒํผ ๋Œ€๊ธฐ

    3. check_accesses: ๋น„ํŠธ๊ฐ€ ์„ค์ •๋˜์—ˆ์œผ๋ฉด ์ ‘๊ทผ์œผ๋กœ ๊ธฐ๋ก

    4. aggr_interval ๊ฒฝ๊ณผ ์‹œ ์ธ์ ‘ ์˜์—ญ ๋ณ‘ํ•ฉ (์ ‘๊ทผ ๋นˆ๋„ ์œ ์‚ฌ)

    5. DAMOS ์Šคํ‚ด ์ ์šฉ (ํŒจํ„ด ๋งค์นญ + ํ•„ํ„ฐ + ์ฟผํ„ฐ ๊ฒ€์‚ฌ)

    6. ์ง‘๊ณ„ ๋ฆฌ์…‹ + ๋„ˆ๋ฌด ์ ์€ ์˜์—ญ์€ ๋ถ„ํ• 

    damon_do_apply_schemes() โ€” DAMOS ์Šคํ‚ด ์ ์šฉ

    ์˜์—ญ์— DAMOS ์Šคํ‚ด์˜ ๋™์ž‘์„ ์ ์šฉํ•˜๋Š” ํ•ต์‹ฌ ํ•จ์ˆ˜์ž…๋‹ˆ๋‹ค.

    /* mm/damon/core.c:1998-2030 */
    static void damon_do_apply_schemes(struct damon_ctx *c,
    				   struct damon_target *t,
    				   struct damon_region *r)
    {
    	struct damos *s;
    
    	damon_for_each_scheme(s, c) {
    		/* ์ ์šฉ ์‹œ์  ํ™•์ธ */
    		if (c->passed_sample_intervals < s->next_apply_sis)
    			continue;
    		/* ์›Œํ„ฐ๋งˆํฌ ํ™œ์„ฑํ™” ํ™•์ธ */
    		if (!s->wmarks.activated)
    			continue;
    		/* ์ฟผํ„ฐ ์ดˆ๊ณผ ํ™•์ธ */
    		if (quota->esz && quota->charged_sz >= quota->esz)
    			continue;
    		/* ์ด์ „์— ์ถฉ์ „๋œ ์˜์—ญ ์Šคํ‚ต */
    		if (damos_skip_charged_region(t, &r, s, c->min_region_sz))
    			continue;
    		/* ์ ‘๊ทผ ํŒจํ„ด ๋งค์นญ */
    		if (damos_valid_target(c, t, r, s))
    			damos_apply_scheme(c, t, r, s);
    	}
    }

    ํŒ๋‹จ ์กฐ๊ฑด ์ˆœ์„œ: ์‹œ์  โ†’ ์›Œํ„ฐ๋งˆํฌ โ†’ ์ฟผํ„ฐ โ†’ ์ถฉ์ „ ์ด๋ ฅ โ†’ ํŒจํ„ด ๋งค์นญ โ†’ ์ ์šฉ

    __damos_valid_target() โ€” ์ ‘๊ทผ ํŒจํ„ด ๋งค์นญ

    ์˜์—ญ์ด DAMOS ์Šคํ‚ด์˜ ์ ‘๊ทผ ํŒจํ„ด ์กฐ๊ฑด์„ ๋งŒ์กฑํ•˜๋Š”์ง€ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค.

    /* mm/damon/core.c:1678-1690 */
    static bool __damos_valid_target(struct damon_region *r, struct damos *s)
    {
    	unsigned long sz;
    	unsigned int nr_accesses = r->nr_accesses_bp / 10000;
    
    	sz = damon_sz_region(r);
    	return s->pattern.min_sz_region <= sz &&
    		sz <= s->pattern.max_sz_region &&
    		s->pattern.min_nr_accesses <= nr_accesses &&
    		nr_accesses <= s->pattern.max_nr_accesses &&
    		s->pattern.min_age_region <= r->age &&
    		r->age <= s->pattern.max_age_region;
    }

    kdamond_merge_regions() โ€” ์˜์—ญ ๋ณ‘ํ•ฉ

    ์ธ์ ‘ํ•œ ์˜์—ญ ์ค‘ ์ ‘๊ทผ ๋นˆ๋„๊ฐ€ ์œ ์‚ฌํ•œ ๊ฒƒ์„ ๋ณ‘ํ•ฉํ•˜์—ฌ ๋ชจ๋‹ˆํ„ฐ๋ง ์˜ค๋ฒ„ํ—ค๋“œ๋ฅผ ์ค„์ž…๋‹ˆ๋‹ค.

    /* mm/damon/core.c:2463-2481 */
    static void kdamond_merge_regions(struct damon_ctx *c, unsigned int threshold,
    				  unsigned long sz_limit)
    {
    	struct damon_target *t;
    	unsigned int nr_regions;
    	unsigned int max_thres;
    
    	max_thres = c->attrs.aggr_interval /
    		(c->attrs.sample_interval ? c->attrs.sample_interval : 1);
    	do {
    		nr_regions = 0;
    		damon_for_each_target(t, c) {
    			damon_merge_regions_of(t, threshold, sz_limit);
    			nr_regions += damon_nr_regions(t);
    		}
    		threshold = max(1, threshold * 2);
    	} while (nr_regions > c->attrs.max_nr_regions &&
    			threshold / 2 < max_thres);
    }

    ๋ณ‘ํ•ฉ ๊ธฐ์ค€: ์ธ์ ‘ + nr_accesses ์ฐจ์ด โ‰ค threshold + ํ•ฉ์‚ฐ ํฌ๊ธฐ โ‰ค sz_limit. ์˜์—ญ ์ˆ˜๊ฐ€ max_nr_regions๋ฅผ ์ดˆ๊ณผํ•˜๋ฉด threshold๋ฅผ 2๋ฐฐ์”ฉ ์˜ฌ๋ ค๊ฐ€๋ฉฐ ๋ฐ˜๋ณต ๋ณ‘ํ•ฉ.

    damos_wmark_wait_us() โ€” ์›Œํ„ฐ๋งˆํฌ ๊ธฐ๋ฐ˜ ํ™œ์„ฑํ™”

    ์‹œ์Šคํ…œ ๋ฉ”๋ชจ๋ฆฌ ์ƒํƒœ์— ๋”ฐ๋ผ DAMOS ์Šคํ‚ด์˜ ํ™œ์„ฑํ™”/๋น„ํ™œ์„ฑํ™”๋ฅผ ๊ฒฐ์ •ํ•ฉ๋‹ˆ๋‹ค.

    /* mm/damon/core.c:2615-2641 */
    static unsigned long damos_wmark_wait_us(struct damos *scheme)
    {
    	unsigned long metric;
    
    	if (damos_get_wmark_metric_value(scheme->wmarks.metric, &metric))
    		return 0;
    
    	/* high ์ดˆ๊ณผ ๋˜๋Š” low ๋ฏธ๋งŒ โ†’ ๋น„ํ™œ์„ฑํ™” */
    	if (metric > scheme->wmarks.high || scheme->wmarks.low > metric) {
    		scheme->wmarks.activated = false;
    		return scheme->wmarks.interval;
    	}
    	/* mid~high ๊ตฌ๊ฐ„์ด๊ณ  ๋น„ํ™œ์„ฑ ์ƒํƒœ โ†’ ๋Œ€๊ธฐ */
    	if ((scheme->wmarks.high >= metric && metric >= scheme->wmarks.mid) &&
    			!scheme->wmarks.activated)
    		return scheme->wmarks.interval;
    
    	scheme->wmarks.activated = true;
    	return 0;
    }

    ์›Œํ„ฐ๋งˆํฌ ์ƒํƒœ ๋‹ค์ด์–ด๊ทธ๋žจ:

    metric > high  โ†’  ๋น„ํ™œ์„ฑํ™” (๋ฉ”๋ชจ๋ฆฌ ์—ฌ์œ )
    mid โ‰ค metric โ‰ค high  โ†’  ๋น„ํ™œ์„ฑ ์ƒํƒœ ์œ ์ง€ (์ค‘๊ฐ„ ์˜์—ญ)
    low โ‰ค metric โ‰ค mid  โ†’  ํ™œ์„ฑํ™” (๋ฉ”๋ชจ๋ฆฌ ์••๋ฐ• ์‹œ์ž‘)
    metric < low  โ†’  ๋น„ํ™œ์„ฑํ™” (๋ฉ”๋ชจ๋ฆฌ ๊ทน์‹ฌํ•œ ๋ถ€์กฑ โ†’ ๋‹ค๋ฅธ ๋ฉ”์ปค๋‹ˆ์ฆ˜ ๋™์ž‘)

    damon_reclaim_new_scheme() โ€” ํšŒ์ˆ˜ ์Šคํ‚ด ๊ตฌ์„ฑ

    DAMON_RECLAIM ๋ชจ๋“ˆ์ด ์‚ฌ์šฉํ•˜๋Š” ๊ธฐ๋ณธ ํšŒ์ˆ˜ ์Šคํ‚ด์„ ๊ตฌ์„ฑํ•ฉ๋‹ˆ๋‹ค.

    /* mm/damon/reclaim.c:163-189 */
    static struct damos *damon_reclaim_new_scheme(void)
    {
    	struct damos_access_pattern pattern = {
    		.min_sz_region = PAGE_SIZE,         /* ์ตœ์†Œ ์˜์—ญ: ํŽ˜์ด์ง€ ํฌ๊ธฐ */
    		.max_sz_region = ULONG_MAX,         /* ์ตœ๋Œ€ ์˜์—ญ: ์ œํ•œ ์—†์Œ */
    		.min_nr_accesses = 0,               /* ์ ‘๊ทผ ์—†์Œ */
    		.max_nr_accesses = 0,               /* ์ ‘๊ทผ ์—†์Œ */
    		.min_age_region = min_age /         /* ์ตœ์†Œ ๋‚˜์ด (์ง‘๊ณ„ ๊ตฌ๊ฐ„ ํ™˜์‚ฐ) */
    			damon_reclaim_mon_attrs.aggr_interval,
    		.max_age_region = UINT_MAX,
    	};
    
    	return damon_new_scheme(
    			&pattern,
    			DAMOS_PAGEOUT,                 /* ์ฝœ๋“œ ํŽ˜์ด์ง€๋ฅผ ์Šค์™‘์•„์›ƒ */
    			0,                             /* ๋งค ์ง‘๊ณ„ ๊ตฌ๊ฐ„๋งˆ๋‹ค ์ ์šฉ */
    			&damon_reclaim_quota,          /* ์ฟผํ„ฐ ์ ์šฉ */
    			&damon_reclaim_wmarks,         /* ์›Œํ„ฐ๋งˆํฌ ์ ์šฉ */
    			NUMA_NO_NODE);
    }

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

    DAMON kdamond ํ˜ธ์ถœ ํ๋ฆ„
    kdamond_fn() [kdamond ์Šค๋ ˆ๋“œ ๋ฉ”์ธ ๋ฃจํ”„]
    โ”œโ”€โ”€ kdamond_wait_activation()
    โ”‚   โ””โ”€โ”€ damos_wmark_wait_us() โ”€โ”€ ์›Œํ„ฐ๋งˆํฌ ๊ธฐ๋ฐ˜ ๋Œ€๊ธฐ
    โ”œโ”€โ”€ ops.prepare_access_checks()
    โ”‚   โ”œโ”€โ”€ [vaddr] damon_va_prepare_access_checks()
    โ”‚   โ”‚   โ””โ”€โ”€ damon_ptep_mkold() โ”€โ”€ PTE young ๋น„ํŠธ ๋ฆฌ์…‹
    โ”‚   โ””โ”€โ”€ [paddr] damon_pa_prepare_access_checks()
    โ”‚       โ””โ”€โ”€ damon_pa_mkold() โ”€โ”€ ํŽ˜์ด์ง€ young ๋น„ํŠธ ๋ฆฌ์…‹
    โ”œโ”€โ”€ ops.check_accesses()
    โ”‚   โ”œโ”€โ”€ [vaddr] damon_va_check_accesses()
    โ”‚   โ”‚   โ””โ”€โ”€ damon_va_young() โ”€โ”€ PTE dirty/young ํ™•์ธ
    โ”‚   โ””โ”€โ”€ [paddr] damon_pa_check_accesses()
    โ”‚       โ””โ”€โ”€ damon_pa_young() โ”€โ”€ ํŽ˜์ด์ง€ young ํ™•์ธ
    โ”œโ”€โ”€ kdamond_merge_regions()
    โ”‚   โ””โ”€โ”€ damon_merge_regions_of()
    โ”‚       โ””โ”€โ”€ damon_merge_two_regions() โ”€โ”€ ์ธ์ ‘ ์˜์—ญ ๋ณ‘ํ•ฉ
    โ”œโ”€โ”€ kdamond_call() โ”€โ”€ ์™ธ๋ถ€ ์š”์ฒญ ์ฒ˜๋ฆฌ (damon_call)
    โ”œโ”€โ”€ kdamond_apply_schemes()
    โ”‚   โ”œโ”€โ”€ damos_adjust_quota() โ”€โ”€ ์ฟผํ„ฐ ์œ ํšจ ํฌ๊ธฐ ๊ณ„์‚ฐ
    โ”‚   โ””โ”€โ”€ damon_do_apply_schemes()
    โ”‚       โ”œโ”€โ”€ damos_valid_target() โ”€โ”€ ํŒจํ„ด ๋งค์นญ
    โ”‚       โ”‚   โ””โ”€โ”€ __damos_valid_target() โ”€โ”€ ํฌ๊ธฐ/๋นˆ๋„/๋‚˜์ด ์กฐ๊ฑด
    โ”‚       โ””โ”€โ”€ damos_apply_scheme()
    โ”‚           โ”œโ”€โ”€ damos_core_filter_out() โ”€โ”€ ์ฝ”์–ด ํ•„ํ„ฐ ์ ์šฉ
    โ”‚           โ”œโ”€โ”€ ops.apply_scheme() โ”€โ”€ ์‹ค์ œ ๋™์ž‘ ์ ์šฉ
    โ”‚           โ”‚   โ”œโ”€โ”€ [paddr] damon_pa_apply_scheme()
    โ”‚           โ”‚   โ”‚   โ””โ”€โ”€ damos_pa_filter_out() โ”€โ”€ ํ•„ํ„ฐ ํ™•์ธ
    โ”‚           โ”‚   โ””โ”€โ”€ [vaddr] damon_va_apply_scheme()
    โ”‚           โ””โ”€โ”€ damos_update_stat() โ”€โ”€ ํ†ต๊ณ„ ์—…๋ฐ์ดํŠธ
    โ”œโ”€โ”€ kdamond_reset_aggregated() โ”€โ”€ ์ง‘๊ณ„ ๋ฆฌ์…‹
    โ””โ”€โ”€ kdamond_split_regions() โ”€โ”€ ์˜์—ญ ๋ถ„ํ•  (์ •ํ™•๋„ ํ–ฅ์ƒ)

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

    ๋ชจ๋‹ˆํ„ฐ๋ง ์—ฐ์‚ฐ ์œ ํ˜• ๋น„๊ต

    ํ•ญ๋ชฉDAMON_OPS_VADDRDAMON_OPS_PADDR
    ๋Œ€์ƒํ”„๋กœ์„ธ์Šค ๊ฐ€์ƒ ์ฃผ์†Œ ๊ณต๊ฐ„๋ฌผ๋ฆฌ ์ฃผ์†Œ ๊ณต๊ฐ„ ์ „์ฒด
    ์‹๋ณ„์ž`target->pid``target->pid = NULL`
    ์ ‘๊ทผ ๊ฒ€์‚ฌPTE young/dirty ๋น„ํŠธํŽ˜์ด์ง€ young ๋น„ํŠธ
    ์˜์—ญ ์ดˆ๊ธฐํ™”VMA ๊ธฐ๋ฐ˜ 3์˜์—ญ ๋ถ„ํ• ์ „์ฒด ๋ฌผ๋ฆฌ ๋ฉ”๋ชจ๋ฆฌ 1์˜์—ญ
    ํ•„ํ„ฐ ์ง€์›ADDR, TARGETANON, MEMCG, ADDR, TARGET, YOUNG, ACTIVE, HUGEPAGE_SIZE, UNMAPPED
    ๋Œ€ํ‘œ ์‚ฌ์šฉ์žํ”„๋กœ์„ธ์Šค๋ณ„ ํ”„๋กœํŒŒ์ผ๋งDAMON_RECLAIM, DAMON_LRU_SORT
    ๊ตฌํ˜„ ํŒŒ์ผ`mm/damon/vaddr.c``mm/damon/paddr.c`

    DAMOS ๋™์ž‘ ๋น„๊ต

    ๋™์ž‘์„ค๋ช…์‚ฌ์šฉ ์˜ˆ
    `DAMOS_PAGEOUT`์ฝœ๋“œ ํŽ˜์ด์ง€๋ฅผ ์Šค์™‘์œผ๋กœ ํšŒ์ˆ˜DAMON_RECLAIM
    `DAMOS_LRU_PRIO`LRU ๋ฆฌ์ŠคํŠธ์—์„œ ์šฐ์„ ์ˆœ์œ„ ์ƒํ–ฅํ•ซ ํŽ˜์ด์ง€ ๋ณดํ˜ธ
    `DAMOS_LRU_DEPRIO`LRU ๋ฆฌ์ŠคํŠธ์—์„œ ์šฐ์„ ์ˆœ์œ„ ํ•˜ํ–ฅDAMON_LRU_SORT
    `DAMOS_COLD``madvise(MADV_COLD)` ํ˜ธ์ถœ์ฝœ๋“œ ํŽ˜์ด์ง€ ํ‘œ์‹œ
    `DAMOS_HUGEPAGE``madvise(MADV_HUGEPAGE)` ํ˜ธ์ถœTHP ์œ ๋„
    `DAMOS_MIGRATE_HOT`ํ•ซ ์˜์—ญ ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜NUMA ํ‹ฐ์–ด๋ง
    `DAMOS_STAT`ํ†ต๊ณ„๋งŒ ๊ธฐ๋กํ”„๋กœํŒŒ์ผ๋ง

    ์›Œํ„ฐ๋งˆํฌ ์ƒํƒœ๋ณ„ ๋™์ž‘

    ๋ฉ”๋ชจ๋ฆฌ ์ƒํƒœmetric ๋ฒ”์œ„์Šคํ‚ด ๋™์ž‘
    ๋ฉ”๋ชจ๋ฆฌ ์—ฌ์œ `metric > high`๋น„ํ™œ์„ฑํ™”
    ์ค‘๊ฐ„ (์ด์ „ ๋น„ํ™œ์„ฑ)`mid โ‰ค metric โ‰ค high`์œ ์ง€ (๋น„ํ™œ์„ฑ)
    ์ค‘๊ฐ„ (์ด์ „ ํ™œ์„ฑ)`low โ‰ค metric โ‰ค mid`ํ™œ์„ฑํ™”
    ๋ฉ”๋ชจ๋ฆฌ ๋ถ€์กฑ`metric < low`๋น„ํ™œ์„ฑํ™”

    ์ฟผํ„ฐ ์ž๋™ ์กฐ์ ˆ ๋ฉ”ํŠธ๋ฆญ ๋น„๊ต

    ๋ฉ”ํŠธ๋ฆญ์˜๋ฏธ๋Œ€์ƒ
    `DAMOS_QUOTA_USER_INPUT`์‚ฌ์šฉ์ž ์ง€์ •๊ฐ’์ปค์Šคํ…€ ํ”ผ๋“œ๋ฐฑ
    `DAMOS_QUOTA_SOME_MEM_PSI_US`์‹œ์Šคํ…œ ์ˆ˜์ค€ ์ผ๋ถ€ ๋ฉ”๋ชจ๋ฆฌ PSI (๋งˆ์ดํฌ๋กœ์ดˆ)์ „์ฒด ์‹œ์Šคํ…œ
    `DAMOS_QUOTA_NODE_MEM_USED_BP`๋…ธ๋“œ๋ณ„ ๋ฉ”๋ชจ๋ฆฌ ์‚ฌ์šฉ ๋น„์œจํŠน์ • NUMA ๋…ธ๋“œ
    `DAMOS_QUOTA_NODE_MEM_FREE_BP`๋…ธ๋“œ๋ณ„ ๋ฉ”๋ชจ๋ฆฌ ์—ฌ์œ  ๋น„์œจํŠน์ • NUMA ๋…ธ๋“œ
    `DAMOS_QUOTA_NODE_MEMCG_USED_BP`์ปจํ…Œ์ด๋„ˆ๋ณ„ ๋ฉ”๋ชจ๋ฆฌ ์‚ฌ์šฉ ๋น„์œจํŠน์ • memcg
    `DAMOS_QUOTA_ACTIVE_MEM_BP`ํ™œ์„ฑ LRU ๋ฉ”๋ชจ๋ฆฌ ๋น„์œจLRU ๋ฐธ๋Ÿฐ์Šค

    ์šด์˜ ๋ฐฉ์‹ ๋น„๊ต

    ํ•ญ๋ชฉ`DAMON_RECLAIM``DAMON_LRU_SORT`์ง์ ‘ DAMOS
    ๋ชฉ์ ์ฝœ๋“œ ํŽ˜์ด์ง€๋ฅผ ์ค„์—ฌ ํšŒ์ˆ˜ ์••๋ฐ• ์™„ํ™”LRU ์šฐ์„ ์ˆœ์œ„๋ฅผ ์žฌ๋ฐฐ์น˜์›Œํฌ๋กœ๋“œ์— ๋งž์ถ˜ ์ •์ฑ… ์ž๋™ํ™”
    ๋Œ€ํ‘œ ์•ก์…˜`DAMOS_PAGEOUT``DAMOS_LRU_DEPRIO` / `DAMOS_LRU_PRIO``DAMOS_MIGRATE_HOT/COLD`, `DAMOS_HUGEPAGE` ๋“ฑ
    ์„ค์ • ์œ„์น˜`/sys/module/damon_reclaim/parameters/*``/sys/module/damon_lru_sort/parameters/*``/sys/kernel/mm/damon/admin/kdamonds/*`
    ํ•จ๊ป˜ ๋ณด๋Š” ์ง€ํ‘œPSI, `pgscan`, `pgsteal`LRU ๊ท ํ˜•, ์žฌ์ฐธ์กฐ์œจquota, watermarks, stat

    ๊ด€๋ จ ๋ฌธ์„œ

  • ๋ฉ”๋ชจ๋ฆฌ ๊ด€๋ฆฌ ๊ฐœ์š”
  • NUMA
  • ํŽ˜์ด์ง€ ํšŒ์ˆ˜ (vmscan)
  • ํŽ˜์ด์ง€ Migration
  • ๋ฉ”๋ชจ๋ฆฌ Cgroup
  • MGLRU ๊ฐœ์„ ์‚ฌํ•ญ
  • ์ฐธ๊ณ  ์ž๋ฃŒ

  • DAMON ๊ณต์‹ ๋ฌธ์„œ: Documentation/mm/damon/
  • damo ๋„๊ตฌ: https://github.com/awslabs/damo
  • SeongJae Park ๋…ผ๋ฌธ: "DAMON: A Framework for Efficient Data Access Monitoring"