专栏首页技巅GlusterFS之内存池(mem-pool)使用实例分析

GlusterFS之内存池(mem-pool)使用实例分析

上一篇博客详细分析了GlusterFS之内存池的实现技术,今天我们看看GlusterFS是怎么使用这个技术的。

第一步:分配和初始化:

cli进程在初始化的过程中会涉及到内存池的建立和初始化,具体涉及到内存池初始化的代码如下(在cli.c文件中的glusterfs_ctx_defaults_init函数):

[cpp]

  1. /* frame_mem_pool size 112 * 64 */
  2. pool->frame_mem_pool = mem_pool_new (call_frame_t, 32);//为调用针对象分配内存池对象,对象类型是call_frame_t,32个这样的内存块
  3. if (!pool->frame_mem_pool)  
  4. return -1;  
  5. /* stack_mem_pool size 256 * 128 */
  6. pool->stack_mem_pool = mem_pool_new (call_stack_t, 16);//为调用堆栈对象分配内存池对象,对象类型是call_stack_t,16个这样的内存块
  7. if (!pool->stack_mem_pool)  
  8. return -1;  
  9. ctx->stub_mem_pool = mem_pool_new (call_stub_t, 16);  
  10. if (!ctx->stub_mem_pool)  
  11. return -1;  
  12. ctx->dict_pool = mem_pool_new (dict_t, 32);  
  13. if (!ctx->dict_pool)  
  14. return -1;  
  15. ctx->dict_pair_pool = mem_pool_new (data_pair_t, 512);  
  16. if (!ctx->dict_pair_pool)  
  17. return -1;  
  18. ctx->dict_data_pool = mem_pool_new (data_t, 512);  
  19. if (!ctx->dict_data_pool)  
  20. return -1;  

由上面的代码可以看出:集合系统中各种结构体对象可能实际会用到的数量来预先分配好,真正需要为对象内存的时候直接从这些内存池中取就可以了,用完之后又放回内存池,这样减少了分配和释放内存的额外系统开销,分配内存往往需要从用户态到内核态切换,这些都是很耗时间的,当然相同的对象还减少了初始化的时间。

代码分配内存调用的函数是mem_pool_new,而不是在上一篇博客结束的mem_pool_new_fn函数,那是因为mem_pool_new是定义的宏函数,就是调用mem_pool_new_fn函数,函数参数分别表示对象所占内存大小、数量和名称(为分配的内存起一个名字,就是对象的名称);

[cpp]

  1. #define mem_pool_new(type,count) mem_pool_new_fn (sizeof(type), count, #type)

第二步:从内存池中取出一个对象内存块:

如下面代码取出一个调用存根的对象内存块(call_stub_t):

[cpp]

  1. call_stub_t *new = NULL;  
  2. GF_VALIDATE_OR_GOTO (“call-stub”, frame, out);  
  3. new = mem_get0 (frame->this->ctx->stub_mem_pool);//从内存池中拿出一个对象内存块

同样使用的函数不是我们介绍的mem_get,而是mem_get0函数,mem-get0封装了mem_get,做参数判断并且把需要使用的内存初始化为0,代码如下:

[cpp]

  1. void*  
  2. mem_get0 (struct mem_pool *mem_pool)  
  3. {  
  4. void             *ptr = NULL;  
  5. if (!mem_pool) {  
  6.                 gf_log_callingfn (“mem-pool”, GF_LOG_ERROR, “invalid argument”);  
  7. return NULL;  
  8.         }  
  9.         ptr = mem_get(mem_pool);//得到一个内存对象块
  10. if (ptr)  
  11.                 memset(ptr, 0, mem_pool->real_sizeof_type);//初始化0
  12. return ptr;  
  13. }  

第三步:放回对象内存块到内存池中:

当我们使用完一个对象以后就会重新放回内存池中,例如还是以调用存根对象(call_stub_t)

[cpp]

  1. void
  2. call_stub_destroy (call_stub_t *stub)  
  3. {  
  4.         GF_VALIDATE_OR_GOTO (“call-stub”, stub, out);  
  5. if (stub->wind) {  
  6.                 call_stub_destroy_wind (stub);  
  7.         } else {  
  8.                 call_stub_destroy_unwind (stub);  
  9.         }  
  10.         stub->stub_mem_pool = NULL;  
  11.         mem_put (stub);//放回对象内存块到内存池中
  12. out:  
  13. return;  
  14. }  

第四步:销毁内存池:

如果整个内存池对象都不需要了,那么销毁掉这个内存池,实现这个功能的函数是mem_pool_destroy:

[cpp]

  1. void
  2. mem_pool_destroy (struct mem_pool *pool)  
  3. {  
  4. if (!pool)  
  5. return;  
  6.         gf_log (THIS->name, GF_LOG_INFO, “size=%lu max=%d total=%”PRIu64,  
  7.                 pool->padded_sizeof_type, pool->max_alloc, pool->alloc_count);  
  8.         list_del (&pool->global_list);//从全局内存池对象中拖链
  9.         LOCK_DESTROY (&pool->lock);//销毁锁
  10.         GF_FREE (pool->name);//释放名字占用的内存
  11.         GF_FREE (pool->pool);//释放内存池分配的内存,就是提供给用户使用的那一段内存
  12.         GF_FREE (pool);//释放内存池对象占用的内存
  13. return;  
  14. }  

一般情况下内存池对象会在程序退出的时候才会释放和销毁,还有一种情况是临时分配的内存池也有可能在系统运行期间释放和销毁,因为不能保证一个预先分配的内存池就能够满足整个系统运行期间那个对象所需要的内存,可能在每一个阶段这个对象使用特别多,以至于把内存池预先分配的对象内存块使用完了,这时就需要临时分配内存池对象,过了这一段时间可能这个对象需要的个数就减少了,这时就需要释放掉临时分配的,已还给系统内存。

OK!内存池管理技术是提供内存使用率和效率的重要手段,Glusterfs使用的内存池技术采用的是Linux内核管理小内存块的分配算法slab,就是基于对象分配内存的技术。可以先去熟悉slab的原理,就能更好的理解Glusterfs的内存池技术了!

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • GlusterFS之内存池(mem-pool)实现原理及代码详解

    技巅
  • 分布式日志收集系统:Facebook Scribe

    技巅
  • Thrift之TProcess类体系原理及源码详细解析

    技巅
  • GlusterFS之内存池(mem-pool)实现原理及代码详解

    技巅
  • 关于Node.js中内存管理的思考与实践

    随着Node的发展,JavaScript的运行已经不再局限于运行在浏览器中了,Node在服务端的应用使得越来越多的问题也显现出来。对于刚接触JavaScript...

    桃翁
  • rt-thread的内存管理分析

    内存是计算机中十分重要的资源。随着芯片性能的提升,容量的变大,内存资源的管理显得非常重要。内存管理是操作系统中一个基本功能,一般操作系统的功能可以概括为五个部分...

    bigmagic
  • 【专业技术】Android内存泄漏简介

    存在问题: 不少人认为JAVA程序,因为有垃圾回收机制,应该没有内存泄露。 解决方案: 其实如果我们一个程序中,已经不再使用某个对象,但是因为仍然有引用指向它...

    程序员互动联盟
  • HAProxy配置文件详解及常用案例

    版权声明:欢迎交流,菲宇运维!

    菲宇
  • Java 堆内内存与堆外内存

    一般情况下,Java 中分配的非空对象都是由 Java 虚拟机的垃圾收集器管理的,也称为堆内内存(on-heap memory)。虚拟机会定期对垃圾内存进行回收...

    smartsi
  • Android应用性能优化——内存优化(内附一个内存泄露优化实例)

    自动管理内存和回收机制,垃圾回收器负责回收程序中已经不使用,但是仍然被各种对象占用的内存,将程序员从繁重、危险的内存管理工中解放出来。

    trampcr

扫码关注云+社区

领取腾讯云代金券