【tcmalloc】优化方法

发布时间:2023年12月23日

一.脱离new使用定长内存池

此项目本意是脱离malloc的使用,但若使用new的话仍然会使用到malloc。因为centralcache和pagecache本身是单例,不考虑创建对象的问题,但是每个线程自身拥有个线程缓冲区和span结构是要考虑new的问题的,引入定长内存池替换new可一提高效率。

二.释放内存的时候不传入对象大小

我们在释放的时候可以拿到内存块的真实物理地址,我们可以通过物理地址找到页号,在通过哈希找到对应的span块。因为所有的span块都是在centralcache统一切分的。所以一整块span块的切分的自由链表内存是固定的。只要在span块内增加一个变量记录对象大小,就可以直接通过span块获得到当前对象的大小。同时大于128页的内存申请我们按照span块的方式去申请也可以通过同样的方式获取到申请的内存大小。

这会导致一个新的问题,我们的哈希映射多次重复使用但没有加锁,在写的时候其实是加了锁的,因为centralcache获取新的span块,和pagecache内部找剩余的大块span的操作都是加了锁的。但是我们的读操作并没有加锁,比如在释放的环节我们要先通过哈希映射拿到释放大小,这时候就有可能发生读写冲突问题,所以我们要对哈希映射的模块加锁,可以采用raii或者直接使用基数树。

三,通过基数树优化哈希映射

通过性能测试可以知道,大部分耗时间都集中在哈希查找的过程中和加锁的过程。采用基数树,相当于空间换取时间,直接定值法,可以用一层或者两层的,对于64 位下则必须使用三层基数树。单层举例,因为32位下一页8k也就是13位,就会产生2^(32-13)=2^19个页号,若是64为就会有2^51个页,乘上映射的指针大小4后就会爆栈,若是多层的因为低下的层不用全部加载,所以省空间。

文章来源:https://blog.csdn.net/m0_62572672/article/details/135128718
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。