jemalloc学习笔记

1,首先从内存中申请一块大内存chunk(默认为4M);

2,需要有一个角色来管理申请的多个chunk,这时候arena出场了,它用来管理多个chunk;

3,将内存对象分为三个等级

small  <4k;

large  [4k,4M);

huge >=4M;

4,为了内存对齐,在small中,将此区间分成 44 档,每次小分配请求归整到某档上。例如,小于8字节的,一律分配 8 字节空间;17-32分配请求,一律分配 32 字节空间。对于上述 44 档,有对应的 44 种 runs。每种 run 专门提供此档分配的内存块(叫做 region),每个run默认大小 为4k。

5,在代码上为了对上述44档方便管理定义了一个长度为44的bin数组,bin[44]={8, ......},则用户申请6字节内存大小时,可以得知应该分配索引为0的bin,即bin[0],但是我们也知道在内存上不可能只有一个8字节大小的内存,可能会需要很多这种8字节内存,这时候就需要有多个8字节的run存在 ,run多个就需要在bin[i]中知道当前所在的run,及后面可用的run(用红黑树管理),这时候bin的结构体信息就需要下面这样定义:

 1 struct arena_bin_s {
 2     /* 作用域当前数据结构的锁*/
 3     malloc_mutex_t  lock;
 4     /* 当前正在使用的run */
 5     arena_run_t *runcur;
 6     /* 可用的run构成的红黑树, 主要用于runcur用完的时候。在查找可用run时, 
 7      * 为保证对象紧凑分布,尽量从低地址开始查找,减少快要空闲的chunk的数量。
 8      */
 9     arena_run_tree_t runs;
10     /* 用于bin统计 */
11     malloc_bin_stats_t stats;
12 };

即:在jemalloc的内存管理层面存在如下关系:

 在代码的调用上我们以定义了一个bin的概念,仅用来区分不同size的内存块(region),其实bins就是一个固定长度的数组,不同的index代表不同的内存大小档位,

bins 

比如,bin[0]大小为8字节,则bin[0]会关联多个8字节的runs,记录当前在哪个run上,如果当前run用完了,可以找到下一个run继续分配内存;如果当前所有的run都用完了,则申请一个chunk,分配出所需要空间,剩余的交给arena->runs_avail管理。

推荐

http://tinylab.org/memory-allocation-mystery-%C2%B7-jemalloc-a/

二、jemalloc利用malloc的hook来对代码中的malloc进行替换

JEMALLOC_EXPORT void (*__free_hook)(void *ptr) = je_free;
JEMALLOC_EXPORT void *(*__malloc_hook)(size_t size) = je_malloc;
JEMALLOC_EXPORT void *(*__realloc_hook)(void *ptr, size_t size) = je_realloc;

这样我们在自己的程序中使用malloc的时候就会被替换成je_malloc了;


三、mallctl的使用
#  define mallctl je_mallctl

je_mallctl(const char *name, void *oldp, size_t *oldlenp, void *newp,
size_t newlen) ;

此函数可以用来查询也可以用来设置;

1,查询:

则指定要查询的名称name,及结果返回的指针oldp,还有返回指针的长度oldlenp;

eg:

const char* j;
size_t s = sizeof(j);
mallctl("version", &j,&s,NULL,0);
std::cout<<j<<" ";

2,设置:

则指定要设置的名称name,要设置变量的地址newp,要设置变量的长度newlen

eg:

bool active = true;

mallctl("prof.active", NULL, NULL,(void*)&active, sizeof(active));



原文地址:https://www.cnblogs.com/guoliushui/p/9947990.html