对比first-fit/best-fit/worst-fit/slab以及buddy这几种算法的特点

2023-05-16

以下均为自己对这些算法的理解

fitst-fit算法

First-fit算法:连续物理内存分配算法的一种,将空闲内存块按照地址从小到大的方式连起来,具体实现时使用了双向链表的方式。当分配内存时,从链表头开始向后找,这意味着从低地址向高地址查找,一旦找到可以满足要求的内存块,即将该内存块分配出去即可。在此处为了避免内部碎片问题,具体实现时我们将该可用内存块分为两部分:前一部分大小与所需内存相同,这样我们只需要将前一部分分配出去,然后将后一部分继续插入到链表中即可。通过这个方式我们实现了一定程度上的任意大小分配,但是这个算法不可避免的产生了较多的外部碎片。同时,我认为该算法有一个缺陷,那就是会在低地址部分产生很多小碎片,这些碎片不但浪费内存,同时会导致每次从低地址向高地址查找时都要遍历一遍,会使得算法的性能大大下降,查找的开销会逐渐上升。

具体实现时的一些细节以及一些优化策略:

  • 用双向链表存储可用内存块,这样的好处在于插入删除结点时较为容易
  • 找到可用块后,如果可用块大小大于所需(通常情况下均为此情况),则将可用块分配前部分使得正好满足所需,而后半部分继续插入到可用块的链表中,可以避免内部碎片的产生,当然会产生外部碎片。
  • 释放内存块时,需要查看要释放的内存块是否和相邻的块可以合并,如果可以合并,则将其合并为一个大块并放入可用内存块队列。判断较为容易,因为是按照地址排序的,所以只需要查看地址排列是否首位相接即可。
  • 实际上,可以用二叉搜索树对该算法进行优化。通过二叉搜索树排序可用内存块,根据地址排序,通过保证二叉树的任意节点的左节点的地址值小于自身地址值,右节点的地址值大于自身地址值,通过此方法优化,我们可以实现O(n)的复杂度进行内存的分配,但是可以O(logn)的复杂度进行内存的释放。
best-fit和worst-fit算法

由于best-fit和worst-fit在实现上与first-fit较为相似,故先对二者进行介绍。

best-fit算法和worst-fit算法均为连续内存分配算法,仅在分配时选择块的依据上有差别。best-fit总是选择可以满足条件的最小的内存块,而worst-fit总是选择可以满足条件的最大块。实际上我们可以认为它们均为一种特殊的first-fit,best-fit实际上就是将可用内存块从小到大排序,将第一个可以用的内存块分配;而worst-fit实际上是将可用内存块从大到小排序,将第一个可用的内存块分配。不能被名字误导而认为best-fit就是优秀而worst-fit就是很差。二者主要使用环境不同,很容易认为best-fit上很优秀,但宏观上,在实际操作中会发现会产生很多难以利用的内部碎片(因为该算法几乎每次分配都会产生很小的难以利用的碎片)。而worst-fit更适合于中小作业较多的情况,如果大作业较多,则worst-fit性能很差。

具体实现时的一些想法:

  • 可以用双向链表存储可用内存块。但对于best-fit来说链表项的顺序按照块的大小从到大排序,而worst-fit则将可用块按照从大到小排序。
  • 对于这两种算法来说,由于是按照可用块的大小进行排序的,故当释放内存块时,必须对整个可用内存块链表进行一次完整的扫描以确定能否合并,故释放时效率较为低下。
  • worst-fit并不是总是太糟糕的,它每次分配后,通常不会使得剩下的空闲块太小,这是非常优秀的方面。
buddy-system算法:

伙伴分配算法将总内存设为2的n次幂,并将内存按照2的n次幂的格式进行分发。

需要分配内存的时:核心就是分配出不小于所需的最小2次幂大小的内存(如果需要25,就分配32;如果需要63,就分配64),具体分配时,如果有符合的内存块,直接分配即可;如果当前的空闲块没有满足要求的,就将大块进行二等分,继续重复分配过程

需要释放内存时:首先将该内存块释放,然后看其相邻的块(可以进行合并的相邻块,即在分配时由一个内存块分成的两个等大内存块)是否释放,如果相邻块没有释放,则结束即可;如果相邻块释放,则将两个块合并,重复释放过程,对合并后的块进行释放。对相邻块做一个更容易实现的解释:相邻块不仅地址相邻,且二者中的低地址块的地址必须为2的整数幂。

引用一张清华大学学堂在线上的一张图,理解该图足以理解该算法:
在这里插入图片描述
buddy-system算法的优缺点:其优点是快速搜索合并(O(logN)时间复杂度)以及低外部碎片(最佳适配best-fit);其缺点是内部碎片,因为按2的幂划分块,如果碰上65单位大小,那么必须划分128单位大小的块。实际上存储结点信息也会占用一小部分内存,但该算法总体上来看性能还是比较优越的。

主要问题就是内部碎片问题,这也是相较于之前三种内存分配算法所特有的(主要因为以上三种算法均可以在实现时通过一些技巧消除内部碎片问题)。

buddy-system具体实现时的一些细节和优化策略:

  • 利用满二叉树的数据结构实现buddy system。分配器的整体思想是,通过一个数组形式的完全二叉树来监控管理内存,二叉树的节点用于标记相应内存块的使用状态,高层节点对应大的块,低层节点对应小的块,在分配和释放中我们就通过这些节点的标记属性来进行块的分离合并。需要强调的是,由于这里均为满二叉树,故仅需要通过数学关系即可找到子结点、父结点,因此用数组存储即可在这里插入图片描述
    • 有效提高内存利用率的思想:由于实际物理内存通常不是2的倍数,故在此处我使用可用于分配的内存(虚拟的内存)可能会大于具体物理内存,但在存储节点信息时将多出的部分进行了标记,也就是将虚拟的内存对应的实际不存在的物理内存部分标为已用即可。也就意味着我们虚拟管理的部分内存可能是不存在的,但是通过将其标记为不可用即可。
  • alloc过程为自上而下进行判定,找到最适合用于分配地空间,并对相关的结点信息进行刷新。free过程需要判断用递归判断是否两个节点可以合并,如果可以则合并后继续判断,并对相关结点信息进行刷新。
slab算法

slab以内存池为思想,解决内部碎片问题,专门解决小内存问题。提供一种可分配任意大小的内存分配机制。

slab分配器是基于对象进行管理,将相同类型的对象归为一类,每当要申请这样一个对象时,slab分配器就从一个slab列表中分配一个这样大小的单元出去,而当要释放时,将其重新保存在该列表中,而不是直接返回给伙伴系统,从而避免内部碎片。slab分配器并不丢弃已经分配的对象,而是释放并把它们保存在内存中。slab分配对象时,会使用最近释放的对象的内存块,因此其驻留在cpu高速缓存中的概率会大大提高。

slab算法在buddy-system分配大内存的基础上,对小内存区域进行了有效的管理。可以解决内部碎片问题,提供一种可分配任意大小的内存分配机制,slab 分配器还支持通用对象的初始化,从而避免了为同一目的而对一个对象重复进行初始化。slab算法最大的缺点就是复杂,包括队列管理较为复杂、缓冲区管理较为复杂,以及实现起来非常复杂。

slab算法的框架:在这里插入图片描述

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

对比first-fit/best-fit/worst-fit/slab以及buddy这几种算法的特点 的相关文章

随机推荐

  • linux系统编程之进程(八):守护进程详解及创建,daemon()使用

    一 xff0c 守护进程概述 Linux Daemon xff08 守护进程 xff09 是运行在后台的一种特殊进程 它独立于控制终端并且周期性地执行某种任务或等待处理某些发生的事件 它不需要用户输入就能运行而且提供某种服务 xff0c 不
  • IMU&GPS融合定位::加速度计基本原理

    加速度计基本原理 核心 xff1a 牛顿第二定律 一 mems加速度计基本原理 加速度计基本结构如上图 xff0c 由上电容 中电容板 可移动 下电容板等组成 xff1b 当加速度达到一定值后 xff0c 中电容板会移动 xff0c 与上
  • 深入理解事件(Event)

    前言 在前一篇文章中讲到了Event 发布与订阅 一 里面用到了事件来实现一些发布与订阅 xff0c 当时对事件及其委托理解的还不是太深入 xff0c 可能在使用上有点捉急 这篇来好好讲讲事件 xff0c 以及通过一些小DEMO来加深理解
  • 数据结构知识体系框图

    数据结构知识体系框图 xff1a 静态顺序表 xff1a https blog csdn net adorable article details 78720919 静态顺序表之二 xff1a https blog csdn net ado
  • 想做嵌入式却没经验找不到工作!!!

    从大学三年级就想做嵌入式 xff0c 但是却到处打酱油 先是帮老师做Java项目 xff0c 后来又去外包公司做了一年的通信系统OAM代码维护 xff0c 啥技术也没有学到 现在年底裸辞出来又找不到合适的嵌入式工作 基础知识不够 xff0c
  • 学习一个陌生的开源库的方法建议

    转载 xff0c 初看这句话 xff0c 感觉没什么意义 xff0c 但当你在看开源库的例子的时候 xff0c 不妨多想想这句话 对于一个不熟悉的开源库和模块 xff0c 我觉的最好的学习方法莫过于 xff1a 1 使用库 xff0c 看库
  • 将函数实现放在头文件中

    研究一个开源算法库 xff0c 采用C 43 43 模板编程 xff0c 所有函数实现都放在了头文件中 xff0c 现在把模板去掉 xff0c 链接时发生冲突 xff0c 具体原因如下 xff1a 因为多个源文件包含了含有函数定义的头文件
  • 编译器错误消息: CS1617: 选项“6”对 /langversion 无效

    编译错误 说明 在编译向该请求提供服务所需资源的过程中出现错误 请检查下列特定错误详细信息并适当地修改源代码 编译器错误消息 CS1617 选项 6 对 langversion 无效 xff1b 必须是 ISO 1 ISO 2 3 4 5
  • 无法序列化会话状态

    添加购物车功能遇到返回错误500 xff0c 解决办法 xff1a 因为ajax post请求后 xff0c 只返回错误500的信息 xff0c 并不能清楚的知道具体问题 xff0c 所以要在js处理返回错误500的方法中添加上xhr re
  • C#获取网络图片

    简单获取图片 string url 61 zhi txt Text 图片地址 string dizhi 61 lujing Text 图片下载后保存路径及图片名称要写在一块 WebClient wc 61 new WebClient wc
  • 在vscode中使用Git

    用了git最方便的就是比如在公司写了很多代码后回到家打开vscode只需要点击一下pull就能全部同步过来 是不是很方便 毕竟之前我都是拿u盘拷贝回家或者存到云盘再下载下来 我这里用的是国内的码云托管的代码 xff0c xff0c gith
  • vscode同步设置&扩展插件

    首先安装同步插件 xff1a Settings Sync 第二步 xff1a 进入你的github如图 xff1a 打开设置选项 xff1a 新建一个token xff1a 如图 xff1a 记住这个token值 转到vscode 按shi
  • mysql 常用语句使用

    1 查询语句 SELECT FROM table 2 更改语句 UPDATE table SET name 61 39 123456 39 WHERE id 61 100 3 插入语句 INSERT INTO table VALUES 1
  • STM32学习第七天--串口调试助手没弄懂

    啊啊 啊 今天真的好沮丧 调代码足足调了一晚上 xff0c 不知道什么原因工程就是错 xff0c 最后好不容易啊 xff0c 在主函数加了个 include 34 stm32f10x lib h 34 就好使了 xff0c 真不知道为什么
  • swoole 相关

    安装虚拟机 VMware Workstation Pro 安装CentOS CentOS 7 x86 64 Minimal 1708 iso 安装FinalShell 教程地址 安装lnmp 教程地址 服务状态管理命令 1 安装lnmp 2
  • ffmpeg编程:读取摄像头信息,保存为裸yuv420p、yuyv422视频流

    1 源码下载 xff1a https download csdn net download dijkstar 10898462 2 编程环境使用Windows下的QT5 11 minGW32 xff0c 源码中已经放好了fmpeg的bin
  • C中__FILE__ __LINE__的用法

    include lt stdio h gt void main void printf 34 File s Successfully reached line d n 34 FILE LINE Other statements here l
  • ubuntu中添加和删除源

    添加PPA源的命令为 xff1a br sudo add apt repository ppa user ppa name 添加好更新一下 xff1a sudo apt get update 删除命令格式则为 xff1a br sudo a
  • jetson nano 部署yoloV3,yoloV4,yoloV3-tiny,yoloV4-tiny

    系统 ubuntu nbsp nbsp 自带cuda10 0 nbsp 1 下载与安装darknet git clone https github com AlexeyAB darknet cd darknet 2 以下步骤我都在直接进入c
  • 对比first-fit/best-fit/worst-fit/slab以及buddy这几种算法的特点

    以下均为自己对这些算法的理解 xff1a fitst fit算法 First fit算法 xff1a 连续物理内存分配算法的一种 xff0c 将空闲内存块按照地址从小到大的方式连起来 xff0c 具体实现时使用了双向链表的方式 当分配内存时