GlusterFS之内存池(mem-pool)使用实例分析
2012-06-29 10:50
746 查看
http://blog.csdn.net/wanweiaiaqiang/article/details/7515536
第一步:分配和初始化:
cli进程在初始化的过程中会涉及到内存池的建立和初始化,具体涉及到内存池初始化的代码如下(在cli.c文件中的glusterfs_ctx_defaults_init函数):
[cpp]
view plaincopy
/* frame_mem_pool size 112 * 64 */
pool->frame_mem_pool = mem_pool_new (call_frame_t, 32);//为调用针对象分配内存池对象,对象类型是call_frame_t,32个这样的内存块
if (!pool->frame_mem_pool)
return -1;
/* stack_mem_pool size 256 * 128 */
pool->stack_mem_pool = mem_pool_new (call_stack_t, 16);//为调用堆栈对象分配内存池对象,对象类型是call_stack_t,16个这样的内存块
if (!pool->stack_mem_pool)
return -1;
ctx->stub_mem_pool = mem_pool_new (call_stub_t, 16);
if (!ctx->stub_mem_pool)
return -1;
ctx->dict_pool = mem_pool_new (dict_t, 32);
if (!ctx->dict_pool)
return -1;
ctx->dict_pair_pool = mem_pool_new (data_pair_t, 512);
if (!ctx->dict_pair_pool)
return -1;
ctx->dict_data_pool = mem_pool_new (data_t, 512);
if (!ctx->dict_data_pool)
return -1;
由上面的代码可以看出:集合系统中各种结构体对象可能实际会用到的数量来预先分配好,真正需要为对象内存的时候直接从这些内存池中取就可以了,用完之后又放回内存池,这样减少了分配和释放内存的额外系统开销,分配内存往往需要从用户态到内核态切换,这些都是很耗时间的,当然相同的对象还减少了初始化的时间。
代码分配内存调用的函数是mem_pool_new,而不是在上一篇博客结束的mem_pool_new_fn函数,那是因为mem_pool_new是定义的宏函数,就是调用mem_pool_new_fn函数,函数参数分别表示对象所占内存大小、数量和名称(为分配的内存起一个名字,就是对象的名称);
[cpp]
view plaincopy
#define mem_pool_new(type,count) mem_pool_new_fn (sizeof(type), count, #type)
第二步:从内存池中取出一个对象内存块:
如下面代码取出一个调用存根的对象内存块(call_stub_t):
[cpp]
view plaincopy
call_stub_t *new = NULL;
GF_VALIDATE_OR_GOTO ("call-stub", frame, out);
new = mem_get0 (frame->this->ctx->stub_mem_pool);//从内存池中拿出一个对象内存块
同样使用的函数不是我们介绍的mem_get,而是mem_get0函数,mem-get0封装了mem_get,做参数判断并且把需要使用的内存初始化为0,代码如下:
[cpp]
view plaincopy
void*
mem_get0 (struct mem_pool *mem_pool)
{
void *ptr = NULL;
if (!mem_pool) {
gf_log_callingfn ("mem-pool", GF_LOG_ERROR, "invalid argument");
return NULL;
}
ptr = mem_get(mem_pool);//得到一个内存对象块
if (ptr)
memset(ptr, 0, mem_pool->real_sizeof_type);//初始化0
return ptr;
}
第三步:放回对象内存块到内存池中:
当我们使用完一个对象以后就会重新放回内存池中,例如还是以调用存根对象(call_stub_t)
[cpp]
view plaincopy
void
call_stub_destroy (call_stub_t *stub)
{
GF_VALIDATE_OR_GOTO ("call-stub", stub, out);
if (stub->wind) {
call_stub_destroy_wind (stub);
} else {
call_stub_destroy_unwind (stub);
}
stub->stub_mem_pool = NULL;
mem_put (stub);//放回对象内存块到内存池中
out:
return;
}
第四步:销毁内存池:
如果整个内存池对象都不需要了,那么销毁掉这个内存池,实现这个功能的函数是mem_pool_destroy:
[cpp]
view plaincopy
void
mem_pool_destroy (struct mem_pool *pool)
{
if (!pool)
return;
gf_log (THIS->name, GF_LOG_INFO, "size=%lu max=%d total=%"PRIu64,
pool->padded_sizeof_type, pool->max_alloc, pool->alloc_count);
list_del (&pool->global_list);//从全局内存池对象中拖链
LOCK_DESTROY (&pool->lock);//销毁锁
GF_FREE (pool->name);//释放名字占用的内存
GF_FREE (pool->pool);//释放内存池分配的内存,就是提供给用户使用的那一段内存
GF_FREE (pool);//释放内存池对象占用的内存
return;
}
一般情况下内存池对象会在程序退出的时候才会释放和销毁,还有一种情况是临时分配的内存池也有可能在系统运行期间释放和销毁,因为不能保证一个预先分配的内存池就能够满足整个系统运行期间那个对象所需要的内存,可能在每一个阶段这个对象使用特别多,以至于把内存池预先分配的对象内存块使用完了,这时就需要临时分配内存池对象,过了这一段时间可能这个对象需要的个数就减少了,这时就需要释放掉临时分配的,已还给系统内存。OK!内存池管理技术是提供内存使用率和效率的重要手段,Glusterfs使用的内存池技术采用的是linux内核管理小内存块的分配算法slab,就是基于对象分配内存的技术。可以先去熟悉slab的原理,就能更好的理解Glusterfs的内存池技术了!
第一步:分配和初始化:
cli进程在初始化的过程中会涉及到内存池的建立和初始化,具体涉及到内存池初始化的代码如下(在cli.c文件中的glusterfs_ctx_defaults_init函数):
[cpp]
view plaincopy
/* frame_mem_pool size 112 * 64 */
pool->frame_mem_pool = mem_pool_new (call_frame_t, 32);//为调用针对象分配内存池对象,对象类型是call_frame_t,32个这样的内存块
if (!pool->frame_mem_pool)
return -1;
/* stack_mem_pool size 256 * 128 */
pool->stack_mem_pool = mem_pool_new (call_stack_t, 16);//为调用堆栈对象分配内存池对象,对象类型是call_stack_t,16个这样的内存块
if (!pool->stack_mem_pool)
return -1;
ctx->stub_mem_pool = mem_pool_new (call_stub_t, 16);
if (!ctx->stub_mem_pool)
return -1;
ctx->dict_pool = mem_pool_new (dict_t, 32);
if (!ctx->dict_pool)
return -1;
ctx->dict_pair_pool = mem_pool_new (data_pair_t, 512);
if (!ctx->dict_pair_pool)
return -1;
ctx->dict_data_pool = mem_pool_new (data_t, 512);
if (!ctx->dict_data_pool)
return -1;
由上面的代码可以看出:集合系统中各种结构体对象可能实际会用到的数量来预先分配好,真正需要为对象内存的时候直接从这些内存池中取就可以了,用完之后又放回内存池,这样减少了分配和释放内存的额外系统开销,分配内存往往需要从用户态到内核态切换,这些都是很耗时间的,当然相同的对象还减少了初始化的时间。
代码分配内存调用的函数是mem_pool_new,而不是在上一篇博客结束的mem_pool_new_fn函数,那是因为mem_pool_new是定义的宏函数,就是调用mem_pool_new_fn函数,函数参数分别表示对象所占内存大小、数量和名称(为分配的内存起一个名字,就是对象的名称);
[cpp]
view plaincopy
#define mem_pool_new(type,count) mem_pool_new_fn (sizeof(type), count, #type)
第二步:从内存池中取出一个对象内存块:
如下面代码取出一个调用存根的对象内存块(call_stub_t):
[cpp]
view plaincopy
call_stub_t *new = NULL;
GF_VALIDATE_OR_GOTO ("call-stub", frame, out);
new = mem_get0 (frame->this->ctx->stub_mem_pool);//从内存池中拿出一个对象内存块
同样使用的函数不是我们介绍的mem_get,而是mem_get0函数,mem-get0封装了mem_get,做参数判断并且把需要使用的内存初始化为0,代码如下:
[cpp]
view plaincopy
void*
mem_get0 (struct mem_pool *mem_pool)
{
void *ptr = NULL;
if (!mem_pool) {
gf_log_callingfn ("mem-pool", GF_LOG_ERROR, "invalid argument");
return NULL;
}
ptr = mem_get(mem_pool);//得到一个内存对象块
if (ptr)
memset(ptr, 0, mem_pool->real_sizeof_type);//初始化0
return ptr;
}
第三步:放回对象内存块到内存池中:
当我们使用完一个对象以后就会重新放回内存池中,例如还是以调用存根对象(call_stub_t)
[cpp]
view plaincopy
void
call_stub_destroy (call_stub_t *stub)
{
GF_VALIDATE_OR_GOTO ("call-stub", stub, out);
if (stub->wind) {
call_stub_destroy_wind (stub);
} else {
call_stub_destroy_unwind (stub);
}
stub->stub_mem_pool = NULL;
mem_put (stub);//放回对象内存块到内存池中
out:
return;
}
第四步:销毁内存池:
如果整个内存池对象都不需要了,那么销毁掉这个内存池,实现这个功能的函数是mem_pool_destroy:
[cpp]
view plaincopy
void
mem_pool_destroy (struct mem_pool *pool)
{
if (!pool)
return;
gf_log (THIS->name, GF_LOG_INFO, "size=%lu max=%d total=%"PRIu64,
pool->padded_sizeof_type, pool->max_alloc, pool->alloc_count);
list_del (&pool->global_list);//从全局内存池对象中拖链
LOCK_DESTROY (&pool->lock);//销毁锁
GF_FREE (pool->name);//释放名字占用的内存
GF_FREE (pool->pool);//释放内存池分配的内存,就是提供给用户使用的那一段内存
GF_FREE (pool);//释放内存池对象占用的内存
return;
}
一般情况下内存池对象会在程序退出的时候才会释放和销毁,还有一种情况是临时分配的内存池也有可能在系统运行期间释放和销毁,因为不能保证一个预先分配的内存池就能够满足整个系统运行期间那个对象所需要的内存,可能在每一个阶段这个对象使用特别多,以至于把内存池预先分配的对象内存块使用完了,这时就需要临时分配内存池对象,过了这一段时间可能这个对象需要的个数就减少了,这时就需要释放掉临时分配的,已还给系统内存。OK!内存池管理技术是提供内存使用率和效率的重要手段,Glusterfs使用的内存池技术采用的是linux内核管理小内存块的分配算法slab,就是基于对象分配内存的技术。可以先去熟悉slab的原理,就能更好的理解Glusterfs的内存池技术了!
相关文章推荐
- GlusterFS之内存池(mem-pool)使用实例分析
- GlusterFS之内存池(mem-pool)使用实例分析
- GlusterFS之内存池(mem-pool)使用实例分析
- GlusterFS之内存池(mem-pool)实现原理及代码详解
- GlusterFS之内存池(mem-pool)实现原理及代码详解
- GlusterFS之内存池(mem-pool)实现原理及代码详解
- GlusterFS之内存池(mem-pool)实现原理及代码详解
- 【Storm】storm安装、配置、使用以及Storm单词计数程序的实例分析
- Android 从具体实例分析Bitmap使用时候内存注意点
- 实例讲解:使用IBM heapAnalyzer分析heap dump文件步骤 .
- PyQt4 精彩实例分析* 实例2 标准对话框的使用
- 线程间通讯:WaitHandler使用实例及分析
- PHP中静态变量的使用方法实例分析
- Rational Purify 使用及分析实例
- 使用PHPExcel操作Excel用法实例分析
- 彻底学会使用epoll(四)——ET的写操作实例分析
- nginx源码分析—内存池结构ngx_pool_t及内存管理
- jsp中Action使用session方法实例分析
- 使用wireshark分析网络流量实例
- Java使用Statement接口执行SQL语句操作实例分析