内存优化之KSM技术
KSM是什么
KSM是linux中针对重复数据进行合并并删除冗余数据的一种内存节约技术,全称是Kernel Samepage Merging。
于linux 2.6.32引入,最初设计用于虚拟机,通过合并内存页来增加并发虚拟机的数量。但在非虚拟环境下仍然有用。通过合并相同的物理页来达到节省内存的效果。
更多详细的特性可以参考: https://www.kernel.org/doc/html/next/mm/ksm.html
KSM的原理
原理:通过扫描内存区域,找到并合并相同的内存页面,实现节省内存的技术
如果KSM被编译进了内核,内核在启动后会创建ksmd内核线程,周期性扫描用户内存,寻找可以合并的相同的内存页并为写保护页
KSM只会作用于标记为可合并的地址空间
核心数据结构
KSM维护两个红黑树,一颗是稳定树,用来保存稳定合并的唯一页面,另一棵是不稳定树,用来保存合适的候选的可合并页面,每次扫描之后重构,比较两个页面是否相等的方法,直接使用 memcmp 函数。
标记可扫描的地址空间的方法,linux提供了系统调用,让用户来指定KSM扫描的地址空间
int madvise(addr, length, MADV_MERGEABLE)
int madvise(addr, length, MADV_UNMERGERABLE)
查看linux ksm的指标
通过命令行 ps aux | grep ksmd 可以打印KSMD的内核进程
命令行 cat /sys/kernel/mm/ksm/pages_sharing 可以查看当前linux的KSM共享页的数量
在/sys/kernel/mm/ksm下包含了整个系统的KSM相关的指标
pages_to_scan表示KSMD需要扫描多少分页,默认是100;
sleep_millisecs表示文件定义执行另一次页面扫面前KSMD进行睡眠的毫秒数
max_kernel_pages表示文件定义KSMD可以使用的最大页面数,默认值是可用内存的25%。
pages_to_scan表示文件定义一次给定扫描中可以扫描的页面数
full_scans表示文件已经执行的全区域扫描的次数
pages_shared表示KSM正在使用的不可交换的内核页面的数量
pages_sharing表示一个内存存储指示,多少节点被共享
pages_unshared 为合并而重复检查的唯一页面的数量
pages_volatitle表示为频繁改变的页面的数量
max_page_sharing表示为每一个分页能够运行共享的次数
merge_across_nodes表示为是否指定多个numa节点的内存进行合并
run可以设置KSM属性的状态
use_zero_pages表示为是否合并空白分页,默认是关闭
KSM的案例效果
使用共享内容KSM可以小幅度减少同一个业务进程的内存消耗,大幅度减少整机的内存消耗。
其中不支持动态寻路接口的使用,(因为会不同的业务进程会有不同的修改操作)
根据/proc/self/smaps计算的Rss与Pss
Rss:10305.51 MB Pss:10284.62MB
Rss:9701.19 MB Pss:9678.25MB
Rss:8744.93 MB Pss:704.89MB
KSM的应用
在测试环境中,可以直接开启,为了让同一台机器可以容纳更多的实例。
在生产环境中,需要针对不同的应用场景来设定
对于延迟敏感型的应用,极限开启KSM会遇到SWAP频繁使用,影响应用执行的问题。开启KSM要注意最大使用的边界,确保不会导致SWAP的使用,同时,开启KSM也能留出更多内存,以应付应用的内存泄露等问题留出更多的团队反应时间。
对于