Jemalloc 深入分析 之 配对堆Pairing Heap
为了更好的阅读效果,推荐下载pdf文档:
详细文章请参考:《jemalloc 深入分析》
https://github.com/everschen/tools/blob/master/DOC/Jemalloc.pdf
https://download.csdn.net/download/ip5108/10941278
2.1. 配对堆Pairing Heap
斐波那契堆主要有两个缺点:编程实现难度较大和实际效率没有理论的那么快(由于它的存储结构和四个指针)。Pairing Heap的提出就是弥补斐波那契堆的两个缺点——编程简单操作的时间复杂度和斐波那契堆一样。
Pairing Heap其实就是一个具有堆(最大堆或最小堆)性质的树,它的特性不是由它的结构决定的,而是由于它的操作(插入,合并,减小一个关键字等)决定的。
一个指针指向该节点的第一个孩子lchild,一个指向它的下个兄弟next,一个指向它的上个兄弟prev(对于最左边的兄弟则指向它的父亲),对于第一个孩子,prev属性表示该孩子的父结点;对于其他结点,prev属性表示该结点的左兄弟。
2.1.1. phn_merge_ordered
把大的作为小的树的最左孩子,插入配对树,小的树如果有孩子作为大的树的根节点的兄弟节点。
2.1.2. ph_merge_siblings
对兄弟节点两两进行merge,merge完后插入FIFO队尾(FIFO是单链表的),再进行后续节点的操作,直到只剩下一个元素为止。
由于一开始没有队尾节点,所以先进行一轮的merge操作,找到队尾和头,然后再进行循环的merge操作,直到只剩下一个节点为止。
排序后返回一个最小值的节点。
2.1.3. ph_merge_aux
对一个树作排序,找到一个最小值,作为树的root。
2.1.4. ph_merge_children
对孩子节点做排序操作,找到一个最小值。
2.1.5. a_prefix##first
对这个树作排序,找到一个最小值并返回。调用ph_merge_aux。
2.1.6. a_prefix##insert
如果树不为空,作为第一个兄弟节点。如果树为空作为root节点。
/* \
- Treat the root as an aux list during insertion, and lazily \
- merge during a_prefix##remove_first(). For elements that \
- are inserted, then removed via a_prefix##remove() before the \
- aux list is ever processed, this makes insert/remove \
- constant-time, whereas eager merging would make insert \
- O(log n). \
2.1.7. a_prefix##remove_first
对这个树作排序,找到一个最小值作为根节点,并且调用ph_merge_children,对孩子节点做排序操作,找到一个最小值作为树的新的根节点。返回原树的根节点。
2.1.8. a_prefix##remove
1)如果被删除的根节点,需要对树做merge。Merge后如果还是根节点,则需要对孩子节点做merge找到一个新的根节点。这样删除后树还是保持最小值在根节点。
2)如果被删除节点是最左孩子节点,则存在父节点。要不不存在父节点。
3)如果被删除节点是一个树,则可以对被删除节点所在的树的孩子节点进行merge,merge后从被删除节点所在的树找新的根节点,如果新的根节点存在,可以用这个节点代替被删除节点,如果该节点不存在,则直接删除这个节点。
2.1.9. 配对堆在jemalloc中的使用
主要用来管理arena_t的runs_avail,和arena_bin_t的runs。
Jemalloc 深入分析
Copyright 2013 Spreadtrum Communications Inc. 6
/* Generate pairing heap functions. */
ph_gen(static UNUSED, arena_run_heap_, arena_run_heap_t, arena_chunk_map_misc_t, ph_link, arena_snad_comp)
#define ph_gen(a_attr, a_prefix, a_ph_type, a_type, a_field, a_cmp)
a_attr void a_prefix##new(a_ph_type *ph)
a_attr bool a_prefix##empty(a_ph_type *ph)
a_attr a_type * a_prefix##first(a_ph_type *ph)
a_attr void a_prefix##insert(a_ph_type *ph, a_type *phn)
a_attr a_type * a_prefix##remove_first(a_ph_type *ph)
a_attr void a_prefix##remove(a_ph_type *ph, a_type *phn)
实际的定义函数如下:
static void arena_run_heap_new(arena_run_heap_t *ph)
static bool arena_run_heap_empty(arena_run_heap_t *ph)
static a_type * arena_run_heap_first(arena_run_heap_t *ph)
static void arena_run_heap_insert(arena_run_heap_t *ph, arena_chunk_map_misc_t *phn)
static a_type * arena_run_heap_remove_first(arena_run_heap_t *ph)
static void arena_run_heap_remove(arena_run_heap_t *ph, arena_chunk_map_misc_t phn)
/ Node structure. */
#define phn(a_type)
struct {
a_type *phn_prev;
a_type *phn_next;
a_type phn_lchild;
}
/ Root structure. */
#define ph(a_type)
struct {
a_type *ph_root;
}
typedef ph(arena_chunk_map_misc_t) arena_run_heap_t;
struct {
arena_chunk_map_misc_t ph_root;
};
struct arena_bin_s {
/
- All operations on runcur, runs, and stats require that lock be
- locked. Run allocation/deallocation are protected by the arena lock,
- which may be acquired while holding one or more bin locks, but not
- vise versa.
/
malloc_mutex_t lock;
/ - Current run being used to service allocations of this bin’s size
- class.
*/
arena_run_t runcur;
/ - Heap of non-full runs. This heap is used when looking for an
- existing run when runcur is no longer usable. We choose the
- non-full run that is lowest in memory; this policy tends to keep
- objects packed well, and it can also help reduce the number of
- almost-empty chunks.
/ arena_run_heap_t runs;
/ Bin statistics. /
malloc_bin_stats_t stats;
};
struct arena_s {
Jemalloc 深入分析
Copyright 2013 Spreadtrum Communications Inc. 8
/ This arena’s index within the arenas array. /
unsigned ind;
……
/ - Size-segregated address-ordered heaps of this arena’s available runs,
- used for first-best-fit run allocation. Runs are quantized, i.e.
- they reside in the last heap which corresponds to a size class less
- than or equal to the run size.
*/ arena_run_heap_t runs_avail[NPSIZES];
};
phn(arena_chunk_map_misc_t) ph_link;
struct {
arena_chunk_map_misc_t *phn_prev;
arena_chunk_map_misc_t *phn_next;
arena_chunk_map_misc_t phn_lchild;
}
/ - Each arena_chunk_map_misc_t corresponds to one page within the chunk, just
- like arena_chunk_map_bits_t. Two separate arrays are stored within each
- chunk header in order to improve cache locality.
/
struct arena_chunk_map_misc_s {
/ - Linkage for run heaps. There are two disjoint uses:
- arena_t’s runs_avail heaps.
- arena_bin_t conceptually uses this linkage for in-use non-full
- runs, rather than directly embedding linkage.
/ phn(arena_chunk_map_misc_t) ph_link;
union {
/ Linkage for list of dirty runs. /
arena_runs_dirty_link_t rd;
/ Profile counters, used for large object runs. */
union {
void *prof_tctx_pun;
prof_tctx_t prof_tctx;
};
/ Small region run metadata. */
arena_run_t run;
};
};
比较函数:arena_snad_comp,先比较arena_sn_comp,如果两个arena_chunk_map_misc_t 来自同一个chunk,则arena_sn_comp结果一样,再用arena_ad_comp直接比较两个地址。
详细文章请参考:《jemalloc 深入分析》
https://github.com/everschen/tools/blob/master/DOC/Jemalloc.pdf
https://download.csdn.net/download/ip5108/10941278
Jemalloc 深入分析 之 配对堆Pairing Heap相关推荐
- 配对堆Pairing Heap
前言 最近做一道Dijkstra的题目,因为边数实在太大了(10910910^9),用STL的priority_queue直接超时(事实上还会MLE).有同学写配对堆的.刚好很久没学习新的数据结构了, ...
- 配对堆(Pairing Heap)
配对堆(Pairing Heap)是一个简单实用的min-heap结构(当然也可以做成max-heap).它是一颗多路树(multiway tree),类似于Leftist Heap和Skew Hea ...
- 结构之美——优先队列三大结构(三)——Pairing Heap
转自http://dsqiu.iteye.com/blog/1714961 1.Pairing Heap简介 斐波那契堆主要有两个缺点:编程实现难度较大和实际效率没有理论的那么快(由于它的存储结构和四 ...
- 堆(heap)与栈(stack)的区别(一)
堆区(heap):一般由程序员分配和释放,若程序员不释放,程序结束时可能由操作系统回收,但它与数据结构中的堆不是一回事,分配方式类似于链表. 栈(stack):由编译器自动分配和释放,存函数的参数值, ...
- 【编程】堆(heap)和栈(stack)的区别
从C/C++的内存分配(与操作系统相关)上来说,堆(heap),栈(stack)属于内存空间的一段区域. 效率: 栈是机器系统提供的数据结构,计算机会在底层对栈提供支持(有专门的寄存器存放栈的地址,压 ...
- C++二叉堆binary heap (附完整源码)
二叉堆binary heap 二叉堆binary heap 算法的完整源码(定义,实现,main函数测试) 二叉堆binary heap 算法的完整源码(定义,实现,main函数测试) #includ ...
- 11.JDK8内存模型、本地方法栈、虚拟机栈、栈帧结构(局部变量表、操作数栈、方法出口、虚拟机栈与本地方法栈的关系、寄存器、方法区、堆(Heap)、jvm中的常量池、Metaspace(元空间))
11.JDK8内存模型 11.1.本地方法栈(Native Method Stacks) 11.2.虚拟机栈(Java Virtual Machine Stacks) 11.3.栈帧结构 11.3.1 ...
- 返回局部变量或临时变量的地址_值传递和地址返回两者在堆区(Heap)应用的三种易错点...
1.指针变量作为参数进行值传递给函数的形参,并在堆区(Heap)进行内存分配和赋值 程序源码: 1 结果: Segmentation fault (core dumped) 分析: 如上图,指针变量p ...
- 看动画学算法之:二叉堆Binary Heap
文章目录 简介 二叉堆的特性 二叉堆的作用 二叉堆的构建 获取二叉堆的最大值 二叉堆的插入 insert操作的时间复杂度 二叉堆的提取Max操作 extractMax的时间复杂度 创建二叉堆 简介 我 ...
最新文章
- 基于三维卷积神经网络的RGB-D显著目标检测
- 打印Java数组的最简单方法是什么?
- boost::mpl模块bind相关的测试程序
- SAP CRM HANA report里 默认filter 的工作机制分析
- python变量持久化_Python 数据持久化:JSON
- Spring Boot 全局异常机制
- IOS 8.0 适配应用图片设计
- MySQL高阶面试题
- linux 文件系统 xfs、ext4、ext3 的区别
- P2207 Photo
- Atitit 安全审计法 目录 1. 安全审计数据结构	1 2. Expame 提现流程	1 2.1. 获取提现钱的数据余额	1 2.2. 扣去余额	1 2.3. 开始safe log	2 2.4.
- Davinci Configurator之User Config File配置功能
- TP6如何配置多应用?
- Excel/WPS如何查找重复数据
- 不错的一个团队积分互换游戏
- 桌面上的文件夹存储路径是什么?桌面文件夹误删了怎么找回
- (与运算)、|(或运算)、^(异或运算)等运算符的解释与运用
- 液晶LCD1602驱动代码
- JAVA获取tomcat信息
- 微博将于今日晚间挂牌上市 最高融资金额4.37亿美元
热门文章
- Windows下安装Boot Camp提示版本不适用
- 计算机的硬件故障维修,计算机硬件故障分析与解决方法
- 中国开源项目哪家强?看看阿里,百度,腾讯,360,新浪,网易,小米等都开源了什么
- ansys 软件安装注意事项
- 【2021版PHP高级教程-Swoole4.X从入门到精通全套高级实战】
- ST-Link SWD接口接线
- FFmpeg —— Linux下进行编译配置(硬件加速编解码)
- PS PNG导出的时候是否交错有什么影响
- 2022 CCPC 威海 赛后总结
- ESP8266-Arduino编程实例-ILI9341-TFT LCD驱动(基于TFT_eSPI库)