参考:

    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特性能提供给客户机更好的性能,但是有些场景并不适用,比如动态迁移可能会失败等,所以要视情景而用。