热门标签 | 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 代码可能就要到了生命的终点了。


推荐阅读
  • H5技术实现经典游戏《贪吃蛇》
    本文将分享一个使用HTML5技术实现的经典小游戏——《贪吃蛇》。通过H5技术,我们将探讨如何构建这款游戏的两种主要玩法:积分闯关和无尽模式。 ... [详细]
  • 本文详细介绍了在 CentOS 系统中如何创建和管理 SWAP 分区,包括临时创建交换文件、永久性增加交换空间的方法,以及如何手动释放内存缓存。 ... [详细]
  • 本文将深入探讨 Unreal Engine 4 (UE4) 中的距离场技术,包括其原理、实现细节以及在渲染中的应用。距离场技术在现代游戏引擎中用于提高光照和阴影的效果,尤其是在处理复杂几何形状时。文章将结合具体代码示例,帮助读者更好地理解和应用这一技术。 ... [详细]
  • 为何Compose与Swarm之后仍有Kubernetes的诞生?
    探讨在已有Compose和Swarm的情况下,Kubernetes是如何以其独特的设计理念和技术优势脱颖而出,成为容器编排领域的领航者。 ... [详细]
  • 本文探讨了如何在PHP与MySQL环境中实现高效的分页查询,包括基本的分页实现、性能优化技巧以及高级的分页策略。 ... [详细]
  • 函子(Functor)是函数式编程中的一个重要概念,它不仅是一个特殊的容器,还提供了一种优雅的方式来处理值和函数。本文将详细介绍函子的基本概念及其在函数式编程中的应用,包括如何通过函子控制副作用、处理异常以及进行异步操作。 ... [详细]
  • 长期从事ABAP开发工作的专业人士,在面对行业新趋势时,往往需要重新审视自己的发展方向。本文探讨了几位资深专家对ABAP未来走向的看法,以及开发者应如何调整技能以适应新的技术环境。 ... [详细]
  • 本文详细介绍了在Windows系统中如何配置Nginx以实现高效的缓存加速功能,包括关键的配置文件设置和示例代码。 ... [详细]
  • 洛谷 P4009 汽车加油行驶问题 解析
    探讨了经典算法题目——汽车加油行驶问题,通过网络流和费用流的视角,深入解析了该问题的解决方案。本文将详细阐述如何利用最短路径算法解决这一问题,并提供详细的代码实现。 ... [详细]
  • 本文将从基础概念入手,详细探讨SpringMVC框架中DispatcherServlet如何通过HandlerMapping进行请求分发,以及其背后的源码实现细节。 ... [详细]
  • 本文详细介绍了如何利用 Bootstrap Table 实现数据展示与操作,包括数据加载、表格配置及前后端交互等关键步骤。 ... [详细]
  • 本文通过分析一个具体的案例,探讨了64位Linux系统对32位应用程序的兼容性问题。案例涉及OpenVPN客户端在64位系统上的异常行为,通过逐步排查和代码测试,最终定位到了与TUN/TAP设备相关的系统调用兼容性问题。 ... [详细]
  • 本文详细探讨了在Web开发中常见的UTF-8编码问题及其解决方案,包括HTML页面、PHP脚本、MySQL数据库以及JavaScript和Flash应用中的乱码问题。 ... [详细]
  • HTML前端开发:UINavigationController与页面间数据传递详解
    本文详细介绍了如何在HTML前端开发中利用UINavigationController进行页面管理和数据传递,适合初学者和有一定基础的开发者学习。 ... [详细]
  • 线段树详解与实现
    本文详细介绍了线段树的基本概念及其在编程竞赛中的应用,并提供了一个具体的线段树实现代码示例。 ... [详细]
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社区 版权所有