Tcmalloc源码简单分析(2)

本文详细介绍了Free过程的工作原理,包括如何根据指针获取对象大小、利用Threadcache和Centralcache释放对象的过程,以及Pageheap如何处理大型对象的释放和回收。

Free过程

1、             首先free根据提供的ptr指针,获得此ptr所在的页面,然后利用页面号,获取需要释放的objsize,这个size首先从pagemap_cache_中拿,如果不在pagemap_cache_中那么直接通过页面好获取所在的span,如果spanNULL,那么直接报错返回,否则通过span获取需要释放的objsize,并将sizepage的关系放入pagemap_cache_

2、             如果能够获取ptr所指objsize,且本释放是在子线程内(可以获取threadcache),那么调用threadcacheDeallocate释放,转到一下步。否则利用InsertRange直接将obj插入Centralcache对应sizefreelist。如果ptr所指的obj size0,有可能是大的obj,直接从pageheap中拿的,那么跳第5步。

3、             Threadcache通过相应的size获得对应的freelist,然后通过pushobj链入freelist。如果插入之后的list太长将通过ReleaseToCentralCachenum_objects_to_moveobj返还给CentralCache,如果整个threadcachesize太大,那么将对整个free数组进行遍历,调用ReleaseToCentralCache函数。

4、             ReleaseToCentralCache将通过对应CentralCachefreelist调用InsertRange将需要返还给CentralCacheobjs插入CentralCacheCentralCache判断所返还的obj数量是不是正好等于num_objects_to_move,如果是且slots_里面有空闲区,那么直接返还给slots_,否则将这些obj返回给相应的Span,如果本Span通过返还之后已经是有freeobj了,将此Spanempty_列表转移到nonempty_列表,如果此Span已经全部空闲了,没有还在被使用的obj,那么通过Static::pageheap()->Delete返还给pageheap

5、             Pageheap通过Delete函数将返还回来Span的相关参数清零,并设置当前SpanON_NORMAL_FREELIST。然后判断此Span能不能和前后相邻的Span合并,然后将Span插入相应sizenormal队列,最后判断是否需要回收,如果需要,尝试回收至少一个页面,回收动作主要讲Spannormal列表转移到return列表,并调用TCMalloc_SystemRelease将页面标记为可回收的,然后通过系统调用madvise(reinterpret_cast<char*>(new_start), new_end - new_start,                   MADV_DONTNEED)将物理内存返回给系统,而保留虚拟内存。


### 对 tcmalloc 进行压力测试 #### 测试环境准备 为了确保测试的有效性和准确性,在开始之前需设置合适的测试环境。这包括安装并配置好 tcmalloc 库,以及准备好用于执行多线程操作的应用程序或脚本。 对于 Linux 系统而言,可以使用如下命令来编译和链接应用程序时指定使用 tcmalloc: ```bash export LD_PRELOAD=/usr/lib/libtcmalloc.so ``` 此方法允许动态加载 tcmalloc 而无需修改源码[^2]。 #### 性能评估工具的选择 选用专业的性能分析工具如 Google 的 `perf` 或者 Intel VTune Profiler 来监控内存分配行为及其效率。这些工具可以帮助收集详细的统计数据,比如每次分配所需时间、平均延迟等指标。 #### 压力场景构建 创建模拟高并发访问情景的工作负载模型,通过编写一个多线程应用来进行大量频繁的小型对象分配与释放动作。下面给出一段简单的 C++ 多线程示例代码片段用来展示如何制造这样的负载条件: ```cpp #include <thread> #include <vector> void thread_function() { std::vector<int*> vec; while (true) { // 模拟持续不断的请求处理过程 int* p = new int[rand() % 100]; // 随机大小的对象分配 delete p; // 即刻销毁刚分配出来的对象 } } int main(){ const unsigned num_threads = 8; // 设置线程数量 std::vector<std::thread> threads; for(unsigned i=0;i<num_threads;++i){ threads.push_back(std::thread(thread_function)); } for(auto& th : threads) th.join(); } ``` 上述代码会启动多个线程不断重复申请和释放不同尺寸的整数指针,以此形成密集的内存管理活动流。 #### 数据记录与分析 在整个过程中保持对系统资源消耗情况的关注,特别是 CPU 使用率、上下文切换次数等方面的变化趋势。同时利用前面提到的专业软件获取更深入的信息,例如每秒发生的 malloc/free 次数、命中率等关键参数。 完成一轮完整的压测周期之后,对比启用 tcmalloc 和默认 glibc 下的表现差异,从而得出关于稳定性的结论。 #### 结果解读 通过对所得数据进行全面解析,判断 tcmalloc 是否能够在高压环境下维持良好的表现水平;是否存在明显的瓶颈点或是异常波动现象。最终根据实际需求调整相应的优化措施以提高整体系统的健壮性.
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值