Linux 内存管理 SLUB 分配器

文章目录

  • 前言
  • 一、SLUB allocator
  • 二、SLUB core
  • 参考资料

前言

本文来自:https://lwn.net/Articles/229984/

[Posted April 11, 2007 by corbet]

SLAB分配器是用于处理“频繁分配和释放的对象”的对象缓存内核内存分配器。它是内存管理子系统中关键的一部分,对于获得良好性能至关重要。Linux的SLAB分配器对几乎所有人都非常有效;然而,一些人(如SGI)发现其当前设计在某些情况下效率低下。例如,在1K节点/处理器配置中,仅在对象队列(object queues)中就浪费了数GB的内存,而不包括对象本身。当添加适当的NUMA策略支持等功能时,内存管理很快变得过于复杂。

因此,SGI的Christoph Lameter开发了一个名为“SLUB”的新的SLAB分配器,以解决这些问题和其他问题。它的设计更简单,但也解决了一些问题,可能在某些情况下提供更好的性能和更高效的内存使用(请参阅此 提交链接 中的完整设计说明)。它还具有更好的调试功能。可以在Documentation/vm/slabinfo.c中找到一个名为slabinfo的用户空间工具。

SLUB是一种减少缓存行使用的SLAB分配器,相比于管理缓存对象队列的SLAB方法,它采用了一种不同的方式。SLUB通过使用对象的SLAB而不是对象队列来实现每个CPU的缓存。

SLUB的目标是透明地取代SLAB,但在2.6.22中,这个新的SLAB分配器是可选的,并且默认情况下未启用。您可以在编译时启用它(使其成为与SLOB(面向嵌入式的SLAB分配器)一起的第三个选项)。SLUB已经经过了一段时间的测试,并且足够稳定,可以在您的系统上尝试使用,但由于内核的这一部分的重要性,在进行更多的公开和测试之前,它不会完全替代当前的SLAB分配器,因此不建议在生产系统中使用它。非常感谢测试报告,特别是回归测试报告。

SLAB分配器数据结构:
在这里插入图片描述
SLUB分配器数据结构:
在这里插入图片描述

一、SLUB allocator

SLAB分配器多年来一直是内核内存管理的核心部分。该分配器(建立在底层页面分配器之上)管理特定大小对象的缓存,实现了快速且高效的内存分配。内核开发者很少深入研究SLAB代码,因为它非常复杂,而且基本上运行良好。

然而,Christoph Lameter是那些认为SLAB分配器并不完全适用的人之一。随着时间的推移,他列出的问题清单变得令人印象深刻。SLAB分配器维护了一些对象队列,这些队列可以加快内存分配速度,但也增加了相当多的复杂性。此外,存储开销往往随系统规模的增大而增加:

SLAB对象队列存在于每个节点和每个CPU上。甚至外部缓存队列都有一个队列数组,其中包含每个节点上每个处理器的队列。对于非常大的系统,队列的数量和可能被占用的对象数量呈指数增长。在我们的1k节点/处理器系统上,我们仅仅为存储这些队列中对象的引用就使用了数十亿字节的内存,这还不包括队列上可能存在的对象。整个机器的内存有一天会被这些队列耗尽。

除此之外,每个SLAB(一组用于分配对象的一个或多个连续页面)在开头包含一块元数据,这使得对象的对齐更加困难。当内存紧张时,清理缓存的代码增加了另一层复杂性。等等。

Christoph的解决方案是SLUB分配器,它是对SLAB代码的直接替代。SLUB通过放弃大多数队列和相关开销,简化了SLAB结构的同时保留了当前的SLAB分配器接口,以提供更好的性能和可伸缩性。

在SLUB分配器中,slab只是一组一个或多个页面,其中紧密地打包了给定大小的对象。slab本身没有元数据,唯一的例外是空闲对象构成了一个简单的链表。当进行分配请求时,会定位到第一个空闲对象,将其从链表中移除,并返回给调用者。

SLUB分配器通过将页帧打包为组,并且通过struct page中未使用的字段来管理这些组,来最小化内存开销。

鉴于缺乏每个SLAB的元数据,我们可能会想知道如何找到第一个空闲对象。答案是SLUB分配器将相关信息存储在系统内存映射中,即与构成SLAB的页面相关联的页面结构中。在大规模环境中,增加struct page的大小是不被推荐的,因此SLUB分配器通过添加另一个联合体来进一步复杂化这个结构。最终结果是,struct page获得了三个新字段,这些字段仅在相关页面是SLAB的一部分时才具有意义:

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

对于slab使用,freelist指向slab中的第一个空闲对象,inuse表示从slab中已经分配的对象数量,offset告诉分配器下一个空闲对象的指针位置。SLUB分配器可以使用RCU来释放对象,但为了实现这一点,它必须能够将“下一个对象”指针放在对象本身之外;offset指针是分配器跟踪该指针位置的方式。

当分配器首次创建一个slab时,该slab中没有分配任何对象。一旦分配了一个对象,它就成为一个"partial" slab,并被存储在kmem_cache结构中的一个列表中。由于这是一个旨在提高可伸缩性的补丁,实际上系统上的每个NUMA节点都有一个"partial" list。分配器尝试保持节点本地的分配,但在填满系统的partial slabs之前,它也会跨节点进行分配。

此外,还有一个每个CPU的 active slabs 数组,旨在防止NUMA节点内的缓存行跳动。有一个特殊的线程(通过工作队列运行),用于监视 per-CPU slabs 使用情况;如果某个CPU的SLAB未被使用,它将被放回到部分列表中,供其他处理器使用。

SLUB维护一个包含一些空闲对象的页面列表。请注意,它不保留完全分配的页面(在其中包含的至少一个对象被释放之前,可以简单地忘记这些页面);它也不保留完全空闲的页面(这些页面被交回页面分配器)。部分页面包含一个或多个自由对象,这些对象被组织到一个链表中。以这种方式做事有一定的美学价值;它使用空闲内存本身来跟踪空闲对象,从而最大限度地减少对象管理所需的开销。

如果一个slab中的所有对象都被分配,分配器会完全忽略该slab。一旦释放了一个满的slab中的对象,分配器可以通过系统内存映射重新定位包含该slab的页面,并将其放回适当的部分列表中。如果给定slab中的所有对象(通过inuse计数器跟踪)都被释放,整个slab将被归还给页面分配器以供重用。

SLUB分配器的一个有趣特性是它可以合并具有相似对象大小和参数的slabs。结果是系统中的slab caches减少了(据称减少了50%),slab allocations的局部性更好,slab内存的碎片化更少。

SLUB分配器在2.6.22之后进入主线。简化的代码和声称的5-10%性能提升都具有吸引力。

二、SLUB core

这是一个新的 SLAB 分配器,受到现有代码(mm/slab.c)的复杂性的启发。它试图解决现有实现中的各种问题。

A. 对象队列的管理

SLAB 分配器中对象队列的复杂管理是一个特别关注的问题。SLUB 分配器中没有这样的队列。相反,我们为每个分配的 CPU 分配一个内存页,并直接从内存页中使用对象,而不是将它们排队。

B. 对象队列的存储开销

SLAB 分配器中的对象队列是按节点和 CPU 划分的。外部缓存队列甚至有一个包含每个节点上每个处理器的队列的队列数组。对于非常大的系统,队列的数量以及可能在这些队列中排队的对象的数量会呈指数级增长。在我们的系统中,如果有 1k 个节点/处理器,仅用于存储这些队列中对象的引用的空间就有几个 GB。这还不包括可能在这些队列中的对象本身。我们担心有一天整个机器的内存都会被这些队列占满。

C. SLAB 元数据开销

SLAB 分配器在每个内存页的开头都有开销。这意味着数据不能在内存页的开头自然对齐。SLUB 分配器将所有元数据保存在相应的 page_struct 结构中。对象可以在内存页中自然对齐。例如,一个 128 字节的对象将在 128 字节的边界上对齐,并且可以完全适配到 4k 大小的内存页中,不会有剩余的字节。SLAB 分配器无法做到这一点。

D. SLAB 有一个复杂的缓存回收机制

SLUB 在单处理器系统中不需要缓存回收机制。在 SMP 系统中,每个 CPU 的内存页可以被推回到部分使用列表,但该操作很简单,不需要对对象列表进行迭代。SLAB 在缓存回收时会过期处理每个 CPU、共享和外部对象队列,这可能导致奇怪的延迟。

E. SLAB 具有复杂的 NUMA 策略支持

SLUB 将 NUMA 策略处理推到页面分配器中。这意味着分配更加粗粒度(SLUB 在页面级别进行交错),但在 2.6.13 版本之前这种情况也存在。SLAB 将策略应用于在 SLAB 中分配的单个对象,这对性能是一个问题,因为频繁引用内存策略可能导致一系列对象从一个节点分配到另一个节点。SLUB 会从一个节点获取一个内存页的对象,然后切换到下一个节点。

F. 减少部分内存页列表的大小

SLAB 分配器在每个节点上有一个部分内存页列表。随着时间的推移,这些列表上可能会积累大量的部分内存页。只有在特定节点上进行分配时,才能重用这些部分内存页。SLUB 分配器有一个全局的部分内存页池,会从该池中获取内存页,以减少碎片化。

G. 可调参数

SLAB 分配器针对每个 SLAB 缓存具有复杂的调优能力。可以详细调整队列的大小。然而,填充队列仍然需要使用自旋锁来检查 SLAB。SLUB 分配器有一个全局参数(min_slab_order)用于调优。增加最小 SLAB 阶数可以减少锁定开销。SLAB 阶数越大,每个 CPU 和部分列表之间的页面移动就越少,SLUB 的扩展性就越好。

G. SLAB 合并

我们经常有具有相似参数的 SLAB 缓存。SLUB 在启动时会检测到它们,并将它们合并到相应的通用缓存中。这会导致更有效的内存使用。大约有 50% 的缓存可以通过 SLAB 合并来消除。这也将减少 SLAB 的碎片化,因为可以重新填充已分配部分的 SLAB。可以通过在启动时指定 slub_nomerge 来关闭 SLAB 合并。

注意,合并可能会暴露内核中迄今未知的错误,因为损坏的对象现在可能被放置在不同的位置,并且可能破坏相邻的对象。启用健全性检查以发现这些问题。

H. 诊断

当前的 SLAB 诊断工具很难使用,并且需要重新编译内核。SLUB 包含了始终可用的调试代码(但被保持在热代码路径之外)。可以通过设置 “slab_debug” 选项启用 SLUB 诊断。可以指定参数选择单个或一组 SLAB 缓存进行诊断。这意味着系统在正常性能下运行,并且更有可能重现竞态条件。

I. 弹性

如果基本的健全性检查开启,SLUB 能够检测常见的错误条件,并尽可能恢复以允许系统继续运行。

J. 跟踪

可以在启动时通过 “slab_debug=T,” 选项启用跟踪。SLUB 将记录该 SLAB 缓存上的所有操作,并在释放时转储对象内容。

K. 按需创建 DMA 缓存

通常不需要 DMA 缓存。如果使用带有 __GFP_DMA 标志的 kmalloc,则只需创建所需的单个 SLAB 缓存。对于没有 ZONE_DMA 要求的系统,完全消除了支持。

L. 性能提升

一些基准测试显示,在内核测试(kernbench)中的速度提升范围为 5-10%。SLUB 的锁定开销基于底层基本分配大小。如果可以可靠地分配较大的页面,那么可以进一步提高 SLUB 的性能。抗碎片化补丁可能会带来进一步的性能提升。

参考资料

https://lwn.net/Articles/229984/
https://kernelnewbies.org/Linux_2_6_22#New_Slab_allocator:_SLUB
https://events.static.linuxfound.org/sites/events/files/slides/slaballocators.pdf

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/679746.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Opencv 色彩空间

一 核心知识 色彩空间变换; 像素访问; 矩阵的、-、*、、; 基本图形的绘制 二 颜色空间 RGB:人眼的色彩空间; OpenCV默认使用BGR; HSV/HSB/HSL; YUV(视频); 1 RGB 2 BGR 图像的多种属性 1 访问图像(Ma…

MySQL之查询性能优化(三)

查询性能优化 重构查询的方式 在优化有问题的查询时,目标应该是找到一个更优的方法获得实际需要的记过——而不是一定总是需要从MySQL获取一模一样的结果集。有时候,可以将查询转换一种写法让其返回一样的结果,但是性能更好。但也可以通过修…

关于URL获取的参数,无法执行二选一查询

🏆本文收录于「Bug调优」专栏,主要记录项目实战过程中的Bug之前因后果及提供真实有效的解决方案,希望能够助你一臂之力,帮你早日登顶实现财富自由🚀;同时,欢迎大家关注&&收藏&&…

Arthas调优工具使用

1,服务器端下载 curl -O https://arthas.aliyun.com/arthas-boot.jar 2,服务器端启动 java -jar arthas-boot.jar 选定要绑定的Java进程ID 3,本地idea安装Arthas idea 4,选定方法右键trace,生成命令 trace com.xxx.xxx.xxx.vouche…

C++之noexcept

目录 1.概述 2.noexcept作为说明符 3.noexcept作为运算符 4.传统throw与noexcept比较 5.原理剖析 6.总结 1.概述 在C中,noexcept是一个关键字,用于指定函数不会抛出异常。如果函数保证不会抛出异常,编译器可以进行更多优化,…

Spring Boot既打jar包又打war包如何做

你好,我是柳岸花开。 引言 在软件开发中,根据不同的部署需求,我们可能需要将应用打包成不同的格式。Spring Boot作为目前流行的Java应用开发框架,提供了一种简单的方式来打包应用。本文将介绍如何利用Maven Profiles在Spring Boot…

JDK8安装详细教程教程-windows

📖JDK8安装详细教程教程-windows ✅1. 下载✅2. 安装 ✅1. 下载 123云盘下载地址: JDK8 | JDK11 | JDK17 官方Oracle地址:https://www.oracle.com/java/technologies/downloads/archive/ ✅2. 安装 运行jdk-8u211-windows-x64.exe安装包文…

Blog项目切换Markdown编辑器———LayUI弹出层弹出写在页面的内容导致的各种bug

【2024.5.24回顾】 1 问题描述(描述完自己解决了…) 正常情况 点击添加文章按钮后,弹出文章编辑界面,如果用富文本功能编辑,则一切正常。可以多次打开、关闭 Markdown 如果在弹出层中点击了切换编辑器按钮,会成功切换为markd…

FreeRTOS的使用与编码器设计

第一步:任务创建:在 FreeRTOS 中,系统功能由任务(Task)组成。在系统启动时,你需要创建各个任务并指定它们的任务频率、优先级、堆栈大小等参数。 xTaskCreate() 来创建开始任务并定义任务的执行函数、优先级…

Java之instanceof 运算符:掌握它的使用方法

哈喽,各位小伙伴们,你们好呀,我是喵手。运营社区:C站/掘金/腾讯云;欢迎大家常来逛逛 今天我要给大家分享一些自己日常学习到的一些知识点,并以文字的形式跟大家一起交流,互相学习,一…

人工智能--深度神经网络

目录 🍉引言 🍉深度神经网络的基本概念 🍈神经网络的起源 🍍 神经网络的基本结构 🍉深度神经网络的结构 🍈 卷积神经网络(CNN) 🍈循环神经网络(RNN&…

期权懂基础知识分享:场外期权怎么做?

今天带你了解期权懂基础知识分享:场外期权怎么做?场外个股期权是一种金融工具,用于在股票市场之外交易。 场外期权怎么做? 签订框架协议:个人需要与机构签订场外期权框架协议,通常无需单独开立账户。 询价…

Web3.0区块链技术开发方案丨中心化与去中心化交易所开发

随着区块链技术的不断发展和普及,加密货币交易所成为数字资产市场中的关键组成部分。其中,中心化交易所(CEX)和去中心化交易所(DEX)是两种主要的交易所类型。本文将探讨Web3.0区块链技术开发方案&#xff0…

【Postman接口测试】第四节.Postman接口测试项目实战(中)

文章目录 前言五、Postman断言 5.1 Postman断言介绍 5.2 响应状态码断言 5.3 包含指定字符串断言 5.4 JSON数据断言六、参数化 5.1 Postman参数化介绍 5.2 Postman参数化实现 5.3 针对项目登录接口参数化实现 总结 前言 五、Postman断言 5.1 Postman断言介…

Android 应用权限

文章目录 权限声明uses-permissionpermissionpermission-grouppermission-tree其他uses-feature 权限配置 权限声明 Android权限在AndroidManifest.xml中声明&#xff0c;<permission>、 <permission-group> 、<permission-tree> 和<uses-permission>…

TSINGSEE青犀视频汇聚机房动环智能监控方案,提升机房安全稳定性

一、背景需求 在当今信息化时代&#xff0c;机房作为数据中心的核心设施&#xff0c;承载着重要的网络设备和数据存储设备&#xff0c;其正常运行对于企业的数据安全和业务连续性至关重要。机房内部设备众多&#xff0c;且运行过程中涉及大量的数据交换和传输。一旦发生安全事…

[C][数据结构][时间空间复杂度]详细讲解

目录 0.铺垫1.时间复杂度 -- 衡量算法的运行快慢1.是什么&#xff1f;2.大O的渐进表示法 2.空间复杂度 - 衡量算法所需要的额外空间3.常见复杂度对比 0.铺垫 时间是累计的空间是不累计的&#xff0c;可以重复利用 1.时间复杂度 – 衡量算法的运行快慢 1.是什么&#xff1f; …

量化研究---大qmt实盘实现禄得可转债策略轮动

前面写了一个强大的可转债自定义系统&#xff0c;我们可以利用这个快速对接到大qmt,我提供实时数据支持 量化研究---强大的可转债分析系统上线&#xff0c;提供api&#xff0c;实时数据支持 打开网页 http://120.78.132.143:8023/ 强大可转债选择系统 http://120.78.132.143:8…

【TB作品】msp430g2553单片机,DS18B20,温控装置,iic OLED

功能 /* 硬件&#xff1a;DS18B20OLEDIIC绿灯红灯一个按键蜂鸣器加热片功能&#xff1a;1 显示温度2 显示临界值&#xff0c;按键可以加减临界值&#xff0c;临界值在20~35之间可调。3 实际温度高于&#xff08;临界值1&#xff09;后绿灯亮表示降温。4 实际温度低于&#xf…

【云原生_K8S系列】什么是 Kubernetes Pod?用实际例子解释

Kubernetes&#xff08;简称K8S&#xff09;是一个开源的容器编排平台&#xff0c;用于自动化容器化应用的部署、扩展和管理。在Kubernetes中&#xff0c;Pod是最小的部署单元。理解Pod的概念对于掌握Kubernetes至关重要。本篇文章将详细解释什么是Kubernetes Pod&#xff0c;并…