热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

slab、slob和slub

一:原文链接:http:www.linuxdiyf.combbsviewthread.php?tid92084很久很久以前:一个叫做MarkHemmen
一:

原文链接:http://www.linuxdiyf.com/bbs/viewthread.php?tid=92084

 很久很久以前:一个叫做Mark Hemment的哥儿们写了Slab。在接下来的一些年里,其他人对Slab进行了完善。一年半以前,SLOB问世了。SLOB的目标是针对嵌入式系统的,主要是适用于那些内存非常有限的系统,比如32MB以下的内存,它不太注重large smp系统,虽然最近在这方面有一些小的改进。几个月之前,SLUB闪亮登场。它基本上属于对Slab的重设计(redesign),但是代码更少,并且能更好的适应large NUMA系统。SLUB被很认为是Slab和Slob的取代者,大概在2.6.24/2.6.25将会被同志们抛弃。而SLUB将是未来Linux Kernel中的首选。

Linux内核真是变化太快了,内存管理这块就是一个好例子。

本来Linux内核只有Slab的,现在好了,Slab多了两个兄弟:Slob和Slub。瞧!这就是内核的命名风格,让你光看名字就糊涂了!这也是我这两天读内核源代码的深刻体会,什么cache啊,cache_cache啊,free_area啊,绕不晕你才怪呢~!

以前搞不懂这三个到底什么关系,为什么要有这三个。今天搜了一下,明白了一些。简单的说:Slab是基础,是最早从Sun OS那引进的;Slub是在Slab上进行的改进,在大型机上表现出色(不知道在普通PC上如何),据说还被IA-64作为默认;而Slob是针对小型系统设计的,当然了,主要是嵌入式。相关文章如下:

Anatomy of the Linux slab allocator
The SLUB allocator
The SLOB allocator

这也正好体现了一个Linux内核开发一贯的思想:提供一种机制,而不是一种策略(Provide mechanism not policy)。

二、

http://blog.chinaunix.net/uid-23795818-id-2385151.html

很久很久以前:一个叫做Mark Hemment的哥儿们写了Slab。在接下来的一些年里,其他人对Slab进行了完善。一年半以前,SLOB问世了。SLOB的目标是针对嵌入式系统 的,主要是适用于那些内存非常有限的系统,比如32MB以下的内存,它不太注重large smp系统,虽然最近在这方面有一些小的改进。几个月之前,SLUB闪亮登场。它基本上属于对Slab的重设计(redesign),但是代码更少,并且 能更好的适应large NUMA系统。

SLUB被很认为是Slab和Slob的取代者,内核开发人员称其为:more SMP-friendly SLUB allocator。显然,在桌面平台上的多核心处理器也能从中受益。

在研究SLUB之前,先说说SLAB。众所周知,操作系统进行内存分配的时候,是以页为单位进行的,也可以称为内存块或者堆。但是内核对象远小于页的大 小,而这些对象在操作系统的生命周期中会被频繁的申请和释放,并且实验发现,这些对象初始化的时间超过了分配内存和释放内存的总时间,所以需要一种更细粒 度的针对内核对象的分配算法,于是SLAB诞生了:

SLAB缓存已经释放的内核对象,以便下次申请时不需要再次初始化和分配空间,类似对象池的概念。并且没有修改通用的内存分配算法,以保证不影响大内存块 分配时的性能。

由于SLAB按照对象的大小进行了分组,在分配的时候不会产生堆分配方式的碎片,也不会产生Buddy分配算法中的空间浪费,并且支持硬件缓存对齐来提高 TLB的性能,堪称完美。

但是这个世界上没有完美的算法,一个算法要么占用更多的空间以减少运算时间,要么使用更多的运算时间减少空间的占用。优秀的算法就是根据实际应用情况在这 两者之间找一个平衡点。SLAB虽然能更快的分配内核对象,但是metadata,诸如缓存队列等复杂层次结构占用了大量的内存。

SLUB因此而诞生:

SLUB 不包含SLAB这么复杂的结构。SLAB不但有队列,而且每个SLAB开头保存了该SLAB对象的metadata。SLUB只将相近大小的对象对齐填入 页面,并且保存了未分配的SLAB对象的链表,访问的时候容易快速定位,省去了队列遍历和头部metadata的偏移计算。该链表虽然和SLAB一样是每 CPU节点单独维护,但使用了一个独立的线程来维护全局的SLAB对象,一个CPU不使用的对象会被放到全局的partial队列,供其他CPU使用,平 衡了个节点的SLAB对象。回收页面时,SLUB的SLAB对象是全局失效的,不会引起对象共享问题。另外,SLUB采用了合并相似SLAB对象的方法, 进一步减少内存的占用。

据内核开发人员称,SLUB相对于SLAB有5%-10%的性能提升和减少50%的内存占用(是内核对象缓存占用的,不是全局哦,否则Linux Kernel可以修改主版本号了)。所以SLUB是一个时间和空间上均有改善的算法,而且SLUB完全兼容SLAB的接口,所以内核其他模块不需要修改即 可从SLUB的高性能中受益。SLUB在2.6.22内核中理所当然的替代了SLAB。

三:

 http://hi.baidu.com/crazyegg/blog/item/100320dbda499d6ed1164ee1.html

SLUB内存分配器
译者按:不知道读者朋友们有没有误入过 /sys/slab 目录,进过这个吓人的目录之后,你可能就很想知道它到底是怎么回事,这和 slab 内存分配器有关,当然,更和 SLUB 内存分配器相关了,/sys/slab 和 slub 一同在 2.6.22 内核被引入,用于提升 cache 内存分配在多处理器系统中的效率。嗯,接下来还是看看这篇不是很久远的考古译文。

***
补充一下,目前SLUB也不是一帆风顺的,和 /sys/slab 有关的东东也有很多问题,http://lwn.net/Articles/263329/ 这篇文章和之后的评论指出了这些问题,让我们拭目以待吧,好了,现在可以继续看这篇考古译文了。
***

slab内存分配器多年以来一直位于内核的内存管理部分的核心地带,它(在底层页分配器之上)管理着特定大小的对象的缓存,允许快速而且省空间的内存分配。内核黑客们一般不愿意去动slab的带脉,因为它实在是非常复杂,而且在大多数情况下,它的工作完成的相当不错。

Christoph Lameter就是那些感到 slab 工作的不是那么好的少数人之一。长时间以来,他提出了一个长长的关于 slab 的问题列表。slab 分配器维护了大量的对象队列,这些队列可以让内存分配更快,却也增加了复杂度。此外,这些存储开销会随着系统规模增大而增大:

每个节点、每个CPU都有 slab 对象队列(一个节点可能对应多个cpu)。alien cache 队列甚至有一个为每个节点的每个cpu都保存一个队列的队列数组。对于大规模的系统,队列数量和对象数量甚至会指数增长。在我们的有一千个节点/处理器的系统中,大约有几G字节的内存被用于存放那些队列,这还不包括哪些在这些队列上的对象。恐怕有一天所有的内存会都消耗在这些队列上头。

而且,每个 slab (一组一个或多个连续的用于分配对象的页面) 都要在起始处包含大量的元数据 ,这使得对象的对其进一步变得困难了。而用于在内存紧张的时候情理 cache 的代码又进一步增加了复杂度……

Christoph 对此的处理是提出了一个SLUB allocator,用于替代 slab 代码。通过取消了大量的队列和相关开销、简化 slab 的结构,SLUB 承诺提供更好的性能和更好的系统可伸缩性,并且可以同时保持现有的 slab 分配器接口。

在 SLUB 分配器中,一个 slab 就是一组一个或多个页面,封装了固定大小的 对象。slab 内部没有元数据,只是空闲对象组织在简单的链表之中。当有一个分配请求的时候,第一个空闲对象就此被定位、从列表中删除并返还给调用者。

在缺少每个slab的元数据的情况下,你可能会非常好奇第一个空闲的对象是如何被发现的。答案就在于 SLUB 分配器将这些信息存储在了系统内存映像之中 — 与这个 slab 所在的页面相关的页结构。让 struct page 变大同样是让人不能认同的,所以SLUB 分配器通过增加了另一个 union 来让这个复杂的结构更复杂了一些,从而解决了这个问题。最终结果是 struct page 增加了三个只在作为 slab 组成部分时才有效的字段:

void *freelist;
short unsigned int inuse;
short unsigned int offset;

在用于 slab 时,freelist 指向 slab 中的第一个空闲对象,inuse 是 slab 已经分配出去的对象数量,而通过 offset ,分配器可以知道那里可以找到指向链表中下一个空闲对象的指针。SLUB 分配器可以使用 RCU 来释放对象,但是,如果想这么做,它必须能够将“下一个对象”的指针放在对象之外;offset 指针正是 SLUB 用来跟踪指针放置位置的手段。

当 slab 被分配器创建的时候,没有对象从中被分配过。一旦一个对象被分配了,它也就成为了一个存储在 kmem_cache 结构中的一个链表中的“部分的” slab。作为一个以可伸缩性为目标的补丁,系统中的每个 NUMA 节点会有一个“部分的”链表。分配器尽力保证分配节点本地的内存,但是会在部分 slab 填满系统之前到达其他节点的。

另外,还有一个每CPU的激活 slab 的数组,用于防止包括 NUMA 节点内部的各种 cache line bouncing。同时还有一个特别的线程(通过一个工作队列)运行,监视每 CPU slab 的使用情况,如果一个CPU的 slab 没有被用上,它还会被放回到部分列表中,以便被其他进程使用。

如果一个 slab 中的所有对象都被分配出去了,分配器就可以完全不用考虑这个 slab 了。一旦一个满 slab 中的一个对象被释放了,分配器就可以可以通过系统内存映像来重定位这个 slab,并将它放回到相应的部分链表之中去。如果一个给定的 slab 中的所有对象(通过 inuse 计数器标记)都被释放了,那么整个 slab 都将被放回到页分配器中,以便重用。

SLUB 内存分配器的一个有趣的特性是它可以合并多个有相似对象尺寸和参数的 slab。其结果是系统中可以有更少的 slab 缓存(据说可以减少 50%),更好的本地化 slab 分配和更少的 slab 内存碎片。该补丁声明:

这个合并可以暴露出内核中迄今为止尚不为人所知的 bug,因为坏掉的对象现在可能难于放置,并会影响到临近的对象。请打开 sanity check 来发现这些问题

让 bug 暴露出来总的来说是件好事,不过,过多使用 SLUB 分配器在那些新的 bug 没有被找出来之前会引起一些奇异行为。

过于广泛的使用是完全可能的:SLUB 分配器现在已经在 -mm 树之中了,并且可能会被加入到 2.6.22 主线内核当中。简化的代码非常诱人,据说有 5-10% 的性能提升。如果被加入到主线内核当中,SLUB 可以和当前的 slab 分配器(以及面向小系统的 SLOB)共存相当常一段时间。从长远来看,当前的 slab 代码可能就要到了生命的终点了。


推荐阅读
  • Nginx使用AWStats日志分析的步骤及注意事项
    本文介绍了在Centos7操作系统上使用Nginx和AWStats进行日志分析的步骤和注意事项。通过AWStats可以统计网站的访问量、IP地址、操作系统、浏览器等信息,并提供精确到每月、每日、每小时的数据。在部署AWStats之前需要确认服务器上已经安装了Perl环境,并进行DNS解析。 ... [详细]
  • android listview OnItemClickListener失效原因
    最近在做listview时发现OnItemClickListener失效的问题,经过查找发现是因为button的原因。不仅listitem中存在button会影响OnItemClickListener事件的失效,还会导致单击后listview每个item的背景改变,使得item中的所有有关焦点的事件都失效。本文给出了一个范例来说明这种情况,并提供了解决方法。 ... [详细]
  • 本文详细介绍了Linux中进程控制块PCBtask_struct结构体的结构和作用,包括进程状态、进程号、待处理信号、进程地址空间、调度标志、锁深度、基本时间片、调度策略以及内存管理信息等方面的内容。阅读本文可以更加深入地了解Linux进程管理的原理和机制。 ... [详细]
  • 本文介绍了在Linux下安装Perl的步骤,并提供了一个简单的Perl程序示例。同时,还展示了运行该程序的结果。 ... [详细]
  • 计算机存储系统的层次结构及其优势
    本文介绍了计算机存储系统的层次结构,包括高速缓存、主存储器和辅助存储器三个层次。通过分层存储数据可以提高程序的执行效率。计算机存储系统的层次结构将各种不同存储容量、存取速度和价格的存储器有机组合成整体,形成可寻址存储空间比主存储器空间大得多的存储整体。由于辅助存储器容量大、价格低,使得整体存储系统的平均价格降低。同时,高速缓存的存取速度可以和CPU的工作速度相匹配,进一步提高程序执行效率。 ... [详细]
  • Webmin远程命令执行漏洞复现及防护方法
    本文介绍了Webmin远程命令执行漏洞CVE-2019-15107的漏洞详情和复现方法,同时提供了防护方法。漏洞存在于Webmin的找回密码页面中,攻击者无需权限即可注入命令并执行任意系统命令。文章还提供了相关参考链接和搭建靶场的步骤。此外,还指出了参考链接中的数据包不准确的问题,并解释了漏洞触发的条件。最后,给出了防护方法以避免受到该漏洞的攻击。 ... [详细]
  • 成功安装Sabayon Linux在thinkpad X60上的经验分享
    本文分享了作者在国庆期间在thinkpad X60上成功安装Sabayon Linux的经验。通过修改CHOST和执行emerge命令,作者顺利完成了安装过程。Sabayon Linux是一个基于Gentoo Linux的发行版,可以将电脑快速转变为一个功能强大的系统。除了作为一个live DVD使用外,Sabayon Linux还可以被安装在硬盘上,方便用户使用。 ... [详细]
  • [大整数乘法] java代码实现
    本文介绍了使用java代码实现大整数乘法的过程,同时也涉及到大整数加法和大整数减法的计算方法。通过分治算法来提高计算效率,并对算法的时间复杂度进行了研究。详细代码实现请参考文章链接。 ... [详细]
  • 深入理解Kafka服务端请求队列中请求的处理
    本文深入分析了Kafka服务端请求队列中请求的处理过程,详细介绍了请求的封装和放入请求队列的过程,以及处理请求的线程池的创建和容量设置。通过场景分析、图示说明和源码分析,帮助读者更好地理解Kafka服务端的工作原理。 ... [详细]
  • 自动轮播,反转播放的ViewPagerAdapter的使用方法和效果展示
    本文介绍了如何使用自动轮播、反转播放的ViewPagerAdapter,并展示了其效果。该ViewPagerAdapter支持无限循环、触摸暂停、切换缩放等功能。同时提供了使用GIF.gif的示例和github地址。通过LoopFragmentPagerAdapter类的getActualCount、getActualItem和getActualPagerTitle方法可以实现自定义的循环效果和标题展示。 ... [详细]
  • 本文详细介绍了Java中vector的使用方法和相关知识,包括vector类的功能、构造方法和使用注意事项。通过使用vector类,可以方便地实现动态数组的功能,并且可以随意插入不同类型的对象,进行查找、插入和删除操作。这篇文章对于需要频繁进行查找、插入和删除操作的情况下,使用vector类是一个很好的选择。 ... [详细]
  • 本文详细介绍了MySQL表分区的创建、增加和删除方法,包括查看分区数据量和全库数据量的方法。欢迎大家阅读并给予点评。 ... [详细]
  • 猜字母游戏
    猜字母游戏猜字母游戏——设计数据结构猜字母游戏——设计程序结构猜字母游戏——实现字母生成方法猜字母游戏——实现字母检测方法猜字母游戏——实现主方法1猜字母游戏——设计数据结构1.1 ... [详细]
  • C# WPF自定义按钮的方法
    本文介绍了在C# WPF中实现自定义按钮的方法,包括使用图片作为按钮背景、自定义鼠标进入效果、自定义按压效果和自定义禁用效果。通过创建CustomButton.cs类和ButtonStyles.xaml资源文件,设计按钮的Style并添加所需的依赖属性,可以实现自定义按钮的效果。示例代码在ButtonStyles.xaml中给出。 ... [详细]
  • 李逍遥寻找仙药的迷阵之旅
    本文讲述了少年李逍遥为了救治婶婶的病情,前往仙灵岛寻找仙药的故事。他需要穿越一个由M×N个方格组成的迷阵,有些方格内有怪物,有些方格是安全的。李逍遥需要避开有怪物的方格,并经过最少的方格,找到仙药。在寻找的过程中,他还会遇到神秘人物。本文提供了一个迷阵样例及李逍遥找到仙药的路线。 ... [详细]
author-avatar
陈雅如7959
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有