详细用法

DAMON 为不同的用户提供以下接口。

  • DAMON 用户空间工具。这个适用于希望拥有一个易于使用的人性化界面的特权用户(例如系统管理员)。使用此工具,用户可以以人性化的方式使用 DAMON 的主要功能。但是,它可能没有针对特殊情况进行高度调整。有关更多详细信息,请参阅其 使用文档

  • sysfs 接口。这个适用于希望更优化地使用 DAMON 的特权用户空间程序员。使用此接口,用户可以通过读取和写入特殊的 sysfs 文件来使用 DAMON 的主要功能。因此,您可以编写和使用您个性化的 DAMON sysfs 包装程序,该程序可以代替您读取/写入 sysfs 文件。DAMON 用户空间工具是此类程序的一个示例。

  • 内核空间编程接口。这个适用于内核空间程序员。使用此接口,用户可以通过编写内核空间 DAMON 应用程序来最灵活高效地利用 DAMON 的每一项功能。您甚至可以扩展 DAMON 以支持各种地址空间。有关详细信息,请参阅接口 文档

  • debugfs 接口。(已弃用!)这个几乎与 sysfs 接口相同。此接口已弃用,因此用户应迁移到 sysfs 接口。如果您依赖此接口并且无法迁移,请将您的用例报告给 damon@lists.linux.devlinux-mm@kvack.org

sysfs 接口

当定义 CONFIG_DAMON_SYSFS 时,会构建 DAMON sysfs 接口。它在其 sysfs 目录 <sysfs>/kernel/mm/damon/ 下创建多个目录和文件。您可以通过写入和读取该目录下的文件来控制 DAMON。

对于一个简单的示例,用户可以如下所示地监视给定工作负载的虚拟地址空间。

# cd /sys/kernel/mm/damon/admin/
# echo 1 > kdamonds/nr_kdamonds && echo 1 > kdamonds/0/contexts/nr_contexts
# echo vaddr > kdamonds/0/contexts/0/operations
# echo 1 > kdamonds/0/contexts/0/targets/nr_targets
# echo $(pidof <workload>) > kdamonds/0/contexts/0/targets/0/pid_target
# echo on > kdamonds/0/state

文件层次结构

DAMON sysfs 接口的文件层次结构如下所示。在下图中,父子关系用缩进表示,每个目录都有 / 后缀,每个目录中的文件用逗号 (“,”) 分隔。

/sys/kernel/mm/damon/admin
│ kdamonds/nr_kdamonds
│ │ 0/state,pid
│ │ │ contexts/nr_contexts
│ │ │ │ 0/avail_operations,operations
│ │ │ │ │ monitoring_attrs/
│ │ │ │ │ │ intervals/sample_us,aggr_us,update_us
│ │ │ │ │ │ nr_regions/min,max
│ │ │ │ │ targets/nr_targets
│ │ │ │ │ │ 0/pid_target
│ │ │ │ │ │ │ regions/nr_regions
│ │ │ │ │ │ │ │ 0/start,end
│ │ │ │ │ │ │ │ ...
│ │ │ │ │ │ ...
│ │ │ │ │ schemes/nr_schemes
│ │ │ │ │ │ 0/action,target_nid,apply_interval_us
│ │ │ │ │ │ │ access_pattern/
│ │ │ │ │ │ │ │ sz/min,max
│ │ │ │ │ │ │ │ nr_accesses/min,max
│ │ │ │ │ │ │ │ age/min,max
│ │ │ │ │ │ │ quotas/ms,bytes,reset_interval_ms,effective_bytes
│ │ │ │ │ │ │ │ weights/sz_permil,nr_accesses_permil,age_permil
│ │ │ │ │ │ │ │ goals/nr_goals
│ │ │ │ │ │ │ │ │ 0/target_metric,target_value,current_value
│ │ │ │ │ │ │ watermarks/metric,interval_us,high,mid,low
│ │ │ │ │ │ │ filters/nr_filters
│ │ │ │ │ │ │ │ 0/type,matching,memcg_id
│ │ │ │ │ │ │ stats/nr_tried,sz_tried,nr_applied,sz_applied,qt_exceeds
│ │ │ │ │ │ │ tried_regions/total_bytes
│ │ │ │ │ │ │ │ 0/start,end,nr_accesses,age
│ │ │ │ │ │ │ │ ...
│ │ │ │ │ │ ...
│ │ │ │ ...
│ │ ...

根目录

DAMON sysfs 接口的根目录是 <sysfs>/kernel/mm/damon/,它有一个名为 admin 的目录。该目录包含用于特权用户空间程序控制 DAMON 的文件。具有 root 权限的用户空间工具或守护程序可以使用此目录。

kdamonds/

admin 目录下,有一个名为 kdamonds 的目录,其中包含用于控制 kdamonds 的文件(有关更多详细信息,请参阅 设计)。最开始,此目录只有一个文件 nr_kdamonds。向该文件写入一个数字 (N) 会创建 N 个名为 0N-1 的子目录。每个目录代表每个 kdamond。

kdamonds/<N>/

在每个 kdamond 目录中,存在两个文件(statepid)和一个目录(contexts)。

如果 kdamond 当前正在运行,读取 state 会返回 on,如果 kdamond 未运行,则会返回 off

用户可以将以下命令写入 state 文件来控制 kdamond。

  • on:开始运行。

  • off:停止运行。

  • commit:再次读取 sysfs 文件中(state 文件除外)的用户输入。

  • commit_schemes_quota_goals:读取基于 DAMON 的操作方案的 配额目标

  • update_schemes_stats:更新 kdamond 的每个基于 DAMON 的操作方案的统计信息文件的内容。有关统计信息的详细信息,请参阅 统计信息部分

  • update_schemes_tried_regions:更新 kdamond 的每个基于 DAMON 的操作方案的基于 DAMON 的操作方案尝试的区域目录。有关基于 DAMON 的操作方案尝试的区域目录的详细信息,请参阅 tried_regions 部分

  • update_schemes_tried_bytes:仅更新 .../tried_regions/total_bytes 文件。

  • clear_schemes_tried_regions:清除 kdamond 的每个基于 DAMON 的操作方案的基于 DAMON 的操作方案尝试的区域目录。

  • update_schemes_effective_quotas:更新 kdamond 的每个基于 DAMON 的操作方案的 effective_bytes 文件的内容。有关更多详细信息,请参阅 配额目录

如果状态为 on,读取 pid 会显示 kdamond 线程的 pid。

contexts 目录包含用于控制此 kdamond 将执行的监视上下文的文件。

kdamonds/<N>/contexts/

初始时,此目录仅包含一个文件,nr_contexts。向该文件写入一个数字 (N) 将创建以 0N-1 命名的子目录。每个目录代表一个监控上下文(更多细节请参考设计)。目前,每个 kdamond 仅支持一个上下文,因此只能向该文件写入 01

contexts/<N>/

在每个上下文目录中,存在两个文件(avail_operationsoperations)和三个目录(monitoring_attrstargetsschemes)。

DAMON 支持多种类型的监控操作,包括虚拟地址空间和物理地址空间的操作。您可以通过读取 avail_operations 文件来获取当前运行内核上可用的监控操作集列表。根据内核配置,该文件将列出不同的可用操作集。请参考设计,了解所有可用操作集及其简要说明的列表。

您可以通过写入 avail_operations 文件中列出的关键字之一,并从 operations 文件读取,来设置和获取 DAMON 将用于上下文的监控操作类型。

contexts/<N>/monitoring_attrs/

用于指定监控属性(包括监控所需的质量和效率)的文件位于 monitoring_attrs 目录中。具体来说,此目录中存在两个目录,intervalsnr_regions

intervals 目录下,存在用于 DAMON 采样间隔 (sample_us)、聚合间隔 (aggr_us) 和更新间隔 (update_us) 的三个文件。您可以通过写入和读取文件来设置和获取以微秒为单位的值。

nr_regions 目录下,存在用于 DAMON 监控区域下限和上限(分别为 minmax)的两个文件,用于控制监控开销。您可以通过写入和读取文件来设置和获取这些值。

有关间隔和监控区域范围的更多详细信息,请参阅设计文档(设计)。

contexts/<N>/targets/

初始时,此目录仅包含一个文件,nr_targets。向该文件写入一个数字 (N) 将创建以 0N-1 命名的子目录。每个目录代表一个监控目标。

targets/<N>/

在每个目标目录中,存在一个文件 (pid_target) 和一个目录 (regions)。

如果您向 contexts/<N>/operations 写入了 vaddr,则每个目标应该是一个进程。您可以通过将进程的 pid 写入 pid_target 文件来指定 DAMON 的进程。

targets/<N>/regions

fvaddrpaddr 监控操作集的情况下,用户需要设置监控目标地址范围。在 vaddr 操作集的情况下,这不是强制性的,但用户可以选择将初始监控区域设置为特定的地址范围。有关更多详细信息,请参阅设计

对于这种情况,用户可以通过将适当的值写入此目录下的文件来显式设置初始监控目标区域。

初始时,此目录仅包含一个文件,nr_regions。向该文件写入一个数字 (N) 将创建以 0N-1 命名的子目录。每个目录代表一个初始监控目标区域。

regions/<N>/

在每个区域目录中,您将找到两个文件(startend)。您可以通过写入和读取文件来设置和获取初始监控目标区域的起始地址和结束地址。

每个区域不应与其他区域重叠。目录 Nend 应该等于或小于目录 N+1start

contexts/<N>/schemes/

基于 DAMON 的操作方案的目录(DAMOS)。用户可以通过读取和写入此目录下的文件来获取和设置方案。

初始时,此目录仅包含一个文件,nr_schemes。向该文件写入一个数字 (N) 将创建以 0N-1 命名的子目录。每个目录代表一个基于 DAMON 的操作方案。

schemes/<N>/

在每个方案目录中,存在五个目录(access_patternquotaswatermarksfiltersstatstried_regions)和三个文件(actiontarget_nidapply_interval)。

action 文件用于设置和获取方案的操作。可以写入和读取该文件的关键字及其含义与设计文档上的列表相同。

target_nid 文件用于设置迁移目标节点,这仅在 actionmigrate_hotmigrate_cold 时才有意义。

apply_interval_us 文件用于设置和获取方案的应用间隔,单位为微秒。

schemes/<N>/access_pattern/

给定基于 DAMON 的操作方案的目标访问模式的目录。

access_pattern 目录下,存在三个目录(sznr_accessesage),每个目录都有两个文件(minmax)。您可以通过写入和读取 sznr_accessesage 目录下的 minmax 文件来设置和获取给定方案的访问模式。请注意,minmax 构成一个闭区间。

schemes/<N>/quotas/

给定基于 DAMON 的操作方案的配额的目录。

quotas 目录下,存在四个文件(msbytesreset_interval_mseffective_bytes)和两个目录(weightsgoals)。

您可以通过向这三个文件写入值来分别设置以毫秒为单位的 时间配额、以字节为单位的 大小配额 和以毫秒为单位的 重置间隔。然后,DAMON 尝试仅在 重置间隔 内使用最多 时间配额 毫秒来对 访问模式 的内存区域应用 操作,并仅对 bytes 字节的内存区域应用操作。除非至少设置了一个目标,否则将 msbytes 都设置为零会禁用配额限制。

时间配额会在内部转换为大小配额。在转换后的大小配额和用户指定的大小配额之间,会应用较小的一个。基于用户指定的目标,有效的大小配额会进一步调整。读取 effective_bytes 会返回当前有效的的大小配额。该文件不会实时更新,因此用户应该通过向相关的 kdamonds/<N>/state 文件写入特殊关键字 update_schemes_effective_quotas 来请求 DAMON sysfs 接口更新该文件的内容,以获取统计信息。

weights 目录下,存在三个文件(sz_permilnr_accesses_permilage_permil)。您可以通过向 weights 目录下的这三个文件写入值来设置大小、访问频率和年龄的优先级权重,单位为千分之几。

schemes/<N>/quotas/goals/

给定基于 DAMON 的操作方案的自动配额调整目标的目录。

最初,此目录只有一个文件 nr_goals。向该文件写入一个数字 (N) 会创建 N 个子目录,名称为 0N-1。每个目录代表每个目标和当前的实现情况。在多个反馈中,会使用最佳的一个。

每个目标目录包含三个文件,分别是 target_metrictarget_valuecurrent_value。用户可以通过向每个文件写入和读取来设置和获取设计文档中指定的配额自动调整目标的三个参数。请注意,用户还应将 commit_schemes_quota_goals 写入kdamond 目录state 文件,以便将反馈传递给 DAMON。

schemes/<N>/watermarks/

给定基于 DAMON 的操作方案的水位线的目录。

在 watermarks 目录下,存在五个文件(metricinterval_ushighmidlow),用于设置指标、指标检查的时间间隔和三个水位线。您可以通过分别写入这些文件来设置和获取这五个值。

可以写入 metric 文件的关键字及其含义如下。

  • none: 忽略水位线

  • free_mem_rate: 系统可用内存率(千分之几)

interval 应以微秒为单位写入。

schemes/<N>/filters/

给定基于 DAMON 的操作方案的过滤器的目录。

最初,此目录只有一个文件 nr_filters。向该文件写入一个数字 (N) 会创建 N 个子目录,名称为 0N-1。每个目录代表每个过滤器。过滤器会按数字顺序进行评估。

每个过滤器目录包含六个文件,分别是 typematcingmemcg_pathaddr_startaddr_endtarget_idx。对于 type 文件,您可以写入以下五个特殊关键字之一:anon 表示匿名页面,memcg 表示特定的内存 cgroup,young 表示年轻页面,addr 表示特定的地址范围(开放式间隔),或者 target 表示特定的 DAMON 监控目标过滤。在内存 cgroup 过滤的情况下,您可以通过将内存 cgroup 的路径从 cgroup 挂载点写入 memcg_path 文件来指定感兴趣的内存 cgroup。在地址范围过滤的情况下,您可以分别在 addr_startaddr_end 文件中指定范围的起始地址和结束地址。对于 DAMON 监控目标过滤,您可以将 DAMON 上下文的监控目标列表中的目标索引指定到 target_idx 文件。您可以向 matching 文件写入 YN,分别过滤掉与类型匹配或不匹配的页面。然后,该方案的操作将不会应用于指定为过滤掉的页面。

例如,以下示例将 DAMOS 操作限制为仅应用于除 /having_care_already 之外的所有内存 cgroup 的非匿名页面。

# echo 2 > nr_filters
# # filter out anonymous pages
echo anon > 0/type
echo Y > 0/matching
# # further filter out all cgroups except one at '/having_care_already'
echo memcg > 1/type
echo /having_care_already > 1/memcg_path
echo Y > 1/matching

请注意,目前仅在使用 paddr 实现时才支持 anonmemcg 过滤器。

此外,由 addrtarget 过滤器过滤掉的内存区域不计入该方案已尝试的区域,而由其他类型过滤器过滤掉的区域则计入该方案已尝试的区域。此差异会应用于统计信息已尝试区域

schemes/<N>/stats/

DAMON 会统计每个方案尝试应用的区域的总数和字节数、每个方案成功应用的区域的总数和字节数,以及超过配额限制的总数。这些统计信息可用于方案的在线分析或调整。

可以通过读取 stats 目录下的文件(分别是 nr_triedsz_triednr_appliedsz_appliedqt_exceeds)来检索统计信息。这些文件不会实时更新,因此您应该通过向相关的 kdamonds/<N>/state 文件写入特殊关键字 update_schemes_stats 来请求 DAMON sysfs 接口更新该文件的内容,以获取统计信息。

schemes/<N>/tried_regions/

此目录最初只有一个文件 total_bytes

当向相关的 kdamonds/<N>/state 文件写入特殊关键字 update_schemes_tried_regions 时,DAMON 会更新 total_bytes 文件,以便读取它会返回方案尝试区域的总大小,并在此目录下创建以整数命名的目录,从 0 开始。每个目录都包含公开有关相应方案的 action 在下一个相应方案的应用间隔期间尝试应用的每个内存区域的详细信息的文件。这些信息包括区域的地址范围、nr_accessesage

update_schemes_tried_bytes 写入相关的 kdamonds/<N>/state 文件只会更新 total_bytes 文件,而不会创建子目录。

当将另一个特殊关键字 clear_schemes_tried_regions 写入相关的 kdamonds/<N>/state 文件时,这些目录将被删除。

此目录的预期用途是调查方案的行为,以及像查询一样高效的数据访问监控结果检索。特别是对于后一种用例,用户可以将 action 设置为 stat,并将 access pattern 设置为他们想要查询的感兴趣的模式。

tried_regions/<N>/

在每个区域目录中,您会找到四个文件(startendnr_accessesage)。读取这些文件将显示基于 DAMON 的操作方案 action 尝试应用的区域的起始和结束地址、nr_accessesage

示例

以下命令应用一个方案,该方案表示“如果大小在 [4KiB, 8KiB] 范围内的内存区域在 [10, 20] 的聚合间隔内,在 [0, 5] 的聚合间隔内显示访问次数,则将该区域换出。对于换出,每秒仅使用最多 10 毫秒,并且每秒也不要换出超过 1GiB 的内存。在限制下,首先换出具有较长 age 的内存区域。此外,每 5 秒检查一次系统的空闲内存率,当空闲内存率低于 50% 时开始监控和换出,但如果空闲内存率大于 60% 或低于 30%,则停止监控和换出”。

# cd <sysfs>/kernel/mm/damon/admin
# # populate directories
# echo 1 > kdamonds/nr_kdamonds; echo 1 > kdamonds/0/contexts/nr_contexts;
# echo 1 > kdamonds/0/contexts/0/schemes/nr_schemes
# cd kdamonds/0/contexts/0/schemes/0
# # set the basic access pattern and the action
# echo 4096 > access_pattern/sz/min
# echo 8192 > access_pattern/sz/max
# echo 0 > access_pattern/nr_accesses/min
# echo 5 > access_pattern/nr_accesses/max
# echo 10 > access_pattern/age/min
# echo 20 > access_pattern/age/max
# echo pageout > action
# # set quotas
# echo 10 > quotas/ms
# echo $((1024*1024*1024)) > quotas/bytes
# echo 1000 > quotas/reset_interval_ms
# # set watermark
# echo free_mem_rate > watermarks/metric
# echo 5000000 > watermarks/interval_us
# echo 600 > watermarks/high
# echo 500 > watermarks/mid
# echo 300 > watermarks/low

请注意,强烈建议使用诸如 damo 之类的用户空间工具,而不是像上面那样手动读取和写入文件。上面只是一个示例。

监控结果的跟踪点

用户可以通过 tried_regions 获取监控结果。该接口对于获取快照很有用,但对于完全记录所有监控结果可能效率不高。为此,提供了两个跟踪点,即 damon:damon_aggregateddamon:damos_before_applydamon:damon_aggregated 提供完整的监控结果,而 damon:damos_before_apply 提供每个基于 DAMON 的操作方案(DAMOS)即将应用的区域的监控结果。因此,damon:damos_before_apply 更适合记录 DAMOS 的内部行为,或基于 DAMOS 目标访问 pattern 的类查询的高效监控结果记录。

在监控开启时,您可以使用诸如 perf 之类的支持跟踪点的工具记录跟踪点事件并显示结果。例如

# echo on > kdamonds/0/state
# perf record -e damon:damon_aggregated &
# sleep 5
# kill 9 $(pidof perf)
# echo off > kdamonds/0/state
# perf script
kdamond.0 46568 [027] 79357.842179: damon:damon_aggregated: target_id=0 nr_regions=11 122509119488-135708762112: 0 864
[...]

perf 脚本输出的每一行都代表一个监控区域。前五个字段与其他跟踪点输出一样。第六个字段 (target_id=X) 显示区域的监控目标的 ID。第七个字段 (nr_regions=X) 显示目标的监控区域总数。第八个字段 (X-Y:) 显示区域的起始 (X) 和结束 (Y) 地址(以字节为单位)。第九个字段 (X) 显示区域的 nr_accesses(有关计数器的更多详细信息,请参阅 design)。最后,第十个字段 (X) 显示区域的 age(有关计数器的更多详细信息,请参阅 design)。

如果事件是 damon:damos_beofre_apply,则 perf script 输出将类似于以下内容

kdamond.0 47293 [000] 80801.060214: damon:damos_before_apply: ctx_idx=0 scheme_idx=0 target_idx=0 nr_regions=11 121932607488-135128711168: 0 136
[...]

输出的每一行都代表在跟踪时每个基于 DAMON 的操作方案即将应用的每个监控区域。前五个字段是通常的字段。除了 damon_aggregated 跟踪点的输出外,它还显示了方案在上下文的 kdamond 上下文列表中的 DAMON 上下文的索引 (ctx_idx=X),以及方案在上下文方案列表中的索引 (scheme_idx=X)。

debugfs 接口(已弃用!)

注意

此功能已弃用!

DAMON debugfs 接口已弃用,因此用户应迁移到 sysfs 接口。如果您依赖于此并且无法迁移,请将您的用例报告给 damon@lists.linux.devlinux-mm@kvack.org

DAMON 在其 debugfs 目录 <debugfs>/damon/ 下导出九个文件:DEPRECATEDattrstarget_idsinit_regionsschemesmonitor_on_DEPRECATEDkdamond_pidmk_contextsrm_contexts

DEPRECATED 是一个只读文件,用于 DAMON debugfs 接口弃用通知。读取它将返回弃用通知,如下所示

# cat DEPRECATED
DAMON debugfs interface is deprecated, so users should move to DAMON_SYSFS. If you cannot, please report your usecase to [email protected] and [email protected].

属性

用户可以通过读取和写入 attrs 文件来获取和设置 sampling intervalaggregation intervalupdate interval 以及监控目标区域的最小/最大数量。要详细了解监控属性,请参阅 Design。例如,以下命令将这些值设置为 5 毫秒、100 毫秒、1,000 毫秒、10 和 1000,然后再次检查它

# cd <debugfs>/damon
# echo 5000 100000 1000000 10 1000 > attrs
# cat attrs
5000 100000 1000000 10 1000

目标 ID

某些类型的地址空间支持多个监控目标。例如,虚拟内存地址空间监控可以有多个进程作为监控目标。用户可以通过将目标的相关 id 值写入 target_ids 文件来设置目标,并通过读取 target_ids 文件来获取当前目标的 id。在虚拟地址空间监控的情况下,这些值应该是监控目标进程的 pid。例如,以下命令将 pid 为 42 和 4242 的进程设置为监控目标,然后再次检查它

# cd <debugfs>/damon
# echo 42 4242 > target_ids
# cat target_ids
42 4242

用户还可以通过将特殊关键字“paddr\n”写入文件来监控系统的物理内存地址空间。因为物理地址空间监控不支持多个目标,所以读取该文件将显示一个虚假值 42,如下所示

# cd <debugfs>/damon
# echo paddr > target_ids
# cat target_ids
42

请注意,设置目标 id 不会启动监控。

初始监控目标区域

在虚拟地址空间监控的情况下,DAMON 会自动设置和更新监控目标区域,以便覆盖目标进程的整个内存映射。但是,用户可能希望将监控区域限制为特定地址范围,例如堆、栈或特定文件映射区域。或者,一些用户可能知道其工作负载的初始访问模式,因此希望为“自适应区域调整”设置最佳初始区域。

相比之下,在物理内存监控的情况下,DAMON 不会自动设置和更新监控目标区域。因此,用户应该自己设置监控目标区域。

在这种情况下,用户可以通过将适当的值写入 init_regions 文件来显式地设置他们想要的初始监控目标区域。输入应为以空格分隔的三个整数的序列,它们以下面的形式表示一个区域。

<target idx> <start address> <end address>

target idx 应该是 target_ids 文件中目标的索引,从 0 开始,并且区域应按地址顺序传递。例如,以下命令会将几个地址范围 1-100100-200 设置为 pid 42 的初始监控目标区域,它是 target_ids 中的第一个(索引 0),并将另外几个地址范围 20-4050-100 设置为 pid 4242 的初始监控目标区域,它是 target_ids 中的第二个(索引 1)。

# cd <debugfs>/damon
# cat target_ids
42 4242
# echo "0   1       100 \
        0   100     200 \
        1   20      40  \
        1   50      100" > init_regions

请注意,这仅设置初始监控目标区域。在虚拟内存监控的情况下,DAMON 将在一个 update interval 后自动更新区域的边界。因此,如果用户不希望进行更新,则在这种情况下应将 update interval 设置得足够大。

方案

用户可以通过读取和写入 schemes debugfs 文件来获取和设置基于 DAMON 的操作方案。读取该文件还会显示每个方案的统计信息。对于该文件,每个方案应以如下形式在每行中表示。

<target access pattern> <action> <quota> <watermarks>

你可以通过简单地向该文件写入空字符串来禁用方案。

目标访问模式

方案的目标访问模式<目标访问模式> 由以下形式的三个范围构成。

min-size max-size min-acc max-acc min-age max-age

具体来说,指定区域大小的字节数(最小大小最大大小),每个聚合间隔监控的访问次数(最小访问最大访问),以及区域年龄的聚合间隔数(最小年龄最大年龄)。请注意,这些范围是闭区间。

动作

<动作> 是内存管理动作的预定义整数。 <动作> 值与内存管理动作之间的映射如下。有关动作的详细含义和支持每个动作的 DAMON 操作集,请参阅设计文档上的列表。

  • 0: willneed

  • 1: cold

  • 2: pageout

  • 3: hugepage

  • 4: nohugepage

  • 5: stat

配额

用户可以通过以下形式的 <配额> 设置给定方案的配额

<ms> <sz> <reset interval> <priority weights>

这使得 DAMON 尝试仅在 <重置间隔> 毫秒内使用最多 <毫秒数> 毫秒的时间,对 目标访问模式 的内存区域应用操作,并在 <重置间隔> 内仅对最多 <大小> 字节的内存区域应用操作。将 <毫秒数><大小> 都设置为零将禁用配额限制。

对于优先级,用户可以在以下形式的 <优先级权重> 中设置三个属性的权重。

<size weight> <access frequency weight> <age weight>

水位线

用户可以通过以下形式的 <水位线> 指定给定方案的水位线

<metric> <check interval> <high mark> <middle mark> <low mark>

<指标> 是要检查的指标的预定义整数。支持的数字及其含义如下。

  • 0:忽略水位线

  • 1:系统可用内存率(每千分之几)

<检查间隔> 微秒检查一次指标的值。

如果该值高于 <高水位线> 或低于 <低水位线>,则该方案将被禁用。如果该值低于 <中间水位线>,则该方案将被激活。

统计信息

它还会统计每个方案尝试应用的区域总数和字节数、每个方案成功应用的区域的两个数字,以及超出配额限制的总数。此统计信息可用于方案的在线分析或调整。

可以通过读取 schemes 文件来显示统计信息。读取该文件将显示您在每行中输入的每个方案,并且统计信息的五个数字将添加到每行的末尾。

示例

以下命令应用一个方案,该方案表示“如果大小在 [4KiB, 8KiB] 范围内的内存区域在 [10, 20] 的聚合间隔内,在 [0, 5] 的聚合间隔内显示访问次数,则将该区域换出。对于换出,每秒仅使用最多 10 毫秒,并且每秒也不要换出超过 1GiB 的内存。在限制下,首先换出具有较长 age 的内存区域。此外,每 5 秒检查一次系统的空闲内存率,当空闲内存率低于 50% 时开始监控和换出,但如果空闲内存率大于 60% 或低于 30%,则停止监控和换出”。

# cd <debugfs>/damon
# scheme="4096 8192  0 5    10 20    2"  # target access pattern and action
# scheme+=" 10 $((1024*1024*1024)) 1000" # quotas
# scheme+=" 0 0 100"                     # prioritization weights
# scheme+=" 1 5000000 600 500 300"       # watermarks
# echo "$scheme" > schemes

开启/关闭

除非您显式启动监控,否则如上所述设置文件不会产生影响。您可以通过写入和读取 monitor_on_DEPRECATED 文件来启动、停止和检查监控的当前状态。向该文件写入 on 会启动具有属性的目标的监控。向该文件写入 off 会停止这些监控。如果每个目标进程都终止,DAMON 也会停止。以下示例命令将开启、关闭和检查 DAMON 的状态。

# cd <debugfs>/damon
# echo on > monitor_on_DEPRECATED
# echo off > monitor_on_DEPRECATED
# cat monitor_on_DEPRECATED
off

请注意,在监控开启时,您无法写入上述 debugfs 文件。如果您在 DAMON 运行时写入文件,将返回一个错误代码,例如 -EBUSY

监控线程 PID

DAMON 使用一个名为 kdamond 的内核线程执行请求的监控。您可以通过读取 kdamond_pid 文件来获取该线程的 pid。当监控关闭时,读取该文件会返回 none

# cd <debugfs>/damon
# cat monitor_on_DEPRECATED
off
# cat kdamond_pid
none
# echo on > monitor_on_DEPRECATED
# cat kdamond_pid
18594

使用多个监控线程

为每个监控上下文创建一个 kdamond 线程。您可以使用 mk_contextsrm_contexts 文件为多个 kdamond 需要的用例创建和删除监控上下文。

将新上下文的名称写入 mk_contexts 文件会在 DAMON debugfs 目录下创建一个以该名称命名的目录。该目录将包含该上下文的 DAMON debugfs 文件。

# cd <debugfs>/damon
# ls foo
# ls: cannot access 'foo': No such file or directory
# echo foo > mk_contexts
# ls foo
# attrs  init_regions  kdamond_pid  schemes  target_ids

如果不再需要该上下文,您可以通过将该上下文的名称放入 rm_contexts 文件来删除它和相应的目录。

# echo foo > rm_contexts
# ls foo
# ls: cannot access 'foo': No such file or directory

请注意,mk_contextsrm_contextsmonitor_on_DEPRECATED 文件仅位于根目录中。