redis服务器上开启了THP(Transparent Huge Pages)。

1) Linux本身的页大小是固定的4KB,在2.6.38内核新增了THP,透明地支持huge page(2MB)的使用,并且默认开启。开启THP的优势在于:


        - 减少page fault。一次page fault可以加载更大的内存块。


        - 更小的页表。相同的内存大小,需要更少的页。


        - 由于页表更小,虚拟地址到物理地址的翻译也更快。


    劣势在于:


        - 降低分配内存效率。需要大块、连续内存块,内核线程会比较激进的进行compaction,解决内存碎片,加剧锁争用。


        - 降低IO吞吐。由于swapable huge page,在swap时需要切分成原有的4K的页。Oracle的测试数据显示会降低30%的IO吞吐。



2) 对于redis而言,开启THP的优势在于:


        - fork子进程的时间大幅减少。fork进程的主要开销是拷贝页表、fd列表等进程数据结构。由于页表大幅较小(2MB / 4KB = 512倍),fork的耗时也会大幅减少。


   劣势在于:


        - fork之后,父子进程间以copy-on-write方式共享地址空间。如果父进程有大量写操作,并且不具有locality,会有大量的页被写,并需要拷贝。同时,由于开启THP,每个页2MB,会大幅增加内存拷贝。




3) 针对这个特性,我做了一个测试,分别在开启和关闭THP的情况下,测试redis的fork、响应时间。


     测试条件:


        redis数据集大小:16G


        rdb文件大小:3.4G


        ./redis-benchmark -P 4 -t set -r 5000000 -n 1000000000



    (1) fork时间对比


开启THP后,fork大幅减少。




redis cluster ping超时 redis请求超时处理_页表



(2)超时次数


        使用redis-benchmark测试,单个kv只有几字节,没办法模拟真实线上的延迟,这里任务延迟超过300us的请求即为超时,统计这些请求的个数。


        开启THP后,超时次数明显增多,但是每次超时时间较短。而关闭THP后,只有4次超时,原因是与fork在同一事件循环的请求受到fork的影响,chu'l。


关闭THP影响的只是零星几个请求,而开启后,虽然超时时间短了,但是影响面扩大了。


redis cluster ping超时 redis请求超时处理_linux_02


redis cluster ping超时 redis请求超时处理_页表_03




4)查看THP状态


$ cat /sys/kernel/mm/transparent_hugepage/enabled 


        [always] madvise never


always表示总是开启, madvise根据程序的配置开启,never关闭。



关闭THP


sudo echo never >  /sys/kernel/mm/transparent_hugepage/enabled


需要重启进程




5) 结论


    集合业界的经验,建议关闭我们线上redis、mysql、mongodb等机器的THP。



6)references


     Transparent Huge Pages


    各种坑:


https://blogs.oracle.com/linux/entry/performance_issues_with_transparent_huge


http://docs.splunk.com/Documentation/Splunk/6.2.3/ReleaseNotes/SplunkandTHP


http://structureddata.org/2012/06/18/linux-6-transparent-huge-pages-and-hadoop-workloads/


http://antirez.com/news/84