本文将分析是否Huge Page在任何条件下(特别是NUMA架构下)都能带来性能提高。node
http://cenalulu.github.io/linux
http://cenalulu.github.io/linux/huge-page-on-numa/git
文章欢迎转载,但转载时请保留本段文字,并置于文章的顶部
做者:卢钧轶(cenalulu)
本文原文地址:http://cenalulu.github.io/linux/huge-page-on-numa/github
在阅读本文以前,须要读者至少了解如下基础知识数据库
Chip Multi Processing aware Linux Kernel Scheduler
论文在正式开始本文分析前,咱们先大概介绍下Huge Page的历史背景和使用场景。数组
为何须要Huge Page
了解CPU Cache大体架构的话,必定听过TLB Cache。Linux
系统中,对程序可见的,可以使用的内存地址是Virtual Address
。每一个程序的内存地址都是从0开始的。而实际的数据访问是要经过Physical Address
进行的。所以,每次内存操做,CPU都须要从page table
中把Virtual Address
翻译成对应的Physical Address
,那么对于大量内存密集型程序来讲page table
的查找就会成为程序的瓶颈。因此现代CPU中就出现了TLB(Translation Lookaside Buffer) Cache用于缓存少许热点内存地址的mapping关系。然而因为制形成本和工艺的限制,响应时间须要控制在CPU Cycle级别的Cache容量只能存储几十个对象。那么TLB Cache在应对大量热点数据Virual Address
转换的时候就显得捉襟见肘了。咱们来算下按照标准的Linux页大小(page size) 4K,一个能缓存64元素的TLB Cache只能涵盖4K*64 = 256K
的热点数据的内存地址,显然离理想很是遥远的。因而Huge Page就产生了。
Tips: 这里不要把Virutal Address
和Windows上的虚拟内存搞混了。后者是为了应对物理内存不足,而将内容从内存换出到其余设备的技术(相似于Linux的SWAP机制)。缓存
什么是Huge Page
既然改变不了TLB Cache的容量,那么只能从系统层面增长一个TLB Cache entry所能对应的物理内存大小,从而增长TLB Cache所能涵盖的热点内存数据量。假设咱们把Linux Page Size
增长到16M
,那么一样一个容纳64个元素的TLB Cache就能顾及64*16M = 1G
的内存热点数据,这样的大小相较上文的256K
就显得很是适合实际应用了。像这种将Page Size
加大的技术就是Huge Page
。session
了解了Huge Page的由来和原理后,咱们不难总结出能从Huge Page受益的程序必然是那些热点数据分散且至少超过64个4K Page Size的程序。此外,若是程序的主要运行时间并非消耗在TLB Cache Miss后的Page Table Lookup上,那么TLB再怎么大,Page Size再怎么增长都是徒劳。在LWN的一篇入门介绍中就提到了这个原理,而且给出了比较详细的估算方法。简单的说就是:先经过oprofile
抓取到TLB Miss
致使的运行时间占程序总运行时间的多少,来计算出Huge Page所能带来的预期性能提高。
简单的说,咱们的程序若是热点数据只有256K,而且集中在连续的内存page上,那么一个64个entry的TLB Cache就足以应付了。说道这里,你们可能有个疑问了:既然咱们比较难预测本身的程序访问逻辑是否能从开启Huge Page中受益。反正Huge Page看上去只改了一个Page Size,不会有什么性能损失。那么咱们就索性对全部程序都是用Huge Page好啦。
其实这样的想法是彻底错误的!也正是本文想要介绍的一个主要内容,在目前常见的NUMA体系下Huge Page也并不是万能钥匙,使用不当甚至会使得程序或者数据库性能降低10%。下面咱们重点分析。架构
Large Pages May Be Harmful on NUMA Systems一文的做者曾今作过一个实验,测试Huge Page在NUMA环境的各类不一样应用场景下带来的性能差别。从下图能够看到Huge Page对于至关一部分的应用场景并不能很好的提高性能,甚至会带来高达10%的性能损耗。
app
性能降低的缘由主要有如下两点
对于写操做密集型的应用,Huge Page会大大增长Cache写冲突的发生几率。因为CPU独立Cache部分的写一致性用的是MESI协议
,写冲突就意味:
类比到数据库就至关于,原来一把用来保护10行数据的锁,如今用来锁1000行数据了。必然这把锁在线程之间的争抢几率要大大增长。
从下图咱们能够看到,本来在4K小页上能够连续分配,并由于较高命中率而在同一个CPU上实现locality的数据。到了Huge Page的状况下,就有一部分数据为了填充统一程序中上次内存分配留下的空间,而被迫分布在了两个页上。而在所在Huge Page中占比较小的那部分数据,因为在计算CPU亲和力的时候权重小,天然就被附着到了其余CPU上。那么就会形成:本该以热点形式存在于CPU2 L1或者L2 Cache上的数据,不得不经过CPU inter-connect去remote CPU获取数据。
假设咱们连续申明两个数组,Array A
和Array B
大小都是1536K。内存分配时因为第一个Page的2M没有用满,所以Array B
就被拆成了两份,分割在了两个Page里。而因为内存的亲和配置,一个分配在Zone 0,而另外一个在Zone 1。那么当某个线程须要访问Array B时就不得不经过代价较大的Inter-Connect去获取另一部分数据。
delays re-sulting from traversing a greater physical distance to reach a remote node, are not the most important source of performance overhead. On the other hand, congestion on interconnect links and in memory controllers, which results from high volume of data flowing across the system, can dramatically hurt performance.
Under interleaving, the memory latency re- duces by a factor of 2.48 for Streamcluster and 1.39 for PCA. This effect is entirely responsible for performance improvement under the better policy. The question is, what is responsible for memory latency improvements? It turns out that interleaving dramatically reduces memory controller and interconnect congestion by allevi- ating the load imbalance and mitigating traffic hotspots.
咱们先谈谈理想状况。上文提到的论文其实他的主要目的就是讨论一种适用于NUMA架构的Huge Page自动内存管理策略。这个管理策略简单的说是基于Carrefour
的一种对Huge Page优化的变种。(注:不熟悉什么是Carrefour
的读者能够参看博客以前的科普介绍或者阅读原文)
下面是一些相关技术手段的简要归纳:
False Sharing
,监控形成大量Cache Miss的Page,并进行拆分重组。将同一CPU亲和的数据放在同一个Page中谈完了理想,咱们看看现实。现实每每是残酷的,因为没有硬件级别的PMU(Performance Monitor Unit)支持,获取精准的Page访问和Cache Miss信息性能代价很是大。因此上面的理想仅仅停留在实验和论文阶段。那么在理想实现以前,咱们如今该怎么办呢?
答案只有一个就是测试
实际测试
实际测试的结果最具备说服力。所谓实际测试就是把优化对象给予真实环境的压力模拟。经过对比开启和关闭Huge Page时的性能差异来验证Huge Page是否会带来性能提高。固然大多数应用程序,要想模拟真实环境下的运行状况是很是困难的。那么咱们就能够用下面这种理论测试
理论测试
理论测试能够经过profile预估出Huge Page可以带来的潜在提高。具体原理就是计算当前应用程序运行时TLB Miss致使的Page Walk成本占程序总执行时间的占比。固然这种测试方式没有把上文提到的那两种性能损失考虑进去,因此只能用于计算Huge Page所能带来的潜在性能提高的上限。若是计算出来这个值很是低,那么能够认为使用Huge Page则会带来额外的性能损失。具体方法见LWN上介绍的方法
具体的计算公式以下图:
若是没有hardware的PMU支持的话,计算须要用到oprofile
和calibrator
。
并非全部的优化方案都是0性能损失的。充分的测试和对于优化原理的理解是一个成功优化的前提条件。