因为安装MangoDB要禁用THP,就比较好奇原因,所以才有了以下。
Huge Pages(以下简称HP),又叫“大页”(编者注:你看我们搞IT的,翻译起来就是那么的直白生猛),或者叫“标准大页”、“传统大页”——这就是相对Transparent Huge Pages(以下简称THP)“透明大页”来的名字。
我们知道CPU读取数据,顺序一般是:一级缓存-->二级缓存-->内存-->硬盘(不严谨,但是大家都明白这个意思)。读取速度依次变慢。
抛开Cache不谈,我们做个不恰当的比喻,CPU就是售货员,负责拿货给客人,要想速度快,最好的办法就是把商品(程序的数据、指令等)放在柜台(内存)里,但是柜台毕竟有限,而且要装很多种商品(不同的程序),不可能完全放下,那么大量的商品还是会放在后面的仓库(硬盘)。
这样处理,问题:
A、柜台对所有商品是开放的。甲商品可以把柜台里放着的乙商品随意处置,乙商品就懵B了。
B、柜台空间不足,卖的甲商品一旦过多,就得把其他商品挪到仓库里,再把甲商品从仓库提出来放在柜台里。这一进一出,效率极其低下。
C、我们可以将程序分割成小份,先在内存处理A部分,然后从硬盘调取B部分,驻留在内存进行处理。但是现在的程序功能复杂,用户脑洞太大,程序员也无法预测处理完A部分之后,接下来一定就是B部分。
等等吧,以上这些内存的寻址、读取、清理等操作,要全靠程序员来处理,所以打击知道为什么程序员多秃顶了吧。
为了解决这些问题,不让程序员干预内存的处理,就有了虚拟内存技术。
简单地说,在硬盘划出一块,叫SWAP分区,跟物理内存一样,被系统当做内存对待,但毕竟不是真内存,故称虚拟内存。
OS把暂时用不到的数据,放入SWAP区,当要处理的数据不在物理内存中时,从硬盘再读取至内存。
各位看官会说,这和刚才我们说的问题C有什么区别?区别就在“地址”!
在问题C的处理中,程序必须知道数据在内存的地址(比如M1、M2、M9......),还要知道在硬盘的地址(比如D21、D22、D29......)。同一份数据,每次从硬盘读取到内存的地址都是随机的(D21的数据这次在M1,下次可能就在M9)。
而虚拟内存则是把内存、硬盘的地址统一编号(S1、S2、S3......),对于程序来说,这份数据在S3就在S3,不管它是在内存还是硬盘,我不care。
还有其他的好处,比如我们说到的问题A,虚拟内存就可以控制进程对内存的访问权限,再不能随意处理了。对于程序来说,可以分配连续的虚拟内存地址——哪怕物理地址不连续。通过页面调度(从硬盘读取数据至内存,从内存写数据至硬盘)算法——先进先出(FIFO)、最近最少使用(LRU)、最佳页面替换(OPT)等,尽量避免问题B中,装入装出大量数据造成的性能浪费。不再一一解释。
关键在于虚拟内存地址,它毕竟不是真实的地址,程序说我要S1的数据,CPU就必须给出真实的地址(M1或D21),这块工作是有Translation Lookaside Buffer(TLB)来做的,TLB通过页表(Page Table)这种数据结构,缓存了虚拟页与物理页的映射关系。打个比方,有点类似虚拟地址:物理地址这样的键值对(当然没那么简单,大家理解即可)。
但是当我们使用Oracle、MangoDB这样需要大内存的应用时,可想而知,这个页表会很大很大。我们知道Linux管理内存,是以4K为一个页面进行管理的。当数据很大的时候,除以4K,所需的页表也会越来越大,维护页表就变得很消耗资源。
举个例子,一个公务员如果想建立一个居民信息表,要是以家庭为单位,那么映射表就会很大,解决办法呢?我们就用小区为单位吧~~~
这就是“大页”(Huge Pages),更大的页!同样的数据,除以4K,需要多少条目,除以2M(HP默认的大小),又需要多少条目,不言而喻。
终于说到本文主题了,不过好像可说的也不多了。
THB相对于HB来说,区别主要在于HB是要预分配的,而THB则是由khugepaged进程进行动态分配。可想而知,对于DB这种内存操作频繁的应用,预分配的更省事,第一次搞好即可,不用每次现分配。Oracle就要求关闭Linux默认启用的THB。
今天是2019乙亥猪年初一,文章前两天就开始边查资料边写,很仓促,里面很多知识点没有写,比如虚拟内存、HB的优点、HB/TLB的各种操作都没有写,以后有机会再写吧。即便是文章写道的也肯定会有谬误,请大家批评指正。
祝大家新春玉快,阖家欢落~~~