dlmalloc 2.8.6 源码详解(7)

本文章由vector03原创, 转载请注明出处.

邮箱地址: [email protected], 欢迎来信讨论.

4. 释放与实现

释放过程相对分配就简单多了,
基本着重在chunk合并, top裁剪, segment释放上. dlmalloc中合并是减少外部碎片最有效的方法了.

4.1 dlfree

释放的主要过程就是根据用户传入的payload,
找到chunk指针,
然后分别检查前一个和后一个chunk是否可以合并.
这里唯一需要注意的就是与dv和top这些特殊chunk的交互.

基本流程如下,

1. 通过用户传入的mem指针计算出chunk指针p.
如果FOOTERS打开,
则通过magic计算出其所属的mspace指针,
并进行校验.

2. 若p是通过direct mmap生成的,
则还原其头尾的fake chunk后直接munmap释放并结束.
详细内容请参考3.4.2小节的说明.

3. 若p的prev chunk也是free chunk则将p和prev合并.
若prev同时又是dv,
则还需要考虑p的next chunk.
假如next是inused chunk,
则直接将合并后的p替换为新的dv并返回,
否则进入下一步.

4. 若p的next chunk也是空闲的,
则又分为三种情况,

a.      next是普通的free chunk,
与p进行合并.
如果p同时是dv,
则更新dv.

b.      next同时是top,
则与p合并后更新top为p.
如果p同时又是dv,
则取消当前记录的dv(相当于dv被top吞并了).
若top已经超出trim阈值,
则执行sys_trim.

c.      next同时是dv,
则与p合并后更新dv为p.

5. 若p是经历前面步骤的普通chunk,
则将更新后的p重新插入分箱系统.
如果realse_check满足,
则检查并回收当前mspace下所有的free segment.

代码注释如下,

4.2 sys_trim

当dlmalloc在执行free请求时,
会检测当前top剩余空间是否超出trim_check规定的阈值.
如果是就会尝试收缩当前的top空间.
默认情况下, dlmalloc会保留一个粒度(granularity)大小的空间,
剩余的都将归还给系统, 可以传入参数pad指定额外的剩余空间(多数情况下是0).
另外, 由于top所在区段有可能位于heap区或mmap区,
因此也会有不同的收缩方式. 对于heap区的top空间,
采取反向MORECORE的方式,
而对于mmap区的,
则先尝试用mremap进行收缩,
如果失败则使用mumap释放掉.
假设遇到trim失败的情况, dlmalloc就会自动关闭auto-trimming功能.

源码注释如下,

4.3 release_unused_segments

尽管有auto-trimming压缩top空间,
但多数情况下, 只依靠这种方法是无法满足内存释放需求的.
尤其是当外部碎片导致top不连续的情况下, auto-trimming可能相当一段时间无法触发.
此时, dlmalloc就转而寻找内部可回收的空闲段.
由于查找空闲段是一个耗时操作, 且出现的频率较低,
所以实际上按照一个周期来进行此操作. 当周期计数为0时,
就调用release_unused_segments.

判断一个区段是否空闲也比较简单,
因为空闲chunk合并的原因,
若当前段的第一个chunk为空闲,
且其大小覆盖整个区段除隐藏区域的全部范围, 就可以判定该区段为空闲段.
接下来只要unlink空闲chunk,
且munmap该区段即可.
源码注释如下,

时间: 2024-10-15 05:44:29

dlmalloc 2.8.6 源码详解(7)的相关文章

dlmalloc 2.8.6 源码详解(6)

本文章由vector03原创, 转载请注明出处. 邮箱地址: [email protected], 欢迎来信讨论. 3.4 sys_alloc sys_alloc是dlmalloc中向系统获取内存的主要接口. 由于涉及到mmap, top-most segment, top chunk的交互, 相对要更复杂. 我们同样先介绍主要分配算法, 再详细分析子函数. 3.4.1 核心算法 基本上sys_alloc分为四个步骤, 1. 首先检查请求大小nb是否超出mmap_threshold的阈值. 如果

dlmalloc 2.8.6 源码详解(5)

本文章由vector03原创, 转载请注明出处. 邮箱地址: [email protected], 欢迎来信讨论. 3. 分配及实现 本章节介绍dlmalloc的分配算法和实现.由于存在多mspace的情况, dlmalloc使用了两套API.一套对应默认的mspace,以dl前缀开头,如dlmalloc, dlrealloc等.如果创建了自定义的mspace,则使用mspace开头的API,如mspace_malloc, mspace_realloc等.但两套API在基础算法上是一致的.我们就

Android编程之Fragment动画加载方法源码详解

上次谈到了Fragment动画加载的异常问题,今天再聊聊它的动画加载loadAnimation的实现源代码: Animation loadAnimation(Fragment fragment, int transit, boolean enter, int transitionStyle) { 接下来具体看一下里面的源码部分,我将一部分一部分的讲解,首先是: Animation animObj = fragment.onCreateAnimation(transit, enter, fragm

Java concurrent AQS 源码详解

一.引言 AQS(同步阻塞队列)是concurrent包下锁机制实现的基础,相信大家在读完本篇博客后会对AQS框架有一个较为清晰的认识 这篇博客主要针对AbstractQueuedSynchronizer的源码进行分析,大致分为三个部分: 静态内部类Node的解析 重要常量以及字段的解析 重要方法的源码详解. 所有的分析仅基于个人的理解,若有不正之处,请谅解和批评指正,不胜感激!!! 二.Node解析 AQS在内部维护了一个同步阻塞队列,下面简称sync queue,该队列的元素即静态内部类No

深入Java基础(四)--哈希表(1)HashMap应用及源码详解

继续深入Java基础系列.今天是研究下哈希表,毕竟我们很多应用层的查找存储框架都是哈希作为它的根数据结构进行封装的嘛. 本系列: (1)深入Java基础(一)--基本数据类型及其包装类 (2)深入Java基础(二)--字符串家族 (3)深入Java基础(三)–集合(1)集合父类以及父接口源码及理解 (4)深入Java基础(三)–集合(2)ArrayList和其继承树源码解析以及其注意事项 文章结构:(1)哈希概述及HashMap应用:(2)HashMap源码分析:(3)再次总结关键点 一.哈希概

Spring IOC源码详解之容器依赖注入

Spring IOC源码详解之容器依赖注入 上一篇博客中介绍了IOC容器的初始化,通过源码分析大致了解了IOC容器初始化的一些知识,先简单回顾下上篇的内容 载入bean定义文件的过程,这个过程是通过BeanDefinitionReader来完成的,其中通过 loadBeanDefinition()来对定义文件进行解析和根据Spring定义的bean规则进行处理 - 事实上和Spring定义的bean规则相关的处理是在BeanDefinitionParserDelegate中完成的,完成这个处理需

Spring IOC源码详解之容器初始化

Spring IOC源码详解之容器初始化 上篇介绍了Spring IOC的大致体系类图,先来看一段简短的代码,使用IOC比较典型的代码 ClassPathResource res = new ClassPathResource("beans.xml"); DefaultListableBeanFactory factory = new DefaultListableBeanFactory(); XmlBeanDefinitionReader reader = new XmlBeanDe

IntentService源码详解

IntentService可以做什么: 如果你有一个任务,分成n个子任务,需要它们按照顺序完成.如果需要放到一个服务中完成,那么IntentService就会使最好的选择. IntentService是什么: IntentService是一个Service(看起来像废话,但是我第一眼看到这个名字,首先注意的是Intent啊.),所以如果自定义一个IntentService的话,一定要在AndroidManifest.xml里面声明. 从上面的"可以做什么"我们大概可以猜测一下Inten

Android View 事件分发机制源码详解(View篇)

前言 在Android View 事件分发机制源码详解(ViewGroup篇)一文中,主要对ViewGroup#dispatchTouchEvent的源码做了相应的解析,其中说到在ViewGroup把事件传递给子View的时候,会调用子View的dispatchTouchEvent,这时分两种情况,如果子View也是一个ViewGroup那么再执行同样的流程继续把事件分发下去,即调用ViewGroup#dispatchTouchEvent:如果子View只是单纯的一个View,那么调用的是Vie