内存碎片_内存碎片是怎么产生的?有解决办法? - CSDN
精华内容
参与话题
  • 内存碎片产生原因及终极解决办法

    千次阅读 2018-04-03 13:56:58
    内存碎片通常分为内部碎片和外部碎片: 1. 内部碎片是由于采用固定大小的内存分区,当一个进程不能完全使用分给它的固定内存区域时就产生了内部碎片,通常内部碎片难以完全避免; 2. 外部碎片是由于某些未分配的...
    内存碎片通常分为内部碎片和外部碎片:
      1. 内部碎片是由于采用固定大小的内存分区,当一个进程不能完全使用分给它的固定内存区域时就产生了内部碎片,通常内部碎片难以完全避免;
      2. 外部碎片是由于某些未分配的连续内存区域太小,以至于不能满足任意进程的内存分配请求,从而不能被进程利用的内存区域。

      现在普遍采用的段页式内存分配方式就是将进程的内存区域分为不同的段,然后将每一段由多个固定大小的页组成。通过页表机制,使段内的页可以不必连续处于同一内存区域,从而减少了外部碎片,然而同一页内仍然可能存在少量的内部碎片,只是一页的内存空间本就较小,从而使可能存在的内部碎片也较少。


    解决办法:

    首先,使用最原始的标记分配方法,系统需要维护一个简单的内存信息表:

    当程序申请一个长度为3的内存空间后:

    当程序再申请一个长度为2,以及长度为4的内存空间后:

    此时,只剩1个可用空间。如果这时程序再来申请长度大于1的空间,就申请不了,也就是内存不够。

    现在,释放掉ID=2的空间:

    我们发现,现在可用内存空间为3,但是,这3个空闲空间,并不是连续的。所以,如果程序现在申请长度为3的内存空间,同样会申请不了,会出现内存不够。业界把这种情况,称之为【内存碎片】。

    明明剩余有3个空间,却申请不了3个内存空间,这TMD扯蛋?

    于是,工程师们,发明了基于页面的内存管理方式:

    首先,把物理内存,按照某种尺寸,进行平均分割。比如我现在以2个内存单位,来分割内存,也就是每两个连续的内存空间,组成一个内存页:


    接着,系统同样需要维护一个内存信息表:

    现在,程序申请长度为3的内存空间,不过由于现在申请的最小单位为页面,而一个页面的长度为2,因此现在需要申请2个页面,也就是4个内存空间。你看,这就浪费了1个内存空间。

    接着,程序再申请长度为1,长度为2的空间:


    释放掉ID=2,内存页ID为3的那条内存空间信息:

    现在,就出现了之前的情况:目前一共有4个内存空间,但是不连续。不过,因为现在是分页管理机制,因此,现在仍然可以继续申请长度为4的内存空间:


    这种方案是不是爽得多?没有碎片,能够尽量地全部用完空间。但仔细想想,这种优势背后,也是需要付出大量代价的。

    前面那种内存分配方式,虽然容易出现碎片,并且内存空间的利用率低,但是使用性能高,程序能直接从内存信息表获取内存地址,接着就可以直接按照地址来使用内存空间了。

    但下面这种分页的方式,程序需要记录的是内存页ID,每次使用时,需要从内存页ID翻译成实际内存地址,多了一次转换。而且这种模式,会浪费一些内存,比如上面申请3个内存空间,实际分配了2个页面共4个内存空间,浪费了1个内存空间。

    以上就是基本原理,实际系统中会做非常多的优化。目前各种主流操作系统都是分页的方式,因此你不需要太关心碎片。

    这个话题再延伸下去,就是一个程序内部的局部内存池了。不过这是另一个问题,喜欢的话可以深究一下。


    来源:知乎
    链接:https://www.zhihu.com/question/51836333/answer/145693402

    转自:https://blog.csdn.net/tong5956/article/details/74937178

    展开全文
  • 如何解决内存碎片

    千次阅读 2013-12-21 08:24:18
    内存碎片的产生:  内存分配有静态分配和动态分配两种  静态分配在程序编译链接时分配的大小和使用寿命就已经确定,而应用上要求操作系统可以提供给进程运行时申请和释放任意大小内存的功能,这就是内存的动态...

    内存碎片的产生:

            内存分配有静态分配和动态分配两种
           静态分配在程序编译链接时分配的大小和使用寿命就已经确定,而应用上要求操作系统可以提供给进程运行时申请和释放任意大小内存的功能,这就是内存的动态分配。
            因此动态分配将不可避免会产生内存碎片的问题,那么什么是内存碎片?内存碎片即“碎片的内存”描述一个系统中所有不可用的空闲内存,这些碎片之所以不能被使用,是因为负责动态分配内存的分配算法使得这些空闲的内存无法使用,这一问题的发生,原因在于这些空闲内存以小且不连续方式出现在不同的位置。因此这个问题的或大或小取决于内存管理算法的实现上。

           为什么会产生这些小且不连续的空闲内存碎片呢?

           实际上这些空闲内存碎片存在的方式有两种:a.内部碎片 b.外部碎片 。
           内部碎片的产生:因为所有的内存分配必须起始于可被 4、8 或 16 整除(视处理器体系结构而定)的地址或者因为MMU的分页机制的限制,决定内存分配算法仅能把预定大小的内存块分配给客户。假设当某个客户请求一个 43 字节的内存块时,因为没有适合大小的内存,所以它可能会获得 44字节、48字节等稍大一点的字节,因此由所需大小四舍五入而产生的多余空间就叫内部碎片。
          外部碎片的产生: 频繁的分配与回收物理页面会导致大量的、连续且小的页面块夹杂在已分配的页面中间,就会产生外部碎片。假设有一块一共有100个单位的连续空闲内存空间,范围是0~99。如果你从中申请一块内存,如10个单位,那么申请出来的内存块就为0~9区间。这时候你继续申请一块内存,比如说5个单位大,第二块得到的内存块就应该为10~14区间。如果你把第一块内存块释放,然后再申请一块大于10个单位的内存块,比如说20个单位。因为刚被释放的内存块不能满足新的请求,所以只能从15开始分配出20个单位的内存块。现在整个内存空间的状态是0~9空闲,10~14被占用,15~24被占用,25~99空闲。其中0~9就是一个内存碎片了。如果10~14一直被占用,而以后申请的空间都大于10个单位,那么0~9就永远用不上了,变成外部碎片。


     

    如何解决内存碎片:

            采用Slab Allocation机制:整理内存以便重复使用
            最近的memcached默认情况下采用了名为Slab Allocator的机制分配、管理内存。在该机制出现以前,内存的分配是通过对所有记录简单地进行malloc和free来进行的。但是,这种方式会导致内存碎片,加重操作系统内存管理器的负担,最坏的情况下,会导致操作系统比memcached进程本身还慢。Slab Allocator就是为解决该问题而诞生的。
            下面来看看Slab Allocator的原理。下面是memcached文档中的slab allocator的目标:he primary goal of the slabs subsystem in memcached was to eliminate memory fragmentation issuestotally by using fixedsizememory chunks coming from a few predetermined size classes.
            也就是说,Slab Allocator的基本原理是按照预先规定的大小,将分配的内存分割成特定长度的块,以完全解决内存碎片问题。Slab Allocation的原理相当简单。将分配的内存分割成各种尺寸的块(chunk),并把尺寸相同的块分成组(chunk的集合)(图2.1)。

      slab allocator还有重复使用已分配的内存的目的。也就是说,分配到的内存不会释放,而是重复利用

    Slab Allocation的主要术语
        Page
        分配给Slab的内存空间,默认是1MB。分配给Slab之后根据slab的大小切分成chunk。
        Chunk
        用于缓存记录的内存空间。
        Slab Class
        特定大小的chunk的组。

    在Slab中缓存记录的原理
    下面说明memcached如何针对客户端发送的数据选择slab并缓存到chunk中。memcached根据收到的数据的大小,选择最适合数据大小的slab(图2.2)。memcached中保存着slab内空闲chunk的列表,根据该列表选择chunk,然后将数据缓存于其中。

     
    图2.2:选择存储记录的组的方法
    实际上,Slab Allocator也是有利也有弊。下面介绍一下它的缺点。

    Slab Allocator的缺点
    Slab Allocator解决了当初的内存碎片问题,但新的机制也给memcached带来了新的问题。这个问题就是,由于分配的是特定长度的内存,因此无法有效利用分配的内存。例如,将100字节的数据缓存到128字节的chunk中,剩余的28字节就浪费了

     对于该问题目前还没有完美的解决方案,但在文档中记载了比较有效的解决方案。
    The most efficient way to reduce the waste is to use a list of size classes that closely matches (if that's at all
    possible) common sizes of objects that the clients of this particular installation of memcached are likely to
    store.
           就是说,如果预先知道客户端发送的数据的公用大小,或者仅缓存大小相同的数据的情况下,只要使用适合数据大小的组的列表,就可以减少浪费。但是很遗憾,现在还不能进行任何调优,只能期待以后的版本了。但是,我们可以调节slab class的大小的差别

    展开全文
  • 内存碎片

    2019-10-03 12:39:26
    什么是内存碎片??? 内存碎片分为 内部碎片 外部碎片 内部碎片:是由于采用固定大小的内存分区,当一个进程不能完全使用分给它的固定内存区域就产生了内部碎片,通常内部碎片难以完全避免; 外部碎片:是由于...

    什么是内存碎片???

    内存碎片分为

    • 内部碎片
    • 外部碎片

    内部碎片:是由于采用固定大小的内存分区,当一个进程不能完全使用分给它的固定内存区域就产生了内部碎片,通常内部碎片难以完全避免;
    外部碎片:是由于某些未分配的连续内存区域太小,以至于不能满足任意进程的内存分配请求,从而不能被进程利用的内存区域;

    什么情况下会产生内存碎片???

    • 对于malloc()等函数,每次申请完内存后都会释放,但每次释放的内存大小及释放时间的不同就会产生内存碎片。
      比如:在内存单元100的起始地址到内存单元200之间,共申请了100个1字节的空间。在free()时,释放了内存地址为奇数的内存单元(如101,103,105……)而偶数单元不释放,释放了50个1字节空间,虽然总空间数为50字节,但由于这50个1字节空间不连续。当下次要申请2字节的内存单元时,却无法在100到200的内存地址单元中申请到空间,于是就产生内存碎片问题。

    内存分配有哪些方法???

    • 连续地址分配
      固定分区分配会产生内部碎片问题,动态分配会产生外部碎片问题
    • 分段式内存管理
      在这里插入图片描述
    • 分页式内存管理
      在这里插入图片描述
    • 段页式内存管理
      在这里插入图片描述

    怎样避免内存碎片???

    • 伙伴算法
    • slab算法
      具体思路可参考该网址
      https://blog.csdn.net/u013009575/article/details/17751147
    展开全文
  • Linux是如何避免内存碎片

    千次阅读 2018-03-23 19:45:28
    Linux是如何避免内存碎片的? 在网上看到这个面试题,参考答案是这样的: 伙伴算法,用于管理物理内存,避免内存碎片; 高速缓存Slab层用于管理内核分配内存,避免碎片。 故继而去深入了解了一波,做了一个...

    Linux是如何避免内存碎片的?

    在网上看到这个面试题,参考答案是这样的:

    1. 伙伴算法,用于管理物理内存,避免内存碎片;
    2. 高速缓存Slab层用于管理内核分配内存,避免碎片。

    故继而去深入了解了一波,做了一个粗略的整理:

    内存碎片问题

    • 频繁地请求和释放不同大小的内存,必然导致内存碎片问题的产生,结果就是当再次要求分配连续的内存时,即使整体内存是足够的,也无法满足连续内存的需求。该问题也称之为外碎片(external fragmentation)。
    • 解决方案:
    • 避免外碎片的方法有两种:
      1、利用分页单元把一组非连续的空闲页框映射到连续的线性地址
      2、开发一种适当的技术来记录现存的空闲的连续页框块的情况,以尽量避免为满足对小块的请求而分割大的空闲快
    • 第一种方案的意思是,我们使用地址转换技术,把非连续的物理地址转换成连续的线性地址。
    • 第二种方案的意思是,开发一种特有的分配技术来记录下来空闲内存的情况,从而解决内存碎片问题。
    • Linux采用了第二种方案,因为在某些情况下,系统的确需要连续的物理地址(DMA处理器可以直接访问总线)。

    这里先对Linux内存管理做一个简单介绍

    • linux kernel 通过把整个物理内存划分成以一个个page进行管理,管理器就是伙伴系统,它的最小分配单元就是page。但是对于小于page的内存分配,如果直接分配一个page,是一个很大的浪费。linux kernel 通过slab来实现对小于page大小的内存分配。slab把page按2的m次幂进行划分一个个字节块,当kmalloc申请内存时,通过slab管理器返回需要满足申请大小的最小空闲内存块。
    • slub主要是针对slab的对象管理数据的优化版本,相比于slab,slub提供更小的管理成本开销。而且slub对多核系统的支持也更加友好。细节这里就不展开讲。
    • 所以kernel的内存管理是个2层分层系统,从下往上依次为:
    • 第一层为全部物理内存:其管理器为伙伴系统,最小管理单位为page;
    • 第二层为slab page:其管理器为slab/slub,最小管理单位为2的m次幂的字节块;

    伙伴系统(buddy system)

    • Linux采用著名的伙伴系统(buddy system)算法来解决外碎片问题。把所有的空闲页框分组为11个块链表,每个链表分别包含大小为1,2,4,8,16,32,64,128,256,512,1024个连续的页框,对1024个页框的最大请求对应着4MB大小的连续RAM(每页大小为4KB),每个块的第一个页框的物理地址是该块大小的整数倍,例如,大小为16个页框的块,其起始地址是16*2^12的倍数。
      我们通过一个例子来说明伙伴算法的工作原理,假设现在要请求一个256个页框的块(1MB),算法步骤如下:
      • 在256个页框的链表中检查是否有一个空闲快,如果没有,查找下一个更大的块,如果有,请求满足。
      • 在512个页框的链表中检查是否有一个空闲块,如果有,把512个页框的空闲块分为两份,第一份用于满足请求,第二份链接到256个页框的链表中。如果没有空闲块,继续寻找下一个更大的块。
      下图比较形象地描述了该过程。
      这里写图片描述
      页的请求
      以上过程的逆过程,就是页框块的释放过程,也是该算法名字的由来,内核试图把大小为B的一对空闲伙伴块合并为一个2B的单独块,满足以下条件的两个块称之为伙伴:
      • 两个块具有相同的大小
      • 他们的物理地址是连续的
      第一块的第一个页框的物理地址是2 * B * 2^12
      该算法是递归的,如果它成功合并了B,就会试图去合并2B,以再次试图形成更大的块。

    高速缓存Slab层

    • slab是Linux操作系统的一种内存分配机制。其工作是针对一些经常分配并释放的对象,如进程描述符等,这些对象的大小一般比较小,如果直接采用伙伴系统来进行分配和释放,不仅会造成大量的内存碎片,而且处理速度也太慢。
    • 而slab分配器是基于对象进行管理的,相同类型的对象归为一类(如进程描述符就是一类),每当要申请这样一个对象,slab分配器就从一个slab列表中分配一个这样大小的单元出去,而当要释放时,将其重新保存在该列表中,而不是直接返回给伙伴系统,从而避免这些内碎片。slab分配器并不丢弃已分配的对象,而是释放并把它们保存在内存中。当以后又要请求新的对象时,就可以从内存直接获取而不用重复初始化。
    • 对象高速缓存的组织如右下图所示,高速缓存的内存区被划分为多个slab,每个slab由一个或多个连续的页框组成,这些页框中既包含已分配的对象,也包含空闲的对象。
    • 在cache和object中加入slab分配器,是在时间和空间上的折中方案。
      这里写图片描述

    • 另外为了解决多核和NUMA架构下效率问题,slab管理器kmem_cache又把slab page对象分为2层结构,从下往上依次为:

    • 第一层为NUMA node下cpu共享page:管理器为kmem_cache_node,管理node下的slab对象,解决NUMA架构的内存访问效率问题。当本层的空闲page不足时,从伙伴系统申请空闲page;
    • 第二层为per-cpu专属page:管理器为kmem_cache_cpu,管理cpu专属的slab对象,解决多核竞争问题。当本层的空闲page不足时,从第一层申请空闲page;
      这里写图片描述

    slab分配算法

    • slab分配算法采用cache 存储内核对象。当创建cache 时,起初包括若干标记为空闲的对象。对象的数量与slab的大小有关。开始,所有对象都标记为空闲。当需要内核数据结构的对象时,可以直接从cache 上直接获取,并将对象初始化为使用。
    • 下面考虑内核如何将slab分配给表示进程描述符的对象。在Linux系统中,进程描述符的类型是struct task_struct ,其大小约为1.7KB。当Linux 内核创建新任务时,它会从cache 中获得struct task_struct 对象所需要的内存。Cache 上会有已分配好的并标记为空闲的struct task_struct 对象来满足请求。
    • Linux 的slab 可有三种状态:
      满的:slab 中的所有对象被标记为使用。
      空的:slab 中的所有对象被标记为空闲。
      部分:slab 中的对象有的被标记为使用,有的被标记为空闲。
    • slab 分配器首先从部分空闲的slab 进行分配。如没有,则从空的slab 进行分配。如没有,则从物理连续页上分配新的slab,并把它赋给一个cache ,然后再从新slab 分配空间。

    资料整理自:
    [1] https://baike.baidu.com/item/slab
    [2] http://www.cnblogs.com/wahaha02/p/6616957.html
    [3] https://www.jianshu.com/p/c4ef33bde4f5

    展开全文
  • 内存碎片产生原因及解决办法

    千次阅读 2018-09-28 22:43:18
    内存碎片通常分为内部碎片和外部碎片:   1. 内部碎片是由于采用固定大小的内存分区,当一个进程不能完全使用分给它的固定内存区域时就产生了内部碎片,通常内部碎片难以完全避免;   2. ...
  • 通常我们习惯直接使用new、malloc等API申请分配内存,这样做的缺点在于:由于所申请内存块的大小不定,当频繁使用时会造成大量的内存碎片并进而降低性能。内存池则是在真正使用内存之前,先申请分配一定数量的、大小...
  • 内存碎片通常分为内部碎片和外部碎片: 1. 内部碎片是由于采用固定大小的内存分区,当一个进程不能完全使用分给它的固定内存区域时就产生了内部碎片,通常内部碎片难以完全避免; 2. 外部碎片是由于某些未分配...
  • C++-----浅谈内存碎片

    千次阅读 多人点赞 2019-07-27 18:24:06
    内存碎片即“碎片的内存”,它分为外碎片和内碎片,内存碎片描述一个系统中所有不可用的空闲内存,这些碎片之所以不能被使用,是因为负责动态分配内存的分配算法使得这些空闲的内存无法使用,这一问题的发生,原因...
  • 外部碎片和内部碎片的区别

    万次阅读 多人点赞 2014-08-20 14:19:06
    故而三个文件不会产生碎片。 现在假设你删除了B文件,这个时候A和C中间就有一块空闲簇段了。此时还是不存在文件碎片的,因为每个文件各自占据的簇段都是连续的,没有文件被分割。而如果现在需要写入一个文件D,而且...
  • Linux下malloc/free内存碎片问题

    千次阅读 2011-08-31 18:13:04
    通过对malloc,free源码的...内存碎片在这里可以从两个方面进行分析,物理地址的内存碎片和线性地址(虚拟地址)的内存碎片。 首先是物理地址的内存碎片,malloc_free_list大小依次为8,16,32....。那么我们请求的
  • Redis内存碎片

    千次阅读 2019-07-05 14:25:30
    文章目录Redis内存碎片内存碎片内存碎片率高的原因解决方法 Redis内存碎片率 redis4支持内存碎片清理功能使用 内存碎片率 mem_fragmentation_ratio = used_memory_rss / used_memory used_memory :Redis使用其...
  • linux设置自动清除内存碎片

    千次阅读 2018-05-30 15:10:54
    清除命令:echo 1 > /proc/sys/vm/drop_caches 配置文件/proc/sys/vm/drop_caches。这个文件中记录了缓存释放的参数,默认值为0,也就是不释放缓存。他的值可以为0~3之间的任意数字,代表着不同的含义:0 – ...
  • 通常我们习惯直接使用new、malloc等API申请分配内存,这样做的缺点在于:由于所申请内存块的大小不定,当频繁使用时会造成大量的内存碎片并进而降低性能。内存池则是在真正使用内存之前,先申请分配一定数量的、...
  • 求大神给解答一下,内存碎片产生原因,以及处理方法,最近看见有关内存碎片的问题 ,我有点没看懂,不知道为什么会产生内存碎片,正常的new和delete,不是不会产生内存泄露么,为什么会产生内存碎片呢!
  • 操作系统内存管理之 内部碎片vs外部碎片

    万次阅读 多人点赞 2012-05-03 11:29:22
    “碎片的内存”描述一个系统中所有不可用的空闲内存。...由于分 配方法决定内存碎片是否是一个问题,因此内存分配器在保证空闲资源可用性方面扮演着重要的角色。 internal fragmentation:when memory allocated
  • 1.内存泄漏的定义    一般我们常说的内存泄漏是指堆内存的泄漏。堆内存是指程序从堆中分配的,大小任意的(内存块的大小可以在程序运行期决定),使用完后必须显示释放的内存。应用程序一般使用malloc,realloc...
  • malloc/free内存碎片的产生原因

    千次阅读 2015-09-28 20:39:47
    malloc和free大量使用后回造成内存碎片,那么这种碎片形成的机理是什么?如果机理是申请的内存空间大小(太小)所形成的,那么申请多大的区域能够最大限度的避免内存碎片呢(这里的避免不是绝对的避免,只是一种概率)? ...
  • linux内存碎片管理

    千次阅读 2014-04-15 10:06:53
    查看内存碎片: # cat /proc/buddyinfo
  • Redis内存碎片

    千次阅读 2017-02-16 19:18:45
    最近使用redis作为kv存一些业务数据,给redis设置了最大使用内存以及数据淘汰规则。maxmemory 60g maxmemory-policy allkeys-lru 设置完之后以为redis进程最多会占用60g的内存,所以就放心的使用。但是前几天收到...
  • 生产Redis内存碎片过高排查

    千次阅读 2018-01-24 16:30:07
    生产Redis内存碎片过高排查 内存碎片率:used_memory_rss(33G)/used_memory(20G)=1.65,导致Redis实例所在虚机发出报警。 生产环境:每日高达1600W次hmset写入操作,且value长短不一(有效期:24小时); 每日上述...
1 2 3 4 5 ... 20
收藏数 139,220
精华内容 55,688
关键字:

内存碎片