目前市面上有不少分析Jemalloc老版本的博文,但最新版本5.3.0却少之又少。而且5.3.0的架构与5之前的版本有较大不同,本着“与时俱进”、“由浅入深”的宗旨,我将逐步分析最新release版本Jemalloc5.3.0的实现。
另外,单讲实现代码是极其枯燥的,我将尽量每个原理知识点都用一个简简单单的小程序引出,这样便于大家测试和上手调试。另外,我还会用GDB打印数据结构、变量的值,方便理解当时的状态或算法。
jemalloc留了几个口子来配置参数,从而提高性能,我了解到的有以下四种:
- 编译选项
- 配置文件(链接) /etc/malloc.conf
- 环境变量 MALLOC_CONF
- 用户程序中调用mallctl动态配置
下面我详细介绍这四种配置方式,因为前面介绍了tcache,它默认是enabled的,本节我将分别用这几种配置方式disable tcache。
欲了解其它设置项请参考https://jemalloc.net/jemalloc.3.html
前三种方式,都是通过函数obtain_malloc_conf来拿到配置字符串的。
1. 编译选项
还记得编译那一篇中我们用了一个--enable-debug选项吗?
./configure --enable-debug
configure脚本还支持很多选项,都列在了INSTALL.md中,其中有一个--with-malloc-conf可以用来配置参数。
cd jemalloc-5.3.0
./configure --with-malloc-conf="tcache:false"
make
sudo make install
像这样就会关闭tcache功能。
用户所给出的"tcache:false"会作为全局变量config_malloc_conf的初始值。
config_malloc_conf中tcache的值false会赋给全局变量opt_tcache以供后来使用
用户的输入已传递到opt_tcache:
之后调用如下函数在tsd中设置tcache_enabled=flase(实际为设置tsd->cant_access_tsd_items_directly_use_a_getter_or_setter_tcache_enabled=false) 。
call stack:
总结一下,数据流向为:./configure --with-malloc-conf="tcache:false" => config_malloc_conf => opt_tcache => tsd
2. 配置文件(链接) /etc/malloc.conf
ln -sf 'tcache:false' /etc/malloc.conf
执行 以上命令,/etc/malloc.conf的链接内容就变成了tcache:false, 注意:不是指向文件。false会先赋给全局变量opt_tcache,与第一种方式一样之后传给tsd。
3. 环境变量 MALLOC_CONF
环境变量可以设置全局的也可以设置临时的,临时的如下:
MALLOC_CONF="tcache:false" ./a.out
获得环境变量值的代码如下:
之后也是把值赋值给opt_tcache, 与第一种方式一样之后传给tsd。
4. 用户程序中调用mallctl动态配置
前面的办法对一个程序来讲是静态的,一旦设定,程序中不能更改。与之相反,mallctl函数允许编程者在运行中动态改变参数值。看下面的例子。
$ cat disable_tcache.c
#include <jemalloc/jemalloc.h>
#include <stdbool.h>
#include <stdio.h>void disable_tcache() {bool tcache_enabled = false;size_t sz = sizeof(tcache_enabled);if (mallctl("thread.tcache.enabled", NULL, NULL, &tcache_enabled, sz) != 0) {perror("Error disabling tcache");}
}int main() {void *ptr1 = malloc(100); //默认tcache enableddisable_tcache(); //关闭tcachevoid *ptr2 = malloc(200); //tcache disabled.return 0;
}
实现代码比较直接,都是mallctl调用je_ctl_byname处理不同的设置项的,本例的设置项为"thread.tcache.enabled"。
x. 运行后打印各个参数设置值
stats_print:true 会打印各种统计信息,不过也会一开始就打印各个参数设置的值,而且贴心的分成了两类:编译时设置项,和运行时设置项。
$ MALLOC_CONF=stats_print:true ./a.out
___ Begin jemalloc statistics ___
Version: "5.3.0-0-g54eaed1d8b56b1aa528be3bdd1877e59c56fa90c"
Build-time option settingsconfig.cache_oblivious: trueconfig.debug: trueconfig.fill: trueconfig.lazy_lock: falseconfig.malloc_conf: ""config.opt_safety_checks: trueconfig.prof: falseconfig.prof_libgcc: falseconfig.prof_libunwind: falseconfig.stats: trueconfig.utrace: falseconfig.xmalloc: false
Run-time option settingsopt.abort: trueopt.abort_conf: trueopt.cache_oblivious: trueopt.confirm_conf: falseopt.retain: trueopt.dss: "secondary"opt.narenas: 1opt.percpu_arena: "disabled"opt.oversize_threshold: 8388608opt.hpa: falseopt.hpa_slab_max_alloc: 65536opt.hpa_hugification_threshold: 1992294opt.hpa_hugify_delay_ms: 10000opt.hpa_min_purge_interval_ms: 5000opt.hpa_dirty_mult: "0.25"opt.hpa_sec_nshards: 4opt.hpa_sec_max_alloc: 32768opt.hpa_sec_max_bytes: 262144opt.hpa_sec_bytes_after_flush: 131072opt.hpa_sec_batch_fill_extra: 0opt.metadata_thp: "disabled"opt.mutex_max_spin: 600opt.background_thread: false (background_thread: false)opt.dirty_decay_ms: 10000 (arenas.dirty_decay_ms: 10000)opt.muzzy_decay_ms: 0 (arenas.muzzy_decay_ms: 0)opt.lg_extent_max_active_fit: 6opt.junk: "true"opt.zero: falseopt.experimental_infallible_new: falseopt.tcache: trueopt.tcache_max: 32768opt.tcache_nslots_small_min: 20opt.tcache_nslots_small_max: 200opt.tcache_nslots_large: 20opt.lg_tcache_nslots_mul: 1opt.tcache_gc_incr_bytes: 65536opt.tcache_gc_delay_bytes: 0opt.lg_tcache_flush_small_div: 1opt.lg_tcache_flush_large_div: 1opt.thp: "default"opt.stats_print: trueopt.stats_print_opts: ""opt.stats_print: trueopt.stats_print_opts: ""opt.stats_interval: -1opt.stats_interval_opts: ""opt.zero_realloc: "free"
Arenas: 2
Quantum size: 16
Page size: 4096
Maximum thread-cached size class: 32768
Number of bin size classes: 36
Number of thread-cache bin size classes: 41
Number of large size classes: 196
Allocated: 113792, active: 126976, metadata: 2425984 (n_thp 0), resident: 3006464, mapped: 6893568, retained: 1495040