`
totoxian
  • 浏览: 1071259 次
  • 性别: Icon_minigender_2
  • 来自: 西安
文章分类
社区版块
存档分类
最新评论

slab着色--一种必然认输的妥协

 
阅读更多

在最新的linux2.6.28内核当中已经不见slab着色的踪迹了,记得研究2.6.9的时候,我还为理解slab着色大伤脑筋,而实际上我当时根本没有理解它的设计初衷以及最终的效果,只是把它当成了一个纯粹的“算法”来玩,还玩得不亦乐乎...
slab的目的是什么?其实它是为了在软件缓存和硬件缓存冲突的时候达成的一种妥协,而普遍的观点是只有相互平等的当事者才具有妥协的可能,如果关系根本 tmd就不平等,那么妥协只是可怜的一厢情愿而已。那么硬件和软件平等吗?在高处看的话是平等的,我们常说硬件的功能完全可以用软件模拟,想象一下,一个cpu 就可以模拟很多的专业电路,靠的就是cpu执行的软件指令,内部是布尔逻辑解决的,诸多的布尔逻辑组成了复杂的算法,完全模拟了专业的硬件连线逻辑,但是 我们不从功能上谈,从别的方面想想,它们就不那么平等了,首先它们的层次不同,计算机硬件往往只是提供了一个平台,一个场地,它提供的是彼此正交的指令系 统,具体怎么发挥要看软件的算法设计,可以说硬件提供了机制而软件实现了策略,如果所有的策略都由硬件直接实现,那么就回到了工业革命或者电气革命时代, 软件工业就消失了,可现实是软件发展的如火如荼,现在硬件发展的已经相当成熟了(摩尔定律制约),我们说一旦出了问题,先不要想是不是机制有问题,而是先 想想是不是我的策略没有用好机制,就好像你在linux上写了一个程序,结果出了些问题,那么不要一开始就怀疑内核出了问题,当然问题的修正,不管是本质 问题还是效率问题都应该应用程序来修正而不能为了迎合一个应用程序的策略而大修改内核机制。同样的道理,当slab代表的软件缓存和cpu硬件cache 有冲突的时候,那么需要修正的也是软件slab缓存。在具体分析之前我为了节省脑细胞(呵呵,主要是我的文笔太差,想表达一个意思对我来说很有难度,因此 我老婆总说读我的东西总像在读翻译得很糟糕的中译本)我先引用一段:
另一个slab allocator注意到的问题是cpu cache的使用率.一般的cache算法是
cache location = address % cache_size
一 般的power of two配置法配置的内存都会经过align(对齐)(首次模仿袁老), 并且大多数程式的习惯会把最常用的资料栏位放在一个结构的最前面. 这两个效应合在一起, 造成这些栏位互相的清掉彼此的cache. 512kb的cache可能只有部分有作用. 更甚者, 如果主记忆体使用interleave的方式, 比如说SPARC center 2000 使用两个bus, 较低的256byte使用第一个bus,较高的256byte使用第二个bus, 那麽所有的data可能会集中在第一个bus上, 造成不平衡现象.
Slab的解决方法是在向paging系统取得一块block之後, (假设为1KB), Slab把他要用的资料摆在这个block最後面, 假设占y bytes. 假设所要配置的是inode, 大小跟前面Mach的例子一样皆是104. 那麽这块记 忆体可以提供(1024-y)/104个inode. 并且有一些馀数, 也就是剩下一些多馀的记忆体.Slab善用这些记忆体, 将之二等分, 一份摆在这块记忆体的最前面,一块摆在最後面. 最前面那块称为coloring area. Slab设法在每次配置的page上使用不同大小的coloring area, 以有效的 分散资料map到cache中的位置,增加cache rate.
(**)Allocator Footprint指的是Allocator在配置记忆体的时候将自己,以及所参考到的资料写到cpu cache/ TLB (translation lookaside buffer), 在cache/TLB上面产生的"脚印". Allocator在cache/TLB内 所留下的资料基本上是没有用的, 并且妨碍真正有用的资料留在cache上. buddy演算法需要参考许多资料才能配置记忆体, 会产生大量的"footprint", 导致cache miss增加. McKusick-Karels和zone allocator的足迹皆很小, 原因是配置记忆体的时候直接从free list上把第一个element抓出来而已. 所以一个好的配置法应该使用简单的演算来配置 物件.Slab也是使用相同的原则, 不论是配置或者是释放,都是简单的一两行运算而已,所以foot print也很小.
原文是台湾的繁体中文,而且用不同的表达词汇,我就不翻译了,大致可以看懂(我们都是炎黄子孙)。slab是好的,因为提前缓存了初始化好的频繁被用到的 结构体,但是由于对齐问题而会造成cpu的cache频频失效,那么软件的解决方法就是slab着色,注意,cpu的cache频频失效就是所谓的冲突, 冲突发生了,软件解决之,不能让cpu cache进行改进,因为那是机制,软件才是策略,于是slab着色由运而生。slab着色的本质就是让slab缓存的对象在cpu的cache里面彼此 错开,这样就不会造成cpu cache频频失效了,否则,经过对齐的很多slab对象都会map到cpu cache的相同位置,这实在不是我们想看到的,cpu cache失效带来的损失抵消了一部分slab缓存带来的性能提高。以上引用的仅仅是从原理上描述的,下面我列举出linux内核中的实现代码:
struct slab {
struct list_head list;
unsigned long colouroff; //该slab的第一个对象的偏移,这个偏移实现了slab对象的错位
void *s_mem; //对象的内存地址,需要对象的时候从这里分配。
unsigned int inuse; //slab中的活动对象数目。
kmem_bufctl_t free;
unsigned short nodeid;
};
struct kmem_cache * kmem_cache_create (const char *name, size_t size, size_t align, unsigned long flags, void (*ctor)(void*, struct kmem_cache *, unsigned long), void (*dtor)(void*, struct kmem_cache *, unsigned long))
{
size_t left_over, slab_size, ralign;
struct kmem_cache *cachep = NULL;
struct list_head *p;
...
cachep = kmem_cache_zalloc(&cache_cache, SLAB_KERNEL);
size = ALIGN(size, align);
left_over = calculate_slab_order(cachep, size, align, flags); //这个left_over就是上述引用的文字中的“多馀的记忆体”
...
slab_size = ALIGN(cachep->num * sizeof(kmem_bufctl_t) + sizeof(struct slab), align);
...
cachep->colour_off = cache_line_size(); //偏移就是cpu cache line的大小
...
cachep->colour = left_over / cachep->colour_off; //颜色的大小就是能错位的最大的数目,比如剩余的内存大小是20,cpu缓存行的大小是4,那么最多可以偏移到5个单位,一个单位是20/5=4
...
}
static int cache_grow(struct kmem_cache *cachep, gfp_t flags, int nodeid)
{
struct slab *slabp;
void *objp;
size_t offset;
...
struct kmem_list3 *l3;
...
offset = l3->colour_next;
l3->colour_next++; //colour_next字段代表的就是当前偏移到第几个单位了
if (l3->colour_next >= cachep->colour) //当偏移的单位超过了总的最大的偏移单位数目,那么当前偏移单位值回归为0。
l3->colour_next = 0;
spin_unlock(&l3->list_lock);
offset *= cachep->colour_off; //当前要分配的slab的对象要从offset开始,这个offset和上一个slab错开了l3->colour_next和单位,每个单位的大小为colour_off
...
objp = kmem_getpages(cachep, flags, nodeid);
...
slabp = alloc_slabmgmt(cachep, objp, offset, local_flags, nodeid); //分配slab
...
list_add_tail(&slabp->list, &(l3->slabs_free));
...
}
static struct slab *alloc_slabmgmt(struct kmem_cache *cachep, void *objp, int colour_off, gfp_t
local_flags, int nodeid)
{
struct slab *slabp;
...
slabp->inuse = 0;
slabp->colouroff = colour_off; //初始化偏移
slabp->s_mem = objp + colour_off; //该slab的对象地址从当前偏移处开始,这里可以看出这个slab的对象和上一个错开了colour_off大小,这样可能就在cpu的cache里 面错开了,但是大多数情况效果甚微
...
}
看到最后一个函数alloc_slabmgmt的最后一段注释,说效果甚微,这是为什 么呢?这其实就是最终撤销slab着色的原因之一。我们看到如果slab的数目只有cachep->colour个的话,这个slab着色的效果就 太好了,但是这往往不太现实,slab的数目有时是相当大的,这样的话,slab着色实际上只是帮了一点点小忙而已,它仅仅保证了最开始的几个slab不 会map到同一个cpu cache line,但是待slab逐渐增加以后,后面的slab将还是会无情的打仗,从而造成cpu访问cache频频失效,这种能救几个算几个的思想可能对于人 类救灾是有效的,毕竟生命高于一切(当然不包括三氯氰胺事件),但是对于系统设计,这种效果的机制不如不要,因为我们用大量的代码维持了一个效果甚微的方 案,这是不值得的,软件设计就是这样,每笔账都要算清,赔本的生意绝对不做,内核开发者的慧眼识别出了这个滥竽充数的所谓的巧妙算法,绝然地移除了它,在 分配器从slab发展到slub以后,这个问题相对减轻了许多,slub的思想就是简单,不要那么多花里胡哨的算法,就是简单,简单就是美,这确实是一句 真理,冲突就冲突呗,只要我们带来的益处超过了冲突带来的麻烦,这就是值得的,鸵鸟算法在这种情况下就是有效的,确实是这样。上述引用的**段其实表明了 这一思想,可以好好体会一下。
作任何事情都是这样,巧妙如果变成了花拳绣腿,那它除了表演就没有别的价值了,毕竟你要维护这种巧妙需要的心血是很大的,有时可能远远大于它带来的回报。回归本真是最好的方式,简单,简单,简单就是一切!

分享到:
评论

相关推荐

    Python库 | slab-1.0.2-py3-none-any.whl

    python库。 资源全名:slab-1.0.2-py3-none-any.whl

    The Slab Allocator An Object-Caching Kernel Memory Allocator

    ### Slab Allocator:一种对象缓存内核内存分配器 #### 概述 本文主要介绍了一种基于对象缓存的内核内存分配器——Slab Allocator。该分配器由Jeff Bonwick在Sun Microsystems设计实现,并在SunOS 5.4操作系统中...

    ROFIN SLAB-LASER电路图.rar

    SLAB-LASER是他们的一种固态激光器,采用了半导体激光棒(slab)作为增益介质,具有高功率、高效率和良好的光束质量。 电路图是理解设备工作原理和进行维修、改进的关键文档。对于ROFIN SLAB-LASER电路图,我们可以...

    Laser output of radial-slab solid-state laser

    In this letter, numerical simulation and experimental study of a radial-slab solid-state laser are presented. The laser includes four crossing-slabs pumped by four Xe flashlamps. The numerical ...

    google-roboto-slab-fonts-1.100263-0.5.20150923git.el7.noarch.rpm

    官方离线安装包,亲测可用。使用rpm -ivh [rpm完整包名] 进行安装

    google-roboto-slab-fonts-1.100263-0.7.20150923git.el8.noarch.rpm

    rpm安装包

    Linux Slab分配器分析文档

    Linux系统下的Slab分配器是一种专门针对内核小块内存管理的设计方案。它有效地解决了由于内核频繁分配和释放固定大小的小块内存所带来的内存碎片问题。与传统的基于页的内存管理相比,Slab分配器提供了一种更加高效...

    Linux_slab_分配器剖析.pdf

    为了克服这一挑战,Linux 内核引入了一种名为“slab 分配器”的内存管理技术。本文旨在深入探讨 slab 分配器的工作原理及其在 Linux 内核中的应用。 #### 二、传统内存管理方法的问题 在讨论 slab 分配器之前,我们...

    SLAB-View软件在含硫天然气井井喷泄漏扩散模拟中的应用

    SLAB-View软件在含硫天然气井井喷泄漏扩散模拟中的应用

    linux slab分配器分析

    Linux内核中的slab分配器是一种高效且灵活的内存管理方案,其基础是Jeff Bonwick为SunOS操作系统首次提出的算法。slab分配器的核心思想是在内存分配和释放的过程中保持数据结构的一致性,避免频繁地初始化和销毁数据...

    Compact diode-pumped Nd:YVO4 slab ns-amplifier

    ### Compact Diode-Pumped Nd:YVO4 Slab Nanosecond Amplifier #### 摘要与背景 本文介绍了一种紧凑型二极管泵浦的Nd:YVO4板条纳秒放大器的设计与实现。该研究由钱学森空间技术实验室(中国航天科技集团)和北京...

    slab-view:平板视图组件。 从模板和文件创建视图

    3. **PHP模板**:这表明slab-view可能支持使用PHP语言来编写模板,PHP是一种广泛使用的服务器端脚本语言,尤其适合处理动态内容生成。使用PHP模板,开发者可以将逻辑和视图设计分离,提高代码的可维护性。 4. **...

    slab-cli:Slab命令行组件。 针对您的站点创建并执行命令

    slab-cli是该命令行接口的核心,它提供了一个用户友好的交互式环境,允许开发者通过输入命令来执行各种操作。CLI工具通常包括输入解析、错误处理和结果输出等功能,slab-cli也不例外。 2. **调度员(Scheduler)**...

    Slab算法.pdf

    Slab 分配机制是一种高效的小对象内存管理技术,在 Linux 内核中被广泛应用于管理内核空间中的小对象分配。与传统的伙伴系统相比,Slab 分配器能够更有效地减少内存碎片,并通过重用已经初始化的对象来降低初始化...

    sharded-slab-无锁并发板-Rust开发

    当有大量值时sharded-slab一个无锁的并发slab。 平板为单个数据类型的许多实例提供了预先分配的存储。 当需要大量单个类型的值时,这比单独分配每个项目更有效。 由于分配的项目大小相同,因此减少了内存碎片,并且...

    Linux内存管理中的Slab分配机制.pdf

    Slab 分配机制是 Linux 内存管理机制中的一种重要机制,用于对内存区域中的内核对象进行分配和回收。Slab 使用对象来组织内存区域,每个对象包含一组数据结构。根据内存区域的使用频率,Slab 将内存区域划分为不同的...

    Memcached内存分配与SLAB机制

    SLAB机制是Memcached内存管理的关键组成部分,它通过一种特殊的缓存机制来存储item数据。这种机制能够有效地提高内存利用率并减少内存碎片,从而提高系统的整体性能。 **SLAB机制概述:** - **SLAB(Class)定义**...

Global site tag (gtag.js) - Google Analytics