linux-zen-desktop/Documentation/translations/zh_CN/admin-guide/mm/ksm.rst

199 lines
10 KiB
ReStructuredText
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

.. include:: ../../disclaimer-zh_CN.rst
:Original: Documentation/admin-guide/mm/ksm.rst
:翻译:
徐鑫 xu xin <xu.xin16@zte.com.cn>
============
内核同页合并
============
概述
====
KSM是一种能节省内存的数据去重功能由CONFIG_KSM=y启用并在2.6.32版本时被添
加到Linux内核。详见 ``mm/ksm.c`` 的实现以及http://lwn.net/Articles/306704
和https://lwn.net/Articles/330589
KSM最初目的是为了与KVM即著名的内核共享内存一起使用而开发的通过共享虚拟机
之间的公共数据,将更多虚拟机放入物理内存。但它对于任何会生成多个相同数据实例的
应用程序都是很有用的。
KSM的守护进程ksmd会定期扫描那些已注册的用户内存区域查找内容相同的页面这些
页面可以被单个写保护页面替换(如果进程以后想要更新其内容,将自动复制)。使用:
引用:`sysfs intraface <ksm_sysfs>` 接口来配置KSM守护程序在单个过程中所扫描的页
数以及两个过程之间的间隔时间。
KSM只合并匿名私有页面从不合并页缓存文件页面。KSM的合并页面最初只能被
锁定在内核内存中,但现在可以就像其他用户页面一样被换出(但当它们被交换回来时共
享会被破坏: ksmd必须重新发现它们的身份并再次合并
以madvise控制KSM
================
KSM仅在特定的地址空间区域时运行即应用程序通过使用如下所示的madvise(2)系统调
用来请求某块地址成为可能的合并候选者的地址空间::
int madvise(addr, length, MADV_MERGEABLE)
应用程序当然也可以通过调用::
int madvise(addr, length, MADV_UNMERGEABLE)
来取消该请求并恢复为非共享页面此时KSM将去除合并在该范围内的任何合并页。注意
这个去除合并的调用可能突然需要的内存量超过实际可用的内存量-那么可能会出现EAGAIN
失败但更可能会唤醒OOM killer。
如果KSM未被配置到正在运行的内核中则madvise MADV_MERGEABLE 和 MADV_UNMERGEABLE
的调用只会以EINVAL 失败。如果正在运行的内核是用CONFIG_KSM=y方式构建的那么这些
调用通常会成功即使KSM守护程序当前没有运行MADV_MERGEABLE 仍然会在KSM守护程序
启动时注册范围即使该范围不能包含KSM实际可以合并的任何页面即使MADV_UNMERGEABLE
应用于从未标记为MADV_MERGEABLE的范围。
如果一块内存区域必须被拆分为至少一个新的MADV_MERGEABLE区域或MADV_UNMERGEABLE区域
当该进程将超过 ``vm.max_map_count`` 的设定则madvise可能返回ENOMEM。请参阅文档
Documentation/admin-guide/sysctl/vm.rst
与其他madvise调用一样它们在用户地址空间的映射区域上使用如果指定的范围包含未
映射的间隙尽管在中间的映射区域工作它们将报告ENOMEM如果没有足够的内存用于
内部结构则可能会因EAGAIN而失败。
KSM守护进程sysfs接口
====================
KSM守护进程可以由``/sys/kernel/mm/ksm/`` 中的sysfs文件控制所有人都可以读取
只能由root用户写入。各接口解释如下
pages_to_scan
ksmd进程进入睡眠前要扫描的页数。
例如, ``echo 100 > /sys/kernel/mm/ksm/pages_to_scan``
默认值100该值被选择用于演示目的
sleep_millisecs
ksmd在下次扫描前应休眠多少毫秒
例如, ``echo 20 > /sys/kernel/mm/ksm/sleep_millisecs``
默认值20该值被选择用于演示目的
merge_across_nodes
指定是否可以合并来自不同NUMA节点的页面。当设置为0时ksm仅合并在物理上位
于同一NUMA节点的内存区域中的页面。这降低了访问共享页面的延迟。在有明显的
NUMA距离上具有更多节点的系统可能受益于设置该值为0时的更低延迟。而对于
需要对内存使用量最小化的较小系统来说设置该值为1默认设置则可能会受
益于更大共享页面。在决定使用哪种设置之前,您可能希望比较系统在每种设置下
的性能。 ``merge_across_nodes`` 仅当系统中没有ksm共享页面时才能被更改设
置:首先将接口`run` 设置为2从而对页进行去合并然后在修改
``merge_across_nodes`` 后再将run又设置为1以根据新设置来重新合并。
默认值1如早期的发布版本一样合并跨站点
run
* 设置为0可停止ksmd运行但保留合并页面
* 设置为1可运行ksmd例如 ``echo 1 > /sys/kernel/mm/ksm/run``
* 设置为2可停止ksmd运行并且对所有目前已合并的页进行去合并但保留可合并
区域以供下次运行。
默认值0必须设置为1才能激活KSM除非禁用了CONFIG_SYSFS
use_zero_pages
指定是否应当特殊处理空页即那些仅含zero的已分配页。当该值设置为1时
空页与内核零页合并,而不是像通常情况下那样空页自身彼此合并。这可以根据
工作负载的不同,在具有着色零页的架构上可以提高性能。启用此设置时应小心,
因为它可能会降低某些工作负载的KSM性能比如当待合并的候选页面的校验和
与空页面的校验和恰好匹配的时候。此设置可随时更改,仅对那些更改后再合并
的页面有效。
默认值0如同早期版本的KSM正常表现
max_page_sharing
单个KSM页面允许的最大共享站点数。这将强制执行重复数据消除限制以避免涉
及遍历共享KSM页面的虚拟映射的虚拟内存操作的高延迟。最小值为2因为新创
建的KSM页面将至少有两个共享者。该值越高KSM合并内存的速度越快去重
因子也越高但是对于任何给定的KSM页面虚拟映射的最坏情况遍历的速度也会
越慢。减慢了这种遍历速度就意味着在交换、压缩、NUMA平衡和页面迁移期间
某些虚拟内存操作将有更高的延迟,从而降低这些虚拟内存操作调用者的响应能力。
其他任务如果不涉及执行虚拟映射遍历的VM操作其任务调度延迟不受此参数的影
响,因为这些遍历本身是调度友好的。
stable_node_chains_prune_millisecs
指定KSM检查特定页面的元数据的频率即那些达到过时信息数据去重限制标准的
页面单位是毫秒。较小的毫秒值将以更低的延迟来释放KSM元数据但它们将使
ksmd在扫描期间使用更多CPU。如果还没有一个KSM页面达到 ``max_page_sharing``
标准,那就没有什么用。
KSM与MADV_MERGEABLE的工作有效性体现于 ``/sys/kernel/mm/ksm/`` 路径下的接口:
pages_shared
表示多少共享页正在被使用
pages_sharing
表示还有多少站点正在共享这些共享页,即节省了多少
pages_unshared
表示有多少页是唯一的,但被反复检查以进行合并
pages_volatile
表示有多少页因变化太快而无法放在tree中
full_scans
表示所有可合并区域已扫描多少次
stable_node_chains
达到 ``max_page_sharing`` 限制的KSM页数
stable_node_dups
重复的KSM页数
比值 ``pages_sharing/pages_shared`` 的最大值受限制于 ``max_page_sharing``
的设定。要想增加该比值,则相应地要增加 ``max_page_sharing`` 的值。
监测KSM的收益
=============
KSM可以通过合并相同的页面来节省内存但也会消耗额外的内存因为它需要生成一些rmap_items
来保存每个扫描页面的简要rmap信息。其中有些页面可能会被合并但有些页面在被检查几次
后可能无法被合并,这些都是无益的内存消耗。
1) 如何确定KSM在全系统范围内是节省内存还是消耗内存这里有一个简单的近似计算方法供参考::
general_profit =~ pages_sharing * sizeof(page) - (all_rmap_items) *
sizeof(rmap_item);
其中all_rmap_items可以通过对 ``pages_sharing````pages_shared````pages_unshared``
``pages_volatile`` 的求和而轻松获得。
2) 单一进程中KSM的收益也可以通过以下近似的计算得到::
process_profit =~ ksm_merging_pages * sizeof(page) -
ksm_rmap_items * sizeof(rmap_item).
其中ksm_merging_pages显示在 ``/proc/<pid>/`` 目录下而ksm_rmap_items
显示在 ``/proc/<pid>/ksm_stat``
从应用的角度来看, ``ksm_rmap_items````ksm_merging_pages`` 的高比例意
味着不好的madvise-applied策略所以开发者或管理员必须重新考虑如何改变madvis策
略。举个例子供参考一个页面的大小通常是4K而rmap_item的大小在32位CPU架构上分
别是32B在64位CPU架构上是64B。所以如果 ``ksm_rmap_items/ksm_merging_pages``
的比例在64位CPU上超过64或者在32位CPU上超过128那么应用程序的madvise策略应
该被放弃因为ksm收益大约为零或负值。
监控KSM事件
===========
在/proc/vmstat中有一些计数器可以用来监控KSM事件。KSM可能有助于节省内存这是
一种权衡因为它可能会在KSM COW或复制中的交换上遭受延迟。这些事件可以帮助用户评估
是否或如何使用KSM。例如如果cow_ksm增加得太快用户可以减少madvise(, , MADV_MERGEABLE)
的范围。
cow_ksm
在每次KSM页面触发写时拷贝COW时都会被递增当用户试图写入KSM页面时
我们必须做一个拷贝。
ksm_swpin_copy
在换入时每次KSM页被复制时都会被递增。请注意KSM页在换入时可能会被复
因为do_swap_page()不能做所有的锁而需要重组一个跨anon_vma的KSM页。
--
Izik Eidus,
Hugh Dickins, 2009年11月17日。