3. KSM

  • 1 KSM概述
    • 1.1 KSM的基本原理
    • 1.2 虚拟化场景下的KSM
      • 1.2.1 提高内存速度和使用效率
    • 1.3 内核的支持以及配置
    • 1.4 QEMU中的KSM支持
    • 1.5 KSM可能带来的问题
      • 1.5.1 CPU使用率提高
      • 1.5.2 客户机OS和应用程序大不相同时效率不高
      • 1.5.3 足够的交换空间
  • 2 KSM操作实践
    • 2.1 配置守护进程ksmd
      • 2.1.1 ksmd相关配置文件
      • 2.1.2 ksm相关数据影响
    • 2.2 ksmtuned: 动态调节ksm
      • 2.2.1 ksm和ksmtuned服务
      • 2.2.2 ksmtuned配置文件
      • 2.2.3 KSM实际操作效果对比
  • 3 QEMU对KSM的控制

在现代操作系统中,共享内存被很普遍地应用。比如著名的“写时复制”(copy-on-write,COW)技术。

而本节介绍的KSM技术却与这种内存共享概念不同。

1 KSM概述

KSM是“Kernel SamePage Merging”的缩写,中文可称为“内核同页合并”。

1.1 KSM的基本原理

KSM允许内核在两个或多个进程(包括虚拟客户机)之间共享完全相同的内存页。KSM让内核扫描检查正在运行中的程序比较它们的内存,如果发现它们有完全相同的内存区域或内存页,就将多个相同的内存合并为一个单一的内存页,并将其标识为“写时复制”。这样可以起到节省系统内存使用量的作用。之后,如果有进程试图去修改被标识为“写时复制”的合并内存页,就为该进程复制出一个新的内存页供其使用。

1.2 虚拟化场景下的KSM

在QEMU/KVM中,一个虚拟客户机就是一个QEMU进程,所以使用KSM也可以实现多个客户机之间相同内存合并。而且,如果在同一宿主机上的多个客户机运行的是相同的操作系统应用程序,则客户机之间的相同内存页的数量就可能比较大,这种情况下KSM的作用就更加显著

在KVM环境下使用KSM,还允许KVM请求哪些相同的内存页是可以被共享而合并的,所以KSM只会识别并合并那些不会干扰客户机运行不会影响宿主机或客户机运行的安全内存页

1.2.1 提高内存速度和使用效率

可见,在KVM虚拟化环境中,KSM能够提高内存的速度使用效率

具体可以从以下两个方面来理解。

1)在KSM的帮助下,相同的内存页被合并了,减少了客户机的内存使用量。

  • 一方面,内存中的内容更容易被保存到CPU的缓存中,
  • 另一方面,有更多的内存可用于缓存一些磁盘中的数据

因此,不管是内存的缓存命中率(CPU缓存命中率),还是磁盘数据的缓存命中率(在内存!!!中命中磁盘数据缓存的命中率)都会提高,从而提高了KVM客户机中操作系统或应用程序的运行速度

2)正如在5.3.3节中提及的那样,KSM内存过载使用的一种较好的方式

KSM通过减少每个客户机实际占用的内存数量,可以让多个客户机分配的内存数量之和大于物理上的内存数量。而对于使用相同内存量的客户机而言,在物理内存量不变的情况下,可以在一个宿主机中创建更多的客户机,提高了虚拟化客户机部署的密度,提高了物理资源的利用效率

1.3 内核的支持以及配置

KSM是在Linux内核2.6.32中被加入内核主干代码中去的。目前多数流行的Linux发型版都已经将KSM的支持编译到内核中了,其内核配置文件中有“CONFIG_KSM=y”项。

Linux系统的内核进程ksmd负责扫描后合并进程的相同内存页,从而实现KSM功能。root用户可以通过“/sys/kernel/mm/ksm/”目录下的文件来配置和监控ksmd这个守护进程

KSM只会去扫描和试图合并那些应用程序建议!!!为可合并的内存页应用程序(如QEMU)通过如下的madvice系统调用来告诉内核哪些页可合并

1.4 QEMU中的KSM支持

目前的QEMU都是支持KSM的,也可以通过查看其代码中对madvise函数的调用情况来确定是否支持KSM。

QEMU中的关键函数简要分析如下:

/* 将地址标志为KSM可合并的系统调用*/
/* int madvise(addr, length, MADV_MERGEABLE) */
/* madvise系统调用的声明在 中*/
/* int madvise( void *start, size_t length, int advice ); */

/* qemu代码的exec.c文件中,开启内存可合并选项*/
static int memory_try_enable_merging(void *addr, size_t len)
{
/*这里可以看到:通过qemu的-machine mem-merge=on|off参数可以对每个客户机开启或关闭KSM支持。
  我们后面通过实例观察效果。*/
    if (!machine_mem_merge(current_machine)) {
        /* disabled by the user */
        return 0;
    }

    return qemu_madvise(addr, len, QEMU_MADV_MERGEABLE);
}

/* qemu代码的osdep.c文件中对qemu_madvise()函数的定义*/
int qemu_madvise(void *addr, size_t len, int advice)
{
    if (advice == QEMU_MADV_INVALID) {
        errno = EINVAL;
        return -1;
    }
#if defined(CONFIG_MADVISE)
    return madvise(addr, len, advice);
#elif defined(CONFIG_POSIX_MADVISE)
    return posix_madvise(addr, len, advice);
#else
    errno = EINVAL;
    return -1;
#endif
}

/*在osdep.h中看到,只有QEMU configure了CONFIG-MADVISE(检查你的config-host.mak)并且你
的宿主机系统支持MADV_MERGEABLE标准POSIX系统调用,QEMU才可以支持KSM;否则,QEMU就不会去调用POSIX接口来做KSM*/
#if defined(CONFIG_MADVISE)

...
#ifdef MADV_MERGEABLE
#define QEMU_MADV_MERGEABLE MADV_MERGEABLE
#else
#define QEMU_MADV_MERGEABLE QEMU_MADV_INVALID
#endif

KSM最初就是为KVM虚拟化中的使用而开发的,不过它对非虚拟化的系统依然非常有用。

1.5 KSM可能带来的问题

由于KSM对KVM宿主机中的内存使用有较大的效率和性能的提高,所以一般建议打开KSM功能

1.5.1 CPU使用率提高

不过,“金无足赤,人无完人”,KSM必须有一个或多个进程去检测和找出哪些内存页是完全相同可以用于合并的,而且需要找到那些不会经常更新的内存页,这样的页才是最适合于合并的。因此,KSM让内存使用量降低了,但是CPU使用率会有一定程度的升高,也可能会带来隐蔽的性能问题,需要在实际使用环境中进行适当配置KSM的使用,以便达到较好的平衡。

1.5.2 客户机OS和应用程序大不相同时效率不高

KSM对内存合并而节省内存的数量与客户机操作系统类型及其上运行的应用程序有关,如果宿主机上的客户机操作系统相同且其上运行的应用程序也类似,节省内存的效果就会很显著,甚至节省超过50%的内存都有可能的。反之,如果客户机操作系统不同,且运行的应用程序也大不相同,KSM节省内存效率就不高,可能连5%都不到。

1.5.3 足够的交换空间

另外,在使用KSM实现内存过载使用时,最好保证系统的交换空间(swap space)足够大。因为KSM不同客户机的相同内存页合并而减少了内存使用量,但是客户机可能由于需要修改被KSM合并的内存页,从而使这些被修改的内存被重新复制出来占用内存空间,因此可能会导致系统内存的不足,这时就需要有足够的交换空间来保证系统的正常运行。

2 KSM操作实践

2.1 配置守护进程ksmd

内核的KSM守护进程是ksmd,配置和监控ksmd的文件在“/sys/kernel/mm/ksm/”目录下。

2.1.1 ksmd相关配置文件

通过如下命令行可以查看该目录下的几个文件:

[root@kvm-host ~]# ps -eLf | grep -i ksm
root      468    2   468  0  1  2016 ?     00:00:00 [ksmd]
root     1605    1  1605  0  1  2016 ?     00:00:13 /bin/bash /usr/sbin/ksmtuned
[root@kvm-host ~]# ls -l /sys/kernel/mm/ksm/
total 0
-r--r--r-- 1 root root 4096 Dec 31 11:35 full_scans
-rw-r--r-- 1 root root 4096 Dec 31 11:35 max_page_sharing
-rw-r--r-- 1 root root 4096 Dec 31 11:35 merge_across_nodes
-r--r--r-- 1 root root 4096 Dec 31 11:35 pages_shared
-r--r--r-- 1 root root 4096 Dec 31 11:35 pages_sharing
-rw-r--r-- 1 root root 4096 Dec 31 11:35 pages_to_scan
-r--r--r-- 1 root root 4096 Dec 31 11:35 pages_unshared
-r--r--r-- 1 root root 4096 Dec 31 11:35 pages_volatile
-rw-r--r-- 1 root root 4096 Jan  8 10:59 run
-rw-r--r-- 1 root root 4096 Dec 31 11:35 sleep_millisecs
-r--r--r-- 1 root root 4096 Dec 31 11:35 stable_node_chains
-rw-r--r-- 1 root root 4096 Dec 31 11:35 stable_node_chains_prune_millisecs
-r--r--r-- 1 root root 4096 Dec 31 11:35 stable_node_dups

这里面的几个文件对于了解KSM的实际工作状态来说是非常重要的。下面简单介绍各个文件的作用。

  • full_scans:记录已经对所有可合并的内存区域扫描过的次数
  • merge_across_nodes:在NUMA(见7.4节)架构的平台上,是否允许跨节点(node)合并内存页
  • pages_shared:记录正在使用中共享内存页的数量
  • pages_sharing:记录有多少数量的内存页正在使用被合并的共享页,不包括合并的内存页本身。这就是实际节省的内存页数量
  • pages_unshared:记录了守护进程去检查并试图合并,却发现了因没有重复内容不能被合并内存页数量
  • pages_volatile:记录了因为其内容很容易变化不被合并的内存页
  • pages_to_scan:在ksmd进程休眠之前扫描的内存页数量
  • sleep_millisecs:ksmd进程休眠的时间(单位:毫秒),ksmd的两次运行之间的间隔
  • run:控制ksmd进程是否运行的参数,默认值为0,要激活KSM必须要设置其值为1(除非内核关闭了sysfs的功能)。
    • 设置为0,表示停止运行ksmd但保持它已经合并的内存页;
    • 设置为1,表示马上运行ksmd进程;
    • 设置为2表示停止运行ksmd,并且分离已经合并的所有内存页,但是保持已经注册为可合并的内存区域给下一次运行使用。

通过前面查看这些sysfs中的ksm相关的文件可以看出,只有pages_to_scansleep_millisecsrun这3个文件对root用户是可读可写的,其余6个文件都是只读的。

可以向pages_to_scan、sleep_millisecs、run这3个文件中写入自定义的值,以便控制ksmd的运行

例如,

  • “echo 1200>/sys/kernel/mm/ksm/pages_to_scan”,用来调整每次扫描内存页数量

  • “echo 10>/sys/kernel/mm/ksm/sleep_millisecs”,用来设置ksmd两次运行的时间间隔

  • “echo 1>/sys/kernel/mm/ksm/run”,用来激活ksmd的运行

2.1.2 ksm相关数据影响

pages_sharing的值越大,说明KSM节省的内存越多,KSM效果越好。如下命令计算了节省的内存数量:

[root@kvm-host ~]# echo "KSM saved: $(( $(cat /sys/kernel/mm/ksm/pages_sharing) * $(getconf PAGESIZE) / 1024 / 1024 ))MB"
KSM saved: 7429MB

而pages_sharing除以pages_shared得到的值越大,说明相同内存页重复的次数越多KSM效率就越高

pages_unshared除以pages_sharing得到的值越大,说明ksmd扫描不能合并的内存页越多,KSM的效率越低

可能有多种因素影响pages_volatile的值,不过较高的page_voliatile值预示着很可能有应用程序过多地使用了madvise(addr,length,MADV_MERGEABLE)系统调用,将其内存标志为KSM可合并

2.2 ksmtuned: 动态调节ksm

在通过“/sys/kernel/mm/ksm/run”等修改了KSM的设置之后,系统默认不会再修改它的值,这样可能并不能更好地使用后续的系统状况,或者经常需要人工动态调节是比较麻烦的。

2.2.1 ksm和ksmtuned服务

Redhat系列系统(如RHEL 6、RHEL 7)中提供了两个服务ksmksmtuned,来动态调节KSM的运行情况

RHEL 7.3中ksm服务包含在qemu-kvm安装包中,ksmtuned服务包含在qemu-kvm-common安装包中。

在RHEL 7.3上,如果不运行ksm服务程序,则KSM默认只会共享2000个内存页,这样一般很难起到较好的效果。

而在启动ksm服务后,KSM能够共享最多达到系统物理内存一半的内存页

ksm服务的类型是一次性的(one shot),而ksmtuned服务forking类型)一直保持循环执行每间隔若干时间,见下面配置),以调节ksm(/sys/kernel/mm/ksm/下各个参数)

# systemctl status ksm.service
# systemctl status ksmtuned.service

2.2.2 ksmtuned配置文件

ksmtuned服务配置文件在/etc/ksmtuned.conf中。

配置文件的默认内容如下:

[root@kvm-host ~]# cat /etc/ksmtuned.conf 
# Configuration file for ksmtuned.

# How long ksmtuned should sleep between tuning adjustments
# 多久运行一次ksm tune
# KSM_MONITOR_INTERVAL=60

# Millisecond sleep between ksm scans for 16Gb server.
# Smaller servers sleep more, bigger sleep less.
# 会对应设置于/sys/kernel/mm/ksm/sleep_millisecs
# KSM_SLEEP_MSEC=10 

# 下面几个参数条件ksmtuned内部维护的npages变量的变化,这个动态调整的变量实际设置于/sys/kernel
  /mm/ksm/pages_to_scan

# 当空闲内存小于threshhold时,ksm扫描页(npages)增加这个数值
# KSM_NPAGES_BOOST=300
# 当空闲内存大于threshhold时,ksm扫描页(npages)减小这个数值
# KSM_NPAGES_DECAY=-50
# 无论动态算出来的npages值是多少,都不可以超过下面min、max定义的范围。在笔者的128G内存的系统
中,因为富余内存比较多,可以看到/sys/kernel/mm/ksm/pages_to_scan一直被ksmtuned服务设置成1250
# KSM_NPAGES_MIN=64
# KSM_NPAGES_MAX=1250

# 下面两个参数是调整threshhold值,即当free memory低于多少时,触发ksm去合并内存

# CONF参数是一个百分比,如下面默认的20%,表示当空闲内存<系统内存*20%时,触发ksm行为
# KSM_THRES_COEF=20
# 但如果系统内存过小,按上面算出来的内存小于下面这个CONST指定的值,依然设置成这个CONST值
# KSM_THRES_CONST=2048

# uncomment the following if you want ksmtuned debug info
# 打开下面的设置可以debug ksmtuned行为
# LOGFILE=/var/log/ksmtuned
# DEBUG=1

可以看到,ksmtuned其实是一个实时动态调整ksm行为的后台服务,笔者理解它的存在是因为前文我们所讲的KSM本身有利有弊,而有了ksmtuned,方便用户合理有效地使用KSM。

2.2.3 KSM实际操作效果对比

下面演示一下KSM带来的节省内存的实际效果。

物理内存为128GB的系统上,使用了Linux 3.10内核的RHEL 7.3系统作为宿主机,开始时将ksm和ksmtuned服务暂停,“/sys/kernel/mm/ksm/run”的默认值为0,KSM不生效。

然后启动每个内存为8GB的4个Windows 10客户机(没有安装virtio-balloon驱动没有以ballooning方式节省内存),启动ksm和ksmtuned服务,10分钟后检查系统内存的使用情况,以确定KSM的效果。实现该功能的一个示例脚本(ksm-test.sh)如下:

#!/bin/bash
# file: ksm-test.sh

echo "----stoping services: ksm and ksmtuned ..."
systemctl stop ksm
systemctl stop ksmtuned

echo "----'free -m -h' command output before starting any guest."
free -m -h

# start 4 Win10 guest
for i in $(seq 1 4)
do
    qemu-system-x86_64 -enable-kvm -m 8G -smp 4 -drive file=./win10.img,format=raw,if=virtio -device virtio-net-pci,netdev=net0 -netdev bridge,br=virbr0,id=net0 -usb -usbdevice tablet -snapshot -name win10_$i -daemonize
    echo "starting the No. ${i} guest..."
    sleep 5
done

echo "----Wait 2 minutes for guests bootup ..."
sleep 120

echo "----'free -m -h' command output with several guests running ."
free -m -h

echo "----starting services: ksm and ksmtuned ..."
systemctl start ksm
systemctl start ksmtuned

echo "----Wait 10 minutes for KSM to take effect ..."
sleep 600

echo "----'free -m -h' command output with ksm and ksmtuned running."
free -m -h

执行该脚本,其命令行输出如下:

[root@kvm-host ~]# ./ksm-test.sh 
----stoping services: ksm and ksmtuned ...
----'free -m -h' command output before starting any guest.
              total        used        free      shared  buff/cache   available
Mem:           125G        2.9G         82G         84M         40G        121G
Swap:           31G          0B         31G
starting the No. 1 guest...
starting the No. 2 guest...
starting the No. 3 guest...
starting the No. 4 guest...
----Wait 2 minutes for guests bootup ...
----'free -m -h' command output with several guests running .
              total        used        free      shared  buff/cache   available
Mem:           125G         35G         48G         97M         41G         89G
Swap:           31G          0B         31G
----starting services: ksm and ksmtuned ...
----Wait 10 minutes for KSM to take effect ...
----'free -m -h' command output with ksm and ksmtuned running.
              total        used        free      shared  buff/cache   available
Mem:           125G         35G         43G         97M         47G         89G
Swap:           31G          0B         31G

在以上输出中,从ksm、ksmtuned服务开始运行之前和之后的“free-m”命令的“-/+buffers/cache:”这一行的输出数值看到:

1)启动4个8GB客户机以后,系统的空闲内存从82GB减少到48GB(相差34GB),符合要求。

2)启动ksmksmtuned服务以后,等待10分钟,系统空闲内存反而从48GB减少到了43GB,这是为什么呢?KSM不起作用吗?

不是的,是因为ksmtuned里面KSM_THRES_COEF默认设置是20%,系统空闲内存还有48GB(超过总内存的35%),没达到ksmtuned要启动KSM的地步。

我们从/var/log/ksmtuned里面可以找到它的debug信息(事先要在/etc/ksmtuned.conf里面打开debug)。

[root@kvm-host ~]# cat /var/log/ksmtuned
...
Sat Jan 21 14:47:44 CST 2017: committed 0 free 93409576
Sat Jan 21 14:47:44 CST 2017: 26361845 < 131809228 and free > 26361845, stop ksm
Sat Jan 21 14:48:44 CST 2017: committed 0 free 93407360
Sat Jan 21 14:48:44 CST 2017: 26361845 < 131809228 and free > 26361845, stop ksm

我们从/sys/kernel/mm/ksm/下面也可以看到,KSM并没有page share

[root@kvm-host ~]# cat /sys/kernel/mm/ksm/pages_shared 
0

我们把/etc/ksmtuned.conf里面KSM_THRES_COEF设到95,再来做一次这个实验(记得实验前要把ksm、ksmtuned服务关掉,否则下次启动设置不会生效。)

[root@kvm-host ~]# ./ksm-test.sh 
----stoping services: ksm and ksmtuned ...
----'free -m -h' command output before starting any guest.
              total        used        free      shared  buff/cache   available
Mem:           125G        2.9G         82G         85M         40G        121G
Swap:           31G          0B         31G
starting the No. 1 guest...
starting the No. 2 guest...
starting the No. 3 guest...
starting the No. 4 guest...
----Wait 2 minutes for guests bootup ...
----'free -m -h' command output with several guests running .
              total        used        free      shared  buff/cache   available
Mem:           125G         35G         48G         97M         41G         89G
Swap:           31G          0B         31G
----starting services: ksm and ksmtuned ...
----Wait 10 minutes for KSM to take effect ...
----'free -m -h' command output with ksm and ksmtuned running.
              total        used        free      shared  buff/cache   available
Mem:           125G         18G         60G         97M         47G        106G
Swap:           31G          0B         31G
[root@kvm-host ~]# echo "KSM saved: $(( $(cat /sys/kernel/mm/ksm/pages_sharing) * $(getconf PAGESIZE) / 1024 / 1024 ))MB"
KSM saved: 22261MB

这次我们就看到KSM起作用了,它大约节省了22GB内存,从free -m -h和/sys/kernel/mm/ksm/pages_sharing都获得了印证。

此时查看“/sys/kernel/mm/ksm/”目录中KSM的状态,如下:

[root@kvm-host ~]# cat /sys/kernel/mm/ksm/full_scans 
41
[root@kvm-host ~]# cat /sys/kernel/mm/ksm/pages_shared 
607746
[root@kvm-host ~]# cat /sys/kernel/mm/ksm/pages_sharing 
5767606
[root@kvm-host ~]# cat /sys/kernel/mm/ksm/pages_to_scan 
1250
[root@kvm-host ~]# cat /sys/kernel/mm/ksm/pages_unshared 
1257693
[root@kvm-host ~]# cat /sys/kernel/mm/ksm/run
1
[root@kvm-host ~]# cat /sys/kernel/mm/ksm/sleep_millisecs 
10

可见,KSM已经为系统提供了不少的共享内存页,而当前KSM的运行标志(run)设置为1。当然,查看到的run值也可能为0,因为ksm和ksmtuned这两个服务会根据系统状况,按照既定的规则来修改“/sys/kernel/mm/ksm/run”文件中的值,从而调节KSM的运行。

3 QEMU对KSM的控制

由7.3.1节的代码分析我们可以看到,QEMU是通过madvise系统调用告诉内核本进程的内存可以被合并

在相关的代码中,我们发现QEMU内部是有个开关控制的,它开关与否,就是通过-machine(或者-M缩写)参数的mem-merge=on/off来指定的。默认是on,也就是允许内存合并。

我们还是通过上面的实验来说明它的效果。我们把上面的ksm-test.sh脚本稍微改一下,将当中的启动客户机的命令改成如下:

qemu-system-x86_64 -enable-kvm -m 8G -smp 4 -drive file=./win10.img,format=raw, if=virtio -device virtio-net-pci,netdev=net0 -netdev bridge,br=virbr0,id=net0,mac=52:54:00:6a:8b:9$i -usb -usbdevice tablet -snapshot -name win10_$i -M q35,mem-merge=off -daemonize

重复那个实验,我们看到的输出如下:

----stoping services: ksm and ksmtuned ...
----'free -m -h' command output before starting any guest.
              total        used        free      shared  buff/cache   available
Mem:           125G        2.9G         78G        109M         44G        121G
Swap:           31G          0B         31G
starting the No. 1 guest...
starting the No. 2 guest...
starting the No. 3 guest...
starting the No. 4 guest...
----Wait 5 minutes for guests bootup ...
----'free -m -h' command output with several guests running .
              total        used        free      shared  buff/cache   available
Mem:           125G         35G         45G        121M         45G         89G
Swap:           31G          0B         31G
----starting services: ksm and ksmtuned ...
----Wait 10 minutes for KSM to take effect ...
----'free -m -h' command output with ksm and ksmtuned running.
              total        used        free      shared  buff/cache   available
Mem:           125G         35G         44G        121M         45G         89G
Swap:           31G          0B         31G
[root@kvm-host ~]# echo "KSM saved: $(( $(cat /sys/kernel/mm/ksm/pages_sharing) * $(getconf PAGESIZE) / 1024 / 1024 ))MB"
KSM saved: 0MB

可以看到,启动客户机之后,再启动ksm和ksmtuned服务之后,系统的free内存并没有增加。通过/sys/kernel/mm/ksm/pages_sharedpage_sharing等参数也发现,KSM共享内存为0

而通过下面检查/var/log/ksmtuned的debug输出,我们可以看到,KSM其实是尝试合并的,但没有发现可以合并的内存页

[root@kvm-host ~]# cat /var/log/ksmtuned
...
Mon Jan 23 20:12:15 CST 2017: committed 0 free 93735500
Mon Jan 23 20:12:15 CST 2017: 125218766 > 131809228, start ksm
Mon Jan 23 20:12:15 CST 2017: 93735500 < 125218766, boost
Mon Jan 23 20:12:15 CST 2017: KSMCTL start 1250 10
Mon Jan 23 20:13:15 CST 2017: committed 0 free 93713948
Mon Jan 23 20:13:15 CST 2017: 125218766 > 131809228, start ksm
Mon Jan 23 20:13:15 CST 2017: 93713948 < 125218766, boost
Mon Jan 23 20:13:15 CST 2017: KSMCTL start 1250 10

如果我们将实验脚本ksm-test.sh调整为两个客户机mem-merge=on,两个mem-merge=off,实验结果则是节省13G左右

----Wait 2 minutes for guests bootup ...
----'free -m -h' command output with several guests running .
              total        used        free      shared  buff/cache   available
Mem:           125G         35G         44G        129M         45G         89G
Swap:           31G          0B         31G
----starting services: ksm and ksmtuned ...
----Wait 3 minutes for KSM to take effect ...
----'free -m -h' command output with ksm and ksmtuned running.
              total        used        free      shared  buff/cache   available
Mem:           125G         22G         57G        129M         45G        102G
Swap:           31G          0B         31G
[root@kvm-host ~]# echo "KSM saved: $(( $(cat /sys/kernel/mm/ksm/pages_sharing) * $(getconf PAGESIZE) / 1024 / 1024 ))MB"
KSM saved: 14033MB

我们在win10_3的QEMU进程(23710)中可以看到类似这样的VMAmapping,显示是被shared。

[root@kvm-host ~]# cat /proc/23710/smaps
......
7f757fe00000-7f777fe00000 rw-p 00000000 00:00 0 
Size:            8388608 kB
Rss:             8388608 kB
Pss:             2275612 kB
Shared_Clean:          0 kB
Shared_Dirty:    6964916 kB
Private_Clean:         0 kB
Private_Dirty:   1423692 kB
Referenced:      8388608 kB
Anonymous:       8388608 kB
AnonHugePages:     18432 kB
Swap:                  0 kB
KernelPageSize:        4 kB
MMUPageSize:           4 kB
Locked:                0 kB
VmFlags: rd wr mr mw me dc ac sd hg mg
......

对比win10_1的QEMU进程(23666),类似的这个VMA,是没有shared。

[root@kvm-host ~]# cat /proc/23666/smaps
......
7fca7be00000-7fcc7be00000 rw-p 00000000 00:00 0 
Size:            8388608 kB
Rss:             8388608 kB
Pss:             8388608 kB
Shared_Clean:          0 kB
Shared_Dirty:          0 kB
Private_Clean:         0 kB
Private_Dirty:   8388608 kB
Referenced:      8388608 kB
Anonymous:       8388608 kB
AnonHugePages:   8388608 kB
Swap:                  0 kB
KernelPageSize:        4 kB
MMUPageSize:           4 kB
Locked:                0 kB
VmFlags: rd wr mr mw me dc ac sd hg
......

QEMU的-machine q35(或者pc)、mem-merge参数,提供给用户精细化的控制:可以只针对某个或某些客户机,开启或关闭KSM。

你可能感兴趣的:(3. KSM)