参考:
http://tech.it168.com/a2016/1101/3005/000003005933.shtml(ksm)
http://www.cnblogs.com/dongzhiquan/p/5043912.html(大页内存优点)
简介:
cow:copy on write,也就是写时复制。这是一种内存共享技术,在linux中当使用fork 函数创建一个进程时,子进程和父进程共享全部的内存,当这片共享的内存区域被进程试图修改的时候,内核会分配一块新的内存区域,并将被试图修改的共享内存区域复制到新的内存区域上,然后再让进程去修改内存区域。
ksm:kernel SamePage Merging。 ksm让内核扫描正在运行中的所有程序,并比较它们的内存,如果发现它们的内存页有相同的,那么就把它们相同的内存页合并为一个内存页,并将其标识为“写时复制”,当标识为“写时复制”的内存页需要被修改时,内核就为其分配新的内存空间,并复制内存页到新的空间,在新的内存空间上进行修改。
ksm设计初衷就是为了给虚拟化节约内存的,因为如果客户机都使用相同的系统和运行类似的程序,那么每个客户机进程就会有很大一部分的内存页是相同的,这时候使用ksm技术就能大大降低内存的使用率。也方便kvm内存的过载使用,传说有人在16G内存的机器上,成功运行52个1G内存的xp客户机。
所以ksm的优点显而易见,但是它的缺点也是很明显的。ksm需要扫描相同的内存页,这就带来了开销,而且ksm自身也需要占用内存,当机器运行的程序没有什么耦合度的话,那么ksm不见得能提升内存效率。而且使用ksm还需要保证足够的内存交换空间,因为我们把多个内存页合并为一个,当内存耗尽,而恰好有内存页需要修改时,此时内存就溢出了,所以需要swap交换空间过渡下。
ksm的使用:
内核的ksm守护进程时ksmd,我们可以通过修改/sys/kernel/mm/ksm/下的ksmd参数来对其进行配置,它的参数有如下几种(参考https://www.kernel.org/doc/Documentation/vm/ksm.txt):
full_scans:对可合并的内存区域扫描过的次数
pages_shared:记录合并后共有多少内存页
pages_sharing:记录有多少内存页正在使用被合并的共享页,不包括合并的内存页本身
pages_to_scan:ksmd进程休眠前扫描的内存页个数,(我的理解是一次扫描的内存页个数)
pages_unshared:因为没有重复内容而不能被合并的内存页数量
pages_volatile:因为内容很容易变化而不能被合并的内存页数量
run:是否开启ksm
0:表示停止ksmd但保持它已经合并的内存页
1:运行ksmd
2:停止ksmd并分离已合并的内存页
sleep_millisecs:ksmd休眠的时间,也就是是两次运行的间隔
虽然参数有这么多,但是我们可以操作的只有run、sleep_millisecs、pages_to_scan,使用也很简单:
echo “$num" >/sys/kernel/mm/ksm/PARAMATER
当然,手动操作很蛋疼,redhat在qemu-kvm的rpm包,整合了ksm 和ksmtuned两个管理工具(在/etc/init.d下的脚本)
ksm:操作ksmd的功能,也就是利用这个脚本可以echo “$num" >/sys/kernel/mm/ksm/PARAMATER
ksmtuned:可以智能地判断什么时候该开启ksmd什么时候该关闭并调节ksmd参数的程序,其配置文件为/etc/ksmtuned.conf
pages_shared和page_sharing的区别:
我的理解是这样的,假设进程A、B、C各占用3个内存页,而且他们所占用的内存页都可以合并,那么page_shared=3而page_sharing=6 也就是实际节约的内存数量。kernel文档解释如下:
pages_shared - how many shared pages are being used
pages_sharing - how many more sites are sharing them i.e. how much saved
大页内存:
优缺点参考http://www.cnblogs.com/dongzhiquan/p/5043912.html,因为我没太理解,这里只记录配置。
配置:
(1)查看硬件和内核是否支持
cat /proc/cpuinfo |grep --color pdpe1gb #这里是1不是L,有结果就代表支持
[root@localhost ~]# grep -i hugetlb /boot/config-2.6.32-431.el6.x86_64
CONFIG_HUGETLBFS=y#两者都为y就代表支持
CONFIG_HUGETLB_PAGE=y
(2)修改宿主机的grub.conf,配置内核启动参数,内容如下:
title CentOS (2.6.32-431.el6.x86_64)
root (hd0,0)
kernel /vmlinuz-2.6.32-431.el6.x86_64 ro root=/dev/mapper/VolGroup-lv_root hugepagesz=2MB hugepages=512 default_hugepagesz=2MB intel_iommu=on rd_NO_LUKS rd_NO_MD rd_LVM_LV=VolGroup/lv_swap crashkernel=auto LANG=en rd_LVM_LV=VolGroup/lv_root KEYBOARDTYPE=pc KEYTABLE=us rd_NO_DM rhgb quiet
initrd /initramfs-2.6.32-431.el6.x86_64.img
增加了hugepagesz(内存页大小)、hugepages(内存页数量)、default_hugepagesz(默认内存页大小)三个参数,必须注意的是这里的hugepagesz*hugepages不能大于物理内存大小,我这里设置了512个2MB 内存页
(3)挂载使用hugetlbfs文件系统
可以先查看未分配前的内存页大小:
[root@localhost ~]# cat /proc/meminfo |grep -i huge
AnonHugePages: 0 kB
HugePages_Total: 512
HugePages_Free: 512
HugePages_Rsvd: 0
HugePages_Surp: 0
Hugepagesize: 2048 kB
挂载:
mount -t hugetlbfs hugetlbfs /dev/hugepages
(mount -t hugetlbfs hugetlbfs /dev/hugepages -o remount,pagesize=1GB 这条可以重新指定内存页大小,但是这里设置1G没什么用,因为1GB大页需要在启动时分配)
安装libhugetlbfs库:(对大页的支持需要调用这个库)
yum install libhugetlbfs libhugetlbfs-utils
#libhugetlbfs-utils包提供一些有用的工具,比如可以用hugeadm --pool-list查看大页内存状态
使用:
qemu-system-x86_64 -m 1000M /home/kvm_vhost/redhat6.qcow2 -mem-path /dev/hugepages/
#这里-m指定的内存大小不能大于挂载的内存页大小,否则报“file_ram_alloc: can't mmap RAM pages: Cannot allocate memory”错,而不能使用大页的功能
再查看:
[root@localhost ~]# cat /proc/meminfo |grep -i huge
AnonHugePages: 4096 kB
HugePages_Total: 512
HugePages_Free: 405
HugePages_Rsvd: 401
HugePages_Surp: 0
Hugepagesize: 2048 kB
发现使用了100多个内存页,也就是占用了200多M内存
透明大页(transparent hugepage):
普通大页(huge page)有以下几个缺点:
(1)大页需要事先分配(1GB大页还只能在启动时分配)
(2)程序代码必须显示使用大页,不使用就会造成物理内存浪费
(3)大页必须常驻在物理内存中,不能交换到分区
(4)需要root权限来挂载hugetlbfs文件系统
透明大页避免了上述缺点,而又享有大页的优势。透明大页对任何程序都是透明的,程序不需要任何修改即可使用透明大页。在使用透明大页时,普通的大页仍然可以使用,只有没有普通大页可以使用时,才使用透明大页。透明大页是可以交换的,当物理内存不足需要被交换时,它被打碎成常规的4KB大小的内存页,当物理内存充裕时,常规的页分配内存可以通过khugepaged进程自动迁往透明大页。
配置:
查看内核是否支持:
root@localhost ~]# cat /boot/config-2.6.32-431.el6.x86_64 |grep -i transparent
CONFIG_TRANSPARENT_HUGEPAGE=y
配置透明大页的使用方式:
[root@localhost ~]# cat /sys/kernel/mm/transparent_hugepage/enabled
[always] madvise never
[root@localhost ~]# echo "never" >/sys/kernel/mm/transparent_hugepage/enabled
[root@localhost ~]# cat /sys/kernel/mm/transparent_hugepage/enabled
always madvise [never]
always:表示尽可能地使用透明大页
madvise:表示仅在“MADV_HUGEPAGE”标识的内存区域使用透明大页(预防申请了2MB大页但是只写入1B数据的情况)
never:不使用
查看透明大页大小:
[root@localhost ~]# cat /proc/meminfo |grep -i anonhuge
AnonHugePages: 6144 kB
AVX和XSAVE:(这方面的我看不懂..只写查看是否支持和启用方法)
查看:
cat /proc/cpuinfo |grep avx |grep xsave
使用:
就是加个 -cpu host参数:
qemu-system-x86_64 -m 1024 -cpu host /home/kvm_vhost/redhat6.qcow2
AES-NI:提升系统对AES加密算法的效率(AES是种对称加密算法,详情可参考我写的加密算法篇)
有个别硬件平台需要bios的支持:
advanced-->Processor Configuration-->AES-NI Defeature
查看内核支持:
[root@localhost ~]# cat /boot/config-2.6.32-431.el6.x86_64 |grep -i aes
CONFIG_SND_MAESTRO3=m
CONFIG_CRYPTO_AES=m
CONFIG_CRYPTO_AES_X86_64=m
CONFIG_CRYPTO_AES_NI_INTEL=m#需要这行,模块的话需要查看是否加载
CONFIG_CRYPTO_DEV_PADLOCK_AES=m
查看硬件支持:
cat /proc/cpuinfo |grep aes
查看是否加载模块:
lsmod |grep aesni
modprobe aesni_intel
(我这里alias grep="grep --color")
使用:可以使用-cpu host 或-cpu qemu64,+aes参数
qemu-system-x86_64 -m 1024 -cpu host /home/kvm_vhost/redhat6.qcow2
完全暴露cpu特性:
其实就是-cpu选项
-cpu host:尽可能地暴露cpu特性给客户机,有些特性kvm还没支持,所以宿主机和客户机的cpu特性可能不一样
-cpu qemu64,+aes:qemu64代表cpu模型,+aes代表aes特性,同样也可以+其他特性
尽管暴露cpu特性能提供给客户机更好的性能,但是有些场景并不适用,比如动态迁移可能会失败等,所以要视情景而用。