Linux kernel damon实现

一:简介

DAMON :Data access monitor。是Linux kernel新提供的内存访问监控框架。它的核心思想是使用一种采样(sampling)技术来确定哪些内存是正在使用的,哪些是正在闲置的。进程的虚拟地址空间或者全局物理地址被分成不同的区域(region),划分出来的区域的 size 并不相同,而是根据活跃情况来划分的。接下来随着时间的推移会对最繁忙的区域进行更细地划分,从而进行更精细的监控。在每个区域内会随机选择一个 page 进行监控,它的活跃程度就被认为是代表了整个区域的情况。在需要的时候,DAMON 会以直方图(histogram)的形式生成一份报告来报告每个内存区域的繁忙程度。最后可以根据设置的条件对内存进行回收。

二:整体实现

采样周期,sample_interval:指每次数据采集的间隔。

统计周期,aggregations_interval:指采样一段时间后,汇总数据的周期。

Damon监控进程运行的函数是kdamond_fn,也是实现监控架构的主要逻辑。

数据结构关系:

三:Damon实现细节

1:prepare access check

采样之前需要执行prepare_access_checks,遍历ctx中的target包含的region,为每个region确定采样地址,然后调用mkold函数,去掉page中的标签。

static void __damon_va_prepare_access_check(struct damon_ctx *ctx,
                        struct mm_struct *mm, struct damon_region *r)
{
        r->sampling_addr = damon_rand(r->ar.start, r->ar.end);//随机获region中的地址
        damon_va_mkold(mm, r->sampling_addr);//mkold函数去掉标签
}

虚拟地址的mkold函数实现: 物理地址类似 

void damon_ptep_mkold(pte_t *pte, struct mm_struct *mm, unsigned long addr)
{
        bool referenced = false;
        struct page *page = damon_get_page(pte_pfn(*pte));
        if (!page)
                return;
        if (pte_young(*pte)) {
                referenced = true;
                *pte = pte_mkold(*pte);//去掉pte的_PAGE_ACCESSED flag
        }
#ifdef CONFIG_MMU_NOTIFIER
        if (mmu_notifier_clear_young(mm, addr, addr + PAGE_SIZE))
                referenced = true;
#endif /* CONFIG_MMU_NOTIFIER */

        if (referenced)
                set_page_young(page);//如果pte刚被访问就设置young flag
        set_page_idle(page); //mkold主要设置page idle.
        put_page(page);
}

2:check access

采样期间,检测sample address是否被访问。

static void __damon_va_check_access(struct damon_ctx *ctx,
                               struct mm_struct *mm, struct damon_region *r)
{
        /*避免重复检查*/
        if (mm == last_mm && (ALIGN_DOWN(last_addr, last_page_sz) ==
                                ALIGN_DOWN(r->sampling_addr, last_page_sz))) {
                if (last_accessed)
                        r->nr_accesses++;
                return;
        }
        //damon_va_young函数确定这个地址是否被访问过。
        last_accessed = damon_va_young(mm, r->sampling_addr, &last_page_sz);
        if (last_accessed)
                r->nr_accesses++;
        last_mm = mm;
        last_addr = r->sampling_addr;
}

测试page(va,pa都一样)是否被访问主要是通过如下逻辑代码:

if (pte_young(*pte) || !page_is_idle(page) ||
                        mmu_notifier_test_young(walk->mm, addr)) {
                *priv->page_sz = PAGE_SIZE;
                priv->young = true;  //代表page被访问过
        }
主要根据页表访问会设置pte为young来判断。

3:apply schemes

统计周期结束后,对满足采样条件的区间执行对应的策略。

scheme->action由用户指定对应的策略,比如换出内存。最后调用madvise相关的函数实现。

Reclaim模块的话是直接调用shrink_page_list回收物理内存。如下代码是虚拟内存相关。

static int damon_va_apply_scheme(struct damon_ctx *ctx, struct damon_target *t,
                struct damon_region *r, struct damos *scheme)
{
        int madv_action;

        switch (scheme->action) {
        case DAMOS_WILLNEED:
                madv_action = MADV_WILLNEED;
                break;
        case DAMOS_COLD:
                madv_action = MADV_COLD;
                break;
        case DAMOS_PAGEOUT:
                madv_action = MADV_PAGEOUT;
                break;
        case DAMOS_HUGEPAGE:
                madv_action = MADV_HUGEPAGE;
                break;
        case DAMOS_NOHUGEPAGE:
                madv_action = MADV_NOHUGEPAGE;
                break;
        case DAMOS_STAT:
                return 0;
        default:
                pr_warn("Wrong action %d\n", scheme->action);
                return -EINVAL;
        }

        return damos_madvise(t, r, madv_action);
}

4:split region

每次统计周期结束后,会对region进行调整。主要根据用户设置参数来调节。比如min_nr_regions。同时会合并相邻的访问次数相同的区间,为了降低负载。

四:damon相关的配置参数

aggr_interval:统计间隔

sample_interval:采样间隔

wmarks_high:free memory in bytes per thousand bytes is higher than this, DAMON_RECLAIM becomes inactive,

wmarks_mid:free memory in bytes per thousand bytes is between this and the low watermark, DAMON_RECLAIM becomes active.

wmarks_low: lower than this, DAMON_RECLAIM becomes inactive,

monitor_region_start/end:监控的起始地址,进程会自动获取。

max/min_nr_regions:最大,最小的region数量,现在region的数目。

min_age:最小的年龄。age是个有意思的度量,代表访问次数变化小于阈值的情况下,经历了多少次统计周期。阈值设置为region的max_nr_accesses / 10。 可以简单理解为相同的访问次数下,经历了多少个统计周期。访问变化后age清零。

quota前缀用于限制damon。

五:Damon相关使用

damon参考:

Detailed Usages — The Linux Kernel documentation

damon_reclaim参考:

DAMON-based Reclamation — The Linux Kernel documentation

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值