MySQL系列:innodb源代码分析之内存管理
在innodb中实现了自己的内存池系统和内存堆分配系统,在innodb的内存管理系统中,大致分为三个部分:基础的内存块分配管理、内存伙伴分配器和内存堆分配器。innodb定义和实现内存池的主要目的是提供内存的使用率和效率,防止内存碎片和内存分配跟踪和调试。我们先来看看他们的关系和结构。
下面是它的关系结构图:
上图中的:
ut_mem_block块是基础内存管理
Buddy allocator是内存伙伴分配器
mem_heap是内存堆分配器
1.基础内存管理
通过一个链表结构体来管理已经分配的内存。结构体例如以下:
typedef ut_mem_block_struct
{
ulint size; /*这个被分配block的内存大小*/
ulint magic_n; /*节点魔法字,用于校验所用*/
UT_LIST_NODE_T(ut_mem_block_t) mem_block_list; /*block list node,指定prev node和next node*/
};
关于block的list定义是个全局的变量。UT_LIST_BASE_NODE_T(ut_mem_block_t)
ut_mem_block_list;全部分配的block都会增加到这个list其中。
在ut_malloc_low函数分配内存的时候会将分配的block增加到list其中。在ut_free的时候会所释放的内存所在的block从list其中删除。
除了这两个函数以外,innodb还提供ut_free_all_mem函数来释放全部分配的block和统计分配内存的总数ut_total_allocated_memory功能。
ut_malloc_low 分配一个n长度的内存块,并将分配的块记录到ut_mem_block_list其中.
ut_malloc 与ut_malloc_low功能同样,可是会用0初始化所分配的内存。
ut_free 释放一个分配的内存块,并将其从ut_mem_block_list其中删除。
ut_free_all_mem 释放ut_mem_block_list全部的内存块并清空ut_mem_block_list
以上函数是支持多线程并发操作的。也就是说是线程安全的。
2.伙伴分配器
innodb的伙伴分配器是基于2的基数为基础的管理方式,其buddy alloc pool的定义例如以下:
struct mem_pool_struct
{
byte* buf; /*总体内存的句柄*/
ulint size; /*总体内存大小*/
ulint reserved; /*当前分配出去的总内存大小*/
mutex mutex; /*多线程相互排斥量*/
UT_LIST_BASE_NODE_T(mem_area_t) free_list[64]; /*area_t链表数组,每一个数组单元能管理2的i次方内存块列表,i是数组的下标*/
};
struct mem_area_struct
{
ulint size_and_free; /*area的内存大小(一定是2的次方),最后一个bit表示是否已经释放*/
UT_LIST_NODE_T(mem_area_t) free_list; /*area链表的上下area,由于buddy area是会分裂的,有可能多个*/
};
mem_area_t是一个buddy的内存区域。也就是mem_area_struct。
下面是一个32位机器管理1024字节内存块的buddy list分布:
watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQveXVhbnJ4ZHU=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="">
2.1mem_area_t的分裂
2.2mem_area_t的合并
1.使用者归还伙伴分配的内存,首先会依据area_t的信息去找到自己的buddy,也就是第8层另外一个没有被分配的area.
2.找到buddy area后。推断buddy area是否是释放状态,假设是,触发合并。将自己和buddy area从第8层删除,合并成一个512大小的第9层area,
3.在反复1 ~ 2步,又会将自己和第九层另外一个buddy area合并成一个1024大小的第10层area.
2.3buddy allocator的接口函数:
mem_area_alloc 用buddy allocator分配一块内存
mem_area_free 将一块内存归还给buddy allocator
mem_pool_get_reserved 获得buddy allocator已经使用的内存大小
3内存分配堆(memory heap)
struct mem_block_info_struct
{
ulint magic_n; /*魔法字*/
char file_name[8]; /*分配内存的文件*/
ulint line; /*分配内存的文件所在行*/
ulint len; /*block的长度*/
ulint type; /*依赖的底层分配类型,有DYNAMIC、BUFFER、BTR_SEARCH三种类型*/
ibool init_block; /*是否是外部分配的内存块*/ ulint free; /*被占用的空间大小*/
ulint start; /*可分配内存的起始位置*/
byte* free_block; /*备用block,只在BTR_SEARCH方式可用*/ UT_LIST_BASE_NODE_T(mem_block_t) base;
UT_LIST_NODE_T(mem_block_t) list;
};
备注:mem_block_info_struct/mem_block_info_t/mem_block_t/mem_heap_t是等价
mem_heap_t的内存结构例如以下:
1.一个mem_block_t最小空间不小于64字节,标准的大小是8KB,在非MEM_HEAP_BUFFER模式下分配的空间不大于page size - 200(page size一般为16KB)
2.mem_heap_t有三种类型,各自是DYNAMIC、BUFFER、BTR_SEARCH。在DYNAMIC模式下都是基于buddy allocator进行mem_block_t分配的。在BTR_SEARCH模式下,使用free_block来作为内存分配,在BUFFER模式下比較复杂。假设分配的内存大小< page size的一半时,使用buddy alloc,否则使用buf_frame的内存分配方式(这个是属于buf0buf.XX里面的方式。还未開始分析)。
3.mem_heap_t在分配新的mem_block_t的时候一定是分配一个heap最后节点大小的两倍,假设分配的大小超过MEM_MAX_ALLOC_IN_BUF(相当于一个page size)的时候,heap 类型推断,在不是DYNAMIC模式下。最大就是一个MEM_MAX_ALLOC_IN_BUF大小。假设其它模式下就是设置成MEM_BLOCK_STANDARD_SIZE标准大小。在这些限制外,假设须要分配的内存大于这些限制,以分配内存大小为准进行mem_block_t分配。分配好的mem_block_t总是增加到heap
base list的最后,也就是heap堆栈的顶端。
4.mem_heap_t在释放mem_block_t时候总是从顶端開始释放,直到不能释放为止(mem_block_t没有被使用者归还)。在mem_block_t释放的时候也是须要參考DYNAMIC、BUFFER、BTR_SEARCH类型进行相对于的归还规则(和2要点是相相应的)。
mem_heap_create 用DYNAMIC模式创建一个mem_heap_t
mem_heap_create_in_buffer 用BUFFER模式创建一个mem_heap_t
mem_heap_create_in_btr_search 用BTR_SEARCH模式创建一个mem_heap_t
mem_heap_free 释放mem_heap_t对象
mem_alloc 创建在MEM_HEAP_DYNAMIC模式下。并分配一块指定大小的内存(在这样的方式下mem_heap_t仅仅会有一个mem_block_t)
mem_free 归还mem_heap_t分配的内存,并释放mem_heap_t
mem_heap_alloc 在指定的mem_heap_t上分配一块内存
mem_heap_get_heap_top 获得heap顶端块可使用内存的地址
mem_heap_empty 清空指定的mem_heap_t
mem_heap_get_top 获得heap顶部的指定n大小的mem_block_t指针
mem_heap_free_top 释放heap顶部N大小的mem_block_t块
4总结
在MySQL-5.6的版本号中。innodb提供两种选择,一种是使用innodb提供的内存池管理内存,另一种是提供系统的malloc和free来作为内存管理。MySQL默认的是系统管理内存方式,一些有经验的DBA会使用系统的管理内存方式+TMalloc来做内存优化。借助TMalloc高效的内存管理方式实现MySQL的性能提升。
MySQL系列:innodb源代码分析之内存管理的更多相关文章
- redis 源代码分析(一) 内存管理
一,redis内存管理介绍 redis是一个基于内存的key-value的数据库,其内存管理是很重要的,为了屏蔽不同平台之间的差异,以及统计内存占用量等,redis对内存分配函数进行了一层封装,程序中 ...
- cocos2d-x 源代码分析 : Ref (CCObject) 源代码分析 cocos2d-x内存管理策略
从源代码版本号3.x.转载请注明 cocos2d-x 总的文件夹的源代码分析: http://blog.csdn.net/u011225840/article/details/31743129 1.R ...
- Memcached源码分析之内存管理
先再说明一下,我本次分析的memcached版本是1.4.20,有些旧的版本关于内存管理的机制和数据结构与1.4.20有一定的差异(本文中会提到). 一)模型分析在开始解剖memcached关于内存管 ...
- iOS的内存分析和内存管理
iOS的内存分析和内存管理 [内存管理]一直是iOS开发中的一个重点. 本文就带你从内存分析开始一步步了解内存的占用情况,从真实的情况中领悟真正项目开发过程中的内存的使用情况. 注:本文默认你熟悉 M ...
- TestNG源代码分析:依赖管理的实现
TestNG源代码分析:依赖管理的实现 2018-03-19 1 背景 当case之间有依赖关系,有依赖关系的case,它们的执行顺序是有限制的.TestNG提供了依赖管理功能 2 基础理论 这个执行 ...
- MySQL InnoDB技术内幕:内存管理、事务和锁
前面有多篇文章介绍过MySQL InnoDB的相关知识,今天我们要更深入一些,看看它们的内部原理和机制是如何实现的. 一.内存管理 我们知道,MySQl是一个存储系统,数据最后都写在磁盘上.我们以前也 ...
- linux 内核源代码情景分析——linux 内存管理的基本框架
386 CPU中的页式存管的基本思路是:通过页面目录和页面表分两个层次实现从线性地址到物理地址的映射.这种映射模式在大多数情况下可以节省页面表所占用的空间.因为大多数进程不会用到整个虚存空间,在虚存空 ...
- nginx源代码分析之内存池实现原理
建议看本文档时结合nginx源代码. 1.1 什么是内存池?为什么要引入内存池? 内存池实质上是接替OS进行内存管理.应用程序申请内存时不再与OS打交道.而是从内存池中申请内存或者释放内存到内存池 ...
- redis源代码解读之内存管理————zmalloc文件
本文章主要记录本人在看redis源代码的一些理解和想法.由于功力有限,肯定会出现故障,所以.希望高手给出指正. 第一篇就是内存相关的介绍.由于我喜欢先看一些组件的东西,再看总体的流程. 先上一下代码吧 ...
随机推荐
- Drop和Truncate与Delete的区别
1.Drop DROP TABLE test; 删除表test,并释放空间,将test删除的一干二净.(结构也被完全删除) 2.Truncate TRUNCATE test; 删除表test里的内容, ...
- CSU1020: 真三国无双
1020: 真三国无双 Submit Page Summary Time Limit: 1 Sec Memory Limit: 128 Mb Submitted: 1042 ...
- 绑定IP 绑定设备
首先引别人的组播测试如下 1. 一个udp client可以同时往多个组播地址发送数据,多个udpclient可以同时往一个组播发数据. 2. 本地udp必须监听组播端口,否则收不到数据.3. 一个u ...
- ECNU 3260 袋鼠妈妈找孩子(dfs)
链接:http://acm.ecnu.edu.cn/problem/3260/ 题意: 给出一个x,y,k.求从左上角到(x,y)最短路径不少于k而且最快到达(x,y)的迷宫.(迷宫有多个 输出其中一 ...
- 10-看图理解数据结构与算法系列(B+树)
B+树 B+树是B树的一种变体,也属于平衡多路查找树,大体结构与B树相同,包含根节点.内部节点和叶子节点.多用于数据库和操作系统的文件系统中,由于B+树内部节点不保存数据,所以能在内存中存放更多索引, ...
- admin源码之url设计
如何实现批量设计url? 1.创建Django项目 2.新建app01 和 app02 3.在models.py中创建模型 4.在settings.py中完成数据库配置.app配置等 5.数据库迁移 ...
- [luoguP2957] [USACO09OCT]谷仓里的回声Barn Echoes(Hash)
传送门 团队里的hash水题,数据小的不用hash都能过.. 也就是前缀hash,后缀hash,再比较一下就行. ——代码 #include <cstdio> #include <c ...
- 面向对象:继承(经典类&新式类继承原理、属性查找)、派生
继承: 继承是指类与类之间的关系,是一种“什么”是“什么”的关系. 继承的功能之一就是用来解决代码重用问题 继承是一种创建新类的方式,在Python中,新建的类可以继承一个或多个父类,父类又可以称为基 ...
- idea使用之maven本地索引更新
idea使用起来的确挺顺手的,但遇到一些问题时,直接百度很难有答案,只能自己慢慢摸索了. 今天在倒腾idea仓库索引的时候,就出事情啦. 先说idea更新本地仓库索引吧,打开settings--> ...
- vimtips阅读记录
__BEGIN__ *vimtips.txt* For Vim version 8.0. ------------------------------------------------------- ...