关于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 分析笔记的更多相关文章

  1. glusterfs 4.0.1 api 分析笔记1

    一般来说,我们写个客户端程序大概的样子是这样的: /* glfs_example.c */ // gcc -o glfs_example glfs_example.c -L /usr/lib64/ - ...

  2. glusterfs 4.0.1 rpc 分析笔记1

    Jimmy的文档:Glusterfs的rpc模块分析 第一节.rpc服务器端实现原理及代码分析 第二节.rpc客户端实现原理及代码分析 第三节.rpc通信过程分析 经过阅读源码对比之前提及的文档,我个 ...

  3. glusterfs 4.0.1 rpc 分析笔记2 (socket.so 模块)

    socket.c在4000行位置定义了一组结构函数,我们可以从这里开始找到入口,如果是客户端则需要调用connect, 如果是服务端则需要调用listen, struct rpc_transport_ ...

  4. 3.View绘制分析笔记之onLayout

    上一篇文章我们了解了View的onMeasure,那么今天我们继续来学习Android View绘制三部曲的第二步,onLayout,布局. ViewRootImpl#performLayout pr ...

  5. 4.View绘制分析笔记之onDraw

    上一篇文章我们了解了View的onLayout,那么今天我们来学习Android View绘制三部曲的最后一步,onDraw,绘制. ViewRootImpl#performDraw private ...

  6. 2.View绘制分析笔记之onMeasure

    今天主要学习记录一下Android View绘制三部曲的第一步,onMeasure,测量. 起源 在Activity中,所有的View都是DecorView的子View,然后DecorView又是被V ...

  7. 1.Android 视图及View绘制分析笔记之setContentView

    自从1983年第一台图形用户界面的个人电脑问世以来,几乎所有的PC操作系统都支持可视化操作,Android也不例外.对于所有Android Developer来说,我们接触最多的控件就是View.通常 ...

  8. JavaScript中的ParseInt("08")和“09”返回0的原因分析及解决办法

    今天在程序中出现一个bugger ,调试了好久,最后才发现,原来是这个问题. 做了一个实验: alert(parseInt("01")),当这个里面的值为01====>07时 ...

  9. Solr4.8.0源码分析(20)之SolrCloud的Recovery策略(一)

    Solr4.8.0源码分析(20)之SolrCloud的Recovery策略(一) 题记: 我们在使用SolrCloud中会经常发现会有备份的shard出现状态Recoverying,这就表明Solr ...

随机推荐

  1. Session 和 Cookie 区别

    会话跟踪是Web程序中常用的技术,用来跟踪用户的整个会话.常用的会话跟踪技术是Cookie与Session.==Cookie通过在客户端记录信息确定用户身份,Session通过在服务器端记录信息确定用 ...

  2. JAVA_SE基础——11.Java中的运算符

    在程序设计中,运算符应用得十分广泛,通过运算符可以将两个变量进行任意运算.数学中的"+"."-"."*"."/"运算符同 ...

  3. linux下安装配置jdk(解压版)

    在linux下登录oracle官网,下载解压版jdk    传送门 系统默认下载到"下载"目录中 创建要将该文件解压的文件夹: 其中 -p 参数代表递归创建文件夹(可以创建多级目录 ...

  4. Class-Based-View(CBV)

    我们都知道,Python是一个面向对象的编程语言,如果只用函数来开发,有很多面向对象的优点就错失了(继承.封装.多态).所以Django在后来加入了Class-Based-View.可以让我们用类写V ...

  5. 搭建一个web服务下载HDFS的文件

    需求描述 为了能方便快速的获取HDFS中的文件,简单的搭建一个web服务提供下载很方便快速,而且在web服务器端不留临时文件,只做stream中转,效率相当高! 使用的框架是SpringMVC+HDF ...

  6. ELK学习总结(2-4)bulk 批量操作-实现多个文档的创建、索引、更新和删除

    bulk 批量操作-实现多个文档的创建.索引.更新和删除 ----------------------------------------------------------------------- ...

  7. TR069网管协议应用在Android系统开发的前言

    随着智能平台的终端设备不断发展,迫切需要我们解决这些终端的管理问题,而现有的终端统一管理平台已经成熟,主要是基于tr069协议网管平台,比如华为的itms等终端管理平台.所以,这篇文章就是为了实现一种 ...

  8. Django:(博客系统)添加文章(中文)出现UnicodeEncodeError乱码

    添加文章时出现了一个UnicodeEncodeError乱码问题 在添加文章时,抛出了异常: 解决方案,修改manage.py(添加import sys reload(sys) sys.setdefa ...

  9. Spring之IOC(一)

    Spring之IOC(一) 对于Spring的基本概念在这里就不在赘述了. Spring的最核心的两部分则是AOP(面向切面编程)和IOC(控制反转).本篇文章主要讲我对IOC的理解. IOC:即In ...

  10. Vue项目结构说明

    简单介绍目录结构 http://blog.csdn.net/u013778905/article/details/53864289 (别人家的链接,留给我自己看的)