切换tbox全局内存分配器

2016-08-04 ruki 更多博文 » 博客 » GitHub »

tbox 内存池 分配器

原文链接 https://waruqi.github.io/2016/08/04/switch-global-memory.cn/
注:以下为加速网络访问所做的原文缓存,经过重新格式化,可能存在格式方面的问题,或偶有遗漏信息,请以原文为准。


tbox的默认内存分配,是完全基于自己的内存池架构,支持内存的快速分配,和对碎片的优化,并且支持各种内存泄露、溢出检测。

如果不想用tbox内置的默认内存分配管理,也可以灵活切换到其他分配模式,因为tbox现在已经完全支持allocator架构, 只要在init阶段传入不同的分配器模型,就能快速切换分配模式,例如:

    /* 采用默认的tbox内存管理,启用内存池维护、碎片优化、内存泄露溢出检测等所有特性
     * 相当于使用了:tb_default_allocator(tb_null, 0)
     */
    tb_init(tb_null, tb_null);

    /* 采用默认的tbox内存管理,启用内存池维护、碎片优化、内存泄露溢出检测等所有特性
     * 并且完全使用外部传入的一整块buffer上进行维护,不再使用其他native内存
     */
    tb_init(tb_null, tb_default_allocator((tb_byte_t*)malloc(300 * 1024 * 1024), 300 * 1024 * 1024));

    /* 采用一整块静态buffer上进行维护,启用内存泄露溢出检测等所有特性
     * 这个跟tb_default_allocator的区别就是,这个allocator比较轻量,内部的数据结构简单,占用内存少,适合低资源环境
     * 但是这个allocator不支持碎片优化,容易产生碎片
     */
    tb_init(tb_null, tb_static_allocator((tb_byte_t*)malloc(300 * 1024 * 1024), 300 * 1024 * 1024));

    // 完全使用系统native内存分配,内部不做任何处理和数据维护,所有特性依赖系统环境,tbox不再支持内存池和内存检测等特性
    tb_init(tb_null, tb_native_allocator());

如果觉得这些分配器还是不够用,可以自定义自己的内存分配器,让tbox去使用,自定义的方式也很简单,这里拿tb_native_allocator的实现代码为例:

static tb_pointer_t tb_native_allocator_malloc(tb_allocator_ref_t allocator, tb_size_t size __tb_debug_decl__)
{
    // trace
    tb_trace_d("malloc(%lu) at %s(): %lu, %s", size, func_, line_, file_);

    // malloc it
    return malloc(size);
}
static tb_pointer_t tb_native_allocator_ralloc(tb_allocator_ref_t allocator, tb_pointer_t data, tb_size_t size __tb_debug_decl__)
{
    // trace
    tb_trace_d("realloc(%p, %lu) at %s(): %lu, %s", data, size, func_, line_, file_);

    // realloc it
    return realloc(data, size);
}
static tb_bool_t tb_native_allocator_free(tb_allocator_ref_t allocator, tb_pointer_t data __tb_debug_decl__)
{
    // trace    
    tb_trace_d("free(%p) at %s(): %lu, %s", data, func_, line_, file_);

    // free it
    return free(data);
}


// 初始化一个native分配器
tb_allocator_t allocator    = {0};
allocator.type              = TB_ALLOCATOR_NATIVE;
allocator.malloc            = tb_native_allocator_malloc;
allocator.ralloc            = tb_native_allocator_ralloc;
allocator.free              = tb_native_allocator_free;

是不是很简单,需要注意的是,上面的__tb_debug_decl__宏里面声明了一些debug信息,例如_file, _func, _line等内存分配时候记录的信息, 你可以在debug的时候打印出来,做调试,也可以利用这些信息自己去处理一些高级的内存检测操作,但是这些在release下,是不可获取的

所以处理的时候,需要使用__tb_debug__宏,来分别处理。。

将allocator传入tb_init接口后,之后 tb_malloc/tb_ralloc/tb_free/... 等所有tbox内存分配接口都会切到新的allocator上进行分配。。

当然如果想直接从一个特定的allocator上进行分配,还可以直接调用allocator的分配接口来实现:

tb_allocator_malloc(allocator, 10);
tb_allocator_ralloc(allocator, data, 100);
tb_allocator_free(allocator, data);

等等。