简述优化 Linux 内存性能的核心思想
原文:linux网络虚拟化
今天分享一篇内存性能优化的文章,文章用了大量精美的图深入浅出地分析了 Linux 内核 slab 性能优化的核心思想。
slab是 Linux 内核小对象内存分配最重要的算法,文章分析了内存分配的各种性能问题(在不同的场景下面),并给出了这些问题的优化方案,这个对我们实现高性能内存池算法,或以后遇到内存性能问题的时候,有一定的启发,值得我们学习。
单CPU上单纯的slab
下图给出了单 CPU 上 slab 在分配和释放对象时的情景序列:
可以看出,非常之简单,而且完全达到了slab设计之初的目标。
扩展到多核心CPU
现在我们简单地将上面的模型扩展到多核心CPU,同样差不多的分配序列如下图所示:
问题
首先,我们来看一个简单的问题,如果单独的某个CPU的 slab 缓存没有对象可分配了,但是其它 CPU 的 slab 缓存仍有大量空闲对象的情况,如下图所示:
这是可能的,因为对单独一种slab的需求是和该CPU上执行的进程/线程紧密相关的,比如 如果CPU0只处理网络,那么它就会对skb等数据结构有大量的需求,对于上图最后引出的问题,如果我们选择从伙伴系统中分配一个新的page(或者pages,取决于对象大小以及slab cache的order),那么久而久之就会造成slab在CPU间分布的不均衡,更可能会因此吃掉大量的物理内存,这都是不希望看到的。
问题的解决-分层slab cache
无级变速总是让人向往。如果一个CPU的slab缓存满了,直接去抢同级别的别的CPU的slab缓存被认为是一种鲁莽且不道义的做法。
那么为何不设置另外一个slab缓存,获取它里面的对象不像直接获取CPU的slab缓存那么简单且直接,但是难度却又不大,只是稍微增加一点消耗,这不是很好吗?
事实上,CPU的L1,L2,L3 cache不就是这个方案设计的吗?这事实上已经成为cache设计的不二法门。这个设计思想同样作用于slab,就是Linux内核的slub实现,现在可以给出概念和解释了。
Linux kernel slab cache:一个分为3层的对象cache模型。
Level 1 slab cache:一个空闲对象链表,每个CPU一个的独享cache,分配释放对象无需加锁。
Level 2 slab cache:一个空闲对象链表,每个CPU一个的共享page(s) cache,分配释放对象时仅需要锁住该page(s),与Level 1 slab cache互斥,不互相包容。
Level 3 slab cache:一个page(s)链表,每个NUMA NODE的所有CPU共享的cache,单位为page(s),获取后被提升到对应CPU的Level 1 slab cache,同时该page(s)作为Level 2的共享page(s)存在。
共享page(s):该page(s)被一个或者多个CPU占有,每一个CPU在该page(s)上都可以拥有互相不充图的空闲对象链表,该page(s)拥有一个唯一的Level 2 slab cache空闲链表,该链表与上述一个或多个Level 1 slab cache空闲链表亦不冲突,多个CPU获取该Level 2 slab cache时必须争抢,获取后可以将该链表提升成自己的Level 1 slab cache。
其行为如下图所示:
2个场景
事实上,对于多个CPU共享一个page(s)的情况,还可以有另一种玩法,如下图所示:
伙伴系统
尽量分配尽可能大的内存
尽量合并连续的小块内存成一块大内存
我们可以通过下面的图解来理解上面的原则:
小结
多CPU操作系统内核中,关键的开销就是锁的开销。
我认为这是一开始的设计导致的,因为一开始,多核CPU并没有出现,单核CPU上的共享保护几乎都是可以用“禁中断”,“禁抢占”来简单实现的,到了多核时代,操作系统同样简单平移到了新的平台,因此同步操作是在单核的基础上后来添加的。
简单来讲,目前的主流操作系统都是在单核年代创造出来的,因此它们都是顺应单核环境的,对于多核环境,可能它们一开始的设计就有问题。
不管怎么说,优化操作的不二法门就是禁止或者尽量减少锁的操作。随之而来的思路就是为共享的关键数据结构创建"每CPU的缓存“,而这类缓存分为两种类型:
比如路由表之类的数据结构,你可以用RCU锁来保护,当然如果为每一个CPU都创建一个本地路由表缓存,也是不错的,现在的问题是何时更新它们,因为所有的缓存都是平级的,因此一种批量同步的机制是必须的。
2. 管理机制缓存
比如slab对象缓存这类,其生命周期完全取决于使用者,因此不存在同步问题,然而却存在管理问题。
采用分级cache的思想是好的,这个非常类似于CPU的L1/L2/L3缓存,采用这种平滑的开销逐渐增大,容量逐渐增大的机制,并配合以设计良好的换入/换出等算法,效果是非常明显的。
最近很多小伙伴找我要一些程序员必备资料,于是我翻出了压箱底的宝藏,免费分享给大家!
扫描海报二维码免费获取。