.. 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日。