ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

Linux 内核 DAMON_STAT 模块深度解析:基于 DAMON 的物理内存访问监控统计

Linux 内核 DAMON_STAT 模块深度解析:基于 DAMON 的物理内存访问监控统计 Linux 内核 DAMON_STAT 模块深度解析基于 DAMON 的物理内存访问监控统计【免费下载链接】linuxLinux kernel source tree项目地址: https://gitcode.com/GitHub_Trending/li/linuxDAMON_STATData Access Monitoring Results Stat是 Linux 内核中基于 DAMON 框架的静态内核模块它以极低开销监控系统整个物理内存的访问模式并对外暴露内存空闲时间百分位数与估计内存带宽两类简化统计指标。本文以内核源码仓库中的 stat.rst 文档为主体结合 stat.c、Kconfig 等源码实现系统讲解 DAMON_STAT 的启用方法、全部模块参数、自动调优机制与底层工作原理帮助读者掌握这一轻量级内存访问监控工具的配置与解读方法。DAMON_STAT 是什么DAMON_STAT 是 Linux 内核提供的一个开箱即用的访问模式监控模块。它不需要用户通过 sysfs 接口手工配置监控上下文而是由模块内部自建 DAMON 上下文监控整个系统的物理内存从系统 RAM 起始到结束的完整地址范围并将监控结果转换为两类易于理解的统计指标空闲时间百分位数memory_idle_ms_percentiles系统内存中每个字节未被访问的时长毫秒的分布情况估计内存带宽estimated_memory_bandwidth系统内存访问强度折算成的字节/秒估计值。从源码结构看该模块属于 DAMON 的三个特殊用途模块special-purpose modules之一与 DAMON_RECLAIMreclaim.c、DAMON_LRU_SORTlru_sort.c并列定位是最简单的接入方式——编译进内核并启用后即可读取监控结果无需任何用户态编程。监控精度与开销基于自动调优的平衡DAMON_STAT 的核心设计目标是高精度与低开销兼得其手段是使用 DAMON 的监控间隔自动调优monitoring intervals auto-tuning机制而不是固定采样参数。根据 stat.rst 文档与 stat.c 中的初始化代码模块在构建 DAMON 上下文时设置了如下目标attrs (struct damon_attrs) { .sample_interval 5 * USEC_PER_MSEC, /* 初始采样间隔 5ms */ .aggr_interval 100 * USEC_PER_MSEC, /* 初始聚合间隔 100ms */ .ops_update_interval 60 * USEC_PER_MSEC * MSEC_PER_SEC, /* 60s */ .min_nr_regions 10, .max_nr_regions 1000, }; /* auto-tune sampling and aggregation interval aiming 4% DAMON-observed * accesses ratio, keeping sampling interval in [5ms, 10s] range. */ attrs.intervals_goal (struct damon_intervals_goal) { .access_bp 400, .aggrs 3, .min_sample_us 5000, .max_sample_us 10000000, };各关键参数含义如下参数值含义access_bp400即 4%期望每个快照捕获的 DAMON 可观测访问事件比例aggrs3以 3 次聚合为窗口评估实际访问事件比例min_sample_us50005ms采样间隔下限max_sample_us1000000010s采样间隔上限min_nr_regions/max_nr_regions10 / 1000监控区域数量的自适应上下限自动调优的具体逻辑记录在 Documentation/mm/damon/design.rstDAMON 以字节粒度统计观测到的访问事件区域大小 ×nr_accesses与理论最大访问事件数聚合间隔/采样间隔比较按实际比例与目标比例4%的差距成比例地同步调整采样间隔与聚合间隔。文档特别指出4% 的目标来源于帕累托原则80/20 法则的两次应用——假设捕获 4%20%×20%的观测访问事件即可反映约 64%80%×80%的真实访问事件。从源码实现看DAMON_STAT 的统计刷新还有一个 5 秒的最小刷新周期限制见 stat.c 的damon_stat_damon_call_fn/* avoid unnecessarily frequent stat update */ if (time_before_eq(jiffies, damon_stat_last_refresh_jiffies secs_to_jiffies(5))) return 0; damon_stat_last_refresh_jiffies jiffies;文档指出在若干生产服务器系统上该模块仅消耗0.x% 的单 CPU 时间即可捕获合理质量的访问模式。调优后的实际聚合间隔可通过aggr_interval_us参数实时读取。构建与启用Kconfig 配置DAMON_STAT 是静态内核模块即只能编译进内核y不支持m动态加载。要使用该功能需要确保内核以CONFIG_DAMON_STATy构建。在 mm/damon/Kconfig 中定义了相关配置项config DAMON_STAT bool Build data access monitoring stat (DAMON_STAT) depends on DAMON_PADDR help This builds the DAMON-based access monitoring statistics subsystem. It runs DAMON and expose access monitoring results in simple stat metrics. config DAMON_STAT_ENABLED_DEFAULT bool Enable DAMON_STAT by default depends on DAMON_STAT default DAMON_STAT help Whether to enable DAMON_STAT by default. Users can disable it in boot or runtime using its enabled parameter.要点CONFIG_DAMON_STAT依赖DAMON_PADDR物理地址空间监控操作后者又依赖DAMON与MMU设置CONFIG_DAMON_STAT_ENABLED_DEFAULTy可让模块在构建时默认启用内核编译时mm/damon/Makefile 中的obj-$(CONFIG_DAMON_STAT) modules-common.o stat.o会将stat.c与公共辅助代码modules-common.c一起编入内核镜像。构建并启用后管理员可在启动阶段内核命令行或运行时通过模块参数控制模块行为并读取监控结果。模块参数详解DAMON_STAT 通过 5 个模块参数对外提供控制与读取接口其 sysfs 路径为/sys/module/damon_stat/parameters/源码 stat.c 中通过MODULE_PARAM_PREFIX damon_stat.指定了模块参数前缀。下表汇总了全部参数参数类型权限读写性用途enabledbool0600读写启用/禁用 DAMON_STATaggr_interval_usulong0400只读当前自动调优后的聚合间隔微秒estimated_memory_bandwidthulong0400只读估计内存带宽字节/秒memory_idle_ms_percentileslong[101]0400只读内存空闲时间百分位数毫秒kdamond_pidint0400只读DAMON 工作线程 PID未运行时为 -1enabled启停开关enabled是唯一可写的参数接受Y/N# 运行时启用 echo Y /sys/module/damon_stat/parameters/enabled # 运行时禁用 echo N /sys/module/damon_stat/parameters/enabled其默认值由CONFIG_DAMON_STAT_ENABLED_DEFAULT决定反映在源码中stat.cstatic bool enabled __read_mostly IS_ENABLED( CONFIG_DAMON_STAT_ENABLED_DEFAULT); module_param_cb(enabled, enabled_param_ops, NULL, 0600);在启动阶段enabled参数可通过内核命令行传入源码 stat.c 的damon_stat_enabled_store对命令行解析阶段此时 DAMON 尚未初始化做了专门处理交由damon_stat_init在模块初始化时真正启动。读取该参数时返回的是 DAMON 上下文的实际运行状态Y或N而非配置值本身。重要限制DAMON_STATdamon_stat不能与其它 DAMON 专用模块同时运行。内核设计文档 Documentation/mm/damon/design.rst 明确说明stat、reclaim、lru_sort 三个模块当前以排他方式运行若其中一个已运行其它模块的启动请求将返回-EBUSY。aggr_interval_us自动调优后的聚合间隔该只读参数暴露 DAMON 实例当前正在使用的聚合间隔微秒。由于间隔由自动调优机制动态调整该值会随系统访问模式实时变化stat.c、stat.c 中每次统计刷新时同步更新。estimated_memory_bandwidth估计内存带宽该只读参数给出系统内存带宽消耗的估计值字节/秒。其计算逻辑位于 stat.c 的damon_stat_set_estimated_memory_bandwidthstatic void damon_stat_set_estimated_memory_bandwidth(struct damon_ctx *c) { struct damon_target *t; struct damon_region *r; unsigned long access_bytes 0; damon_for_each_target(t, c) { damon_for_each_region(r, t) access_bytes (r-ar.end - r-ar.start) * r-nr_accesses; } estimated_memory_bandwidth access_bytes * USEC_PER_MSEC * MSEC_PER_SEC / c-attrs.aggr_interval; }即对每个监控区域将区域大小字节乘以该聚合周期内的访问次数nr_accesses累加得到访问字节数再除以聚合间隔折算为每秒字节数。由于 DAMON 本质上是采样机制该指标只是访问强度的估计而非精确的内存带宽计量。memory_idle_ms_percentiles空闲时间百分位数该只读参数返回101 个以逗号分隔的毫秒值分别对应 0 到 100 的百分位0th、1st、2nd、…、99th、100th的空闲时间。空闲时间的定义在 stat.c 的damon_stat_idletime中实现static int damon_stat_idletime(const struct damon_region *r) { if (r-nr_accesses) return -1 * (r-age 1); return r-age 1; }若区域访问频率nr_accesses大于 0空闲时间取负数-1 × (当前访问频率保持时长 1)负号用于排序区分活跃与空闲区域若区域访问频率为 0空闲时间为区域保持零访问的时长age 1。百分位计算过程stat.c先将所有区域按空闲时间排序再按字节累计比例映射到各百分位最后乘以聚合间隔并换算为毫秒。因此该指标本质上是系统内存中每个字节未被访问时长的分布可用于识别冷内存的比例、评估回收/迁移收益等场景。kdamond_pidDAMON 工作线程 PID当 DAMON_STAT 启用时该只读参数为 DAMON 后台线程kdamond的 PID禁用时返回-1stat.c。由于该参数是只读的内核命令行写入时会被静默忽略见damon_stat_kdamond_pid_store。底层运行机制从参数到监控结果综合 stat.c 源码DAMON_STAT 的完整运行链路如下构建上下文damon_stat_build_ctxstat.c创建 DAMON 上下文选择DAMON_OPS_PADDR物理地址监控操作依赖DAMON_PADDR配置创建单一 target并通过damon_set_region_system_rams_default将监控范围设为系统全部物理内存从系统 RAM 起始地址到结束启动监控damon_stat_startstat.c调用damon_start启动 kdamond 线程并注册一个重复回调damon_call用于周期刷新统计周期统计damon_stat_damon_call_fnstat.c每 5 秒最小刷新间隔更新一次aggr_interval_us、estimated_memory_bandwidth与memory_idle_ms_percentiles读取结果管理员通过/sys/module/damon_stat/parameters/下的只读参数获取最新快照。模块初始化damon_stat_initstat.c会检查 DAMON 是否已初始化并根据enabled参数决定是否立即启动监控若启动失败则回退enabled为 false。此外modules-common.c 提供了damon_modules_new_paddr_ctx_target等公共辅助函数供 stat、reclaim、lru_sort 三个模块共享创建物理地址 DAMON 上下文的样板代码。典型使用场景与注意事项适用场景从文档与源码定位推断快速了解系统整机内存的访问冷热分布无需编写任何用户态代码作为性能诊断的第一步判断内存是否大量处于空闲状态、是否存在明显的内存访问带宽瓶颈为后续启用 DAMON_RECLAIM内存回收或 DAMON_LRU_SORTLRU 列表排序等主动式内存管理提供决策依据。注意事项模块为静态编译CONFIG_DAMON_STATy无法动态加载需在构建内核时包含与 reclaim、lru_sort 模块互斥同一时刻只能运行其中一个启用前需确认其它 DAMON 专用模块未在运行estimated_memory_bandwidth与memory_idle_ms_percentiles均基于 DAMON 采样结果推算属于估计/统计性质指标不代表精确测量值统计值每 5 秒才刷新一次读取参数前应预留足够的聚合周期让自动调优收敛。通过 stat.rst 文档、stat.c 实现与 design.rst 设计文档三者的对照阅读可以完整把握 DAMON_STAT 从编译配置、运行时参数到内部计算逻辑的全貌为内核内存子系统观测与调优提供一套轻量、可落地的方案。【免费下载链接】linuxLinux kernel source tree项目地址: https://gitcode.com/GitHub_Trending/li/linux创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进