glusterfs4.0.1 mempool 分析笔记
关于3.2.5版本分析,详见《GlusterFS之内存池(mem-pool)实现原理及代码详解》
此4.0.1版本内存池与版本3中的描述变化有点大,总的原理还是类似LINUX中的SLAB算法,定义一系列大小类型的池子,
1. 一共定义了15个池,每个池子大小都是依次幂级数增长的
#define POOL_SMALLEST 7 /* i.e. 128 2的7次幂 */
#define POOL_LARGEST 20 /* i.e. 2048576 2的20次幂 */
#define NPOOLS (POOL_LARGEST - POOL_SMALLEST + 1)
结构体 mem_pool_shared 用来记录每一类池子大小,同时用来记录各种操作的次数,用来检测使用情况以及趋势分析
struct mem_pool_shared
{
unsigned int power_of_two; // 每个池子大小定义
gf_atomic_t allocs_hot;
gf_atomic_t allocs_cold;
gf_atomic_t allocs_stdc;
gf_atomic_t frees_to_list;
};
2. 又定义了一组全局变量:
// 这里定义了内存池的全局变量
static pthread_key_t pool_key; // 用来线程本地存储 per_thread_pool_list_t *pool_list,见 mem_get_pool_list ,初始化见mem_pools_init_early
static pthread_mutex_t pool_lock;
static struct list_head pool_threads; // 用来把每个线程的pool_list 链接在一起,见 mem_get_pool_list (void)
static pthread_mutex_t pool_free_lock;
static struct list_head pool_free_threads; //
static struct mem_pool_shared pools[NPOOLS]; // 总共15个池子类型
static size_t pool_list_size; // 线程上本地存储一个队列,队列里面是15个池子类型的链表头,mem_pools_preinit (void) 里给出了计算方法
每个线程使用本地存储方式保存一个链表,链表是开辟的整块内存,内存头是struct per_thread_pool_list 结构,
后面跟着15个 struct per_thread_pool结构,每个结构都有一个热链表和一个冷链表,分别用来保存正在使用的池链表和暂时空闲的池链表。
在函数per_thread_pool_list_t * mem_get_pool_list (void) 中是分配线程池链表头的初始化代码。
逻辑关系如图:

3. 在struct per_thread_pool链表中挂着很多内存块,每个内存块都是一个小的分配池。每个内存块都用 结构体 struct pooled_obj_hdr 来描述头部。
struct pooled_obj_hdr {
unsigned long magic; // 标记内存块幻数,固定为:#define GF_MEM_HEADER_MAGIC 0xCAFEBABE
struct pooled_obj_hdr *next; // 下一个
struct per_thread_pool_list *pool_list; // 反向引用,指向线程池链表
unsigned int power_of_two; // 块大小
/* track the pool that was used to request this object */
struct mem_pool *pool; //
}
函数 mem_get (struct mem_pool *mem_pool) 是用来获取内存块的函数。
4. struct mem_pool的用法与之前的版本有很大的不同。这个结构体,仅仅用来保存某个类型大小线程池的基本信息,并不实际存储内存块链表。
个人分析如下:之前的版本使用了一个大的结构体管理,但是多个线程竞争影响效率,所以4.0版本每建立一个struct mem_pool 对象就按照大小与 全局 pools[NPOOLS] 相对应,并且将池内存块链表的根使用线程本地存储方式保存。这样每个线程不存在竞争关系。
1)每个需要内存池的地方都是使用宏 mem_pool_new(type,count) 生成。
2)当需要使用内存的时候,调用mem_get0 (struct mem_pool *mem_pool) 。此函数内部再次调用 mem_get(mem_pool) ,该函数内部流程如下:
per_thread_pool_list_t *pool_list = mem_get_pool_list ();
之后从pool_list列表中找到指定大小的per_thread_pool_t *pt_pool,
再根据pooled_obj_hdr_t * retval = mem_get_from_pool (pt_pool); 初始化内存块 前面部分作为 pooled_obj_hdr_t 结构,函数返回结构体后面部分的内存块。
3)释放内存块回链表中:mem_put (void *ptr)
根据ptr指针前移获得 hdr = ((pooled_obj_hdr_t *)ptr) - 1; 检查内存块幻数,并把幻数改为GF_MEM_INVALID_MAGIC 0xDEADC0DE,
之后将内存块放回线程本地存储的对应类型链表头中“hot_list”。
glusterfs4.0.1 mempool 分析笔记的更多相关文章
- glusterfs 4.0.1 api 分析笔记1
一般来说,我们写个客户端程序大概的样子是这样的: /* glfs_example.c */ // gcc -o glfs_example glfs_example.c -L /usr/lib64/ - ...
- glusterfs 4.0.1 rpc 分析笔记1
Jimmy的文档:Glusterfs的rpc模块分析 第一节.rpc服务器端实现原理及代码分析 第二节.rpc客户端实现原理及代码分析 第三节.rpc通信过程分析 经过阅读源码对比之前提及的文档,我个 ...
- glusterfs 4.0.1 rpc 分析笔记2 (socket.so 模块)
socket.c在4000行位置定义了一组结构函数,我们可以从这里开始找到入口,如果是客户端则需要调用connect, 如果是服务端则需要调用listen, struct rpc_transport_ ...
- 3.View绘制分析笔记之onLayout
上一篇文章我们了解了View的onMeasure,那么今天我们继续来学习Android View绘制三部曲的第二步,onLayout,布局. ViewRootImpl#performLayout pr ...
- 4.View绘制分析笔记之onDraw
上一篇文章我们了解了View的onLayout,那么今天我们来学习Android View绘制三部曲的最后一步,onDraw,绘制. ViewRootImpl#performDraw private ...
- 2.View绘制分析笔记之onMeasure
今天主要学习记录一下Android View绘制三部曲的第一步,onMeasure,测量. 起源 在Activity中,所有的View都是DecorView的子View,然后DecorView又是被V ...
- 1.Android 视图及View绘制分析笔记之setContentView
自从1983年第一台图形用户界面的个人电脑问世以来,几乎所有的PC操作系统都支持可视化操作,Android也不例外.对于所有Android Developer来说,我们接触最多的控件就是View.通常 ...
- JavaScript中的ParseInt("08")和“09”返回0的原因分析及解决办法
今天在程序中出现一个bugger ,调试了好久,最后才发现,原来是这个问题. 做了一个实验: alert(parseInt("01")),当这个里面的值为01====>07时 ...
- Solr4.8.0源码分析(20)之SolrCloud的Recovery策略(一)
Solr4.8.0源码分析(20)之SolrCloud的Recovery策略(一) 题记: 我们在使用SolrCloud中会经常发现会有备份的shard出现状态Recoverying,这就表明Solr ...
随机推荐
- php网上支付易宝
巴巴运动网是通过易宝向招商银行打钱,这个首先易宝是需要审核巴巴运动网的钱来的是否正当不然易宝就成了一个洗钱的工具,这个是犯法的:因为钱的来路不明!财政部是需要抓起来的!所以钱的流向实际上是用户的招商银 ...
- H5新特性之webWorker
众所周知javascript是单线程语言,这就是js开发难度较低的原因了,因为不需要解决多线程的资源共享问题(例如死锁),但是单线程性能并不好,因此多了一个webWorker实现js的多进程来提升js ...
- istio入门(02)istio的架构和概念
Istio从逻辑上可以分为数据平面和控制平面: 数据平面主要由一系列的智能代理(Envoy)组成,管理微服务之间的网络通信 控制平面负责管理和配置这些智能代理,并动态执行策略 主要由以下组件构成 En ...
- 新概念英语(1-105)Full Of Mistakes
Lesson 105 Full of mistakes 错误百出 Listen to the tape then answer this question. What was Sandra's pre ...
- 2018年Web前端自学路线
本文最初发表于博客园,并在GitHub上持续更新前端的系列文章.欢迎在GitHub上关注我,一起入门和进阶前端. 以下是正文. Web前端入门的自学路线 新手入门前端,需要学习的基础内容有很多,如下. ...
- 启动Eclipse时An internal error occurred during: "Initializing Java Tooling".错误
解决方法一 重置窗口布局: windows > perspective > reset perspective 解决方法二: 如果上述方法不好使,采用下面的这种方法: 删除workspac ...
- tk mybatis通用mapper,复杂and or条件查询
需求:where查询,需要支持(a or b or c) and d 也就是a.b.c三个条件是或的关系,然后再与d相与. 尝试后,可以通过以下方式处理: 方式1:Weekend语法 Weekend& ...
- Why deep learning?
1. 深度学习中网络越深越好么? 理论上说是这样的,因为网络越深,参数也越多,拟合能力也越强(但实际情况是,网络很深的时候,不容易训练,使得表现能力可能并不好). 2. 那么,不同什么深度的网络,在参 ...
- jquery的ajax全局事件详解
jquery在ajax方面是非常强大和方便的,以下是jquery进行ajax请求时方法模板: $.ajax({ type: "get", url: "" ...
- oracle 11g rac R2 for linux change(public,vip)IP ,hostname (oracle 11g rac R2 修改公有,虚拟,私有IP,网卡)
结构如下: 说明: 节点IP,主机名的修改步骤来自ORACLE support文档: 如何修改集群的公网信息(包括 VIP) (文档 ID 1674442.1) 实验环境情况如下: 实验 节点名称 数 ...