Jemalloc free的过程

来源:互联网 发布:广州淘宝美工学校 编辑:程序博客网 时间:2024/06/01 09:20
redis第一次调用free函数
(gdb) bt
#0  je_free (ptr=0x7ffff661b000) at src/jemalloc.c:1837
#1  0x000000000043194e in zfree (ptr=0x7ffff661b000) at zmalloc.c:204
#2  0x0000000000423ea7 in dictRehash (d=0x7ffff6618060, n=-1) at dict.c:279
#3  0x0000000000423fc6 in _dictRehashStep (d=0x7ffff6618060) at dict.c:318
#4  0x0000000000424077 in dictAddRaw (d=0x7ffff6618060, key=0x7ffff6616081) at dict.c:352
#5  0x0000000000423fef in dictAdd (d=0x7ffff6618060, key=0x7ffff6616081, val=0x917930 <redisCommandTable+560>) at dict.c:324
#6  0x00000000004298ab in populateCommandTable () at server.c:2035
#7  0x0000000000428734 in initServerConfig () at server.c:1587
#8  0x000000000042e55a in main (argc=1, argv=0x7fffffffe3f8) at server.c:3984

je_free
    tsd_t *tsd = tsd_fetch();得到当前线程的tsd
    ifree(tsd, ptr, tcache_get(tsd, false));
        tcache = tsd_tcache_get(tsd);
            得到tsd的tcache字段
        usize = isalloc(ptr, config_prof);
            arena_salloc(ptr, demote)
                chunk = (arena_chunk_t *)CHUNK_ADDR2BASE(ptr);
                    (arena_chunk_t *) 0x7ffff6600000
                pageind = ((uintptr_t)ptr - (uintptr_t)chunk) >> LG_PAGE;
                    (0x7ffff661b000 - 0x7ffff6600000) >> 27
                binind = arena_mapbits_binind_get(chunk, pageind);
                    &chunk->map_bits[pageind-map_bias]
                    *mapbitsp = 0x61
                    binind = (mapbits & CHUNK_MAP_BININD_MASK) >> CHUNK_MAP_BININD_SHIFT;
                        (0x61 & (0xff << 5)) >> 5 = 3,后五位清0,取6-12位
                    ret = index2size(binind);
                        64
                    释放64字节的大小
        *tsd_thread_deallocatedp_get(tsd) += usize;
            tsd的thread_deallocated += 64
        iqalloc(tsd, ptr, tcache);
            idalloctm(tsd, ptr, tcache, false);
                arena_dalloc(tsd, ptr, tcache);
                    chunk = (arena_chunk_t *)CHUNK_ADDR2BASE(ptr);
                    pageind = ((uintptr_t)ptr - (uintptr_t)chunk) >> LG_PAGE;
                    mapbits = arena_mapbits_get(chunk, pageind);
                        0x61
                    szind_t binind = arena_ptr_small_binind_get(ptr, mapbits);
                        binind = (mapbits & CHUNK_MAP_BININD_MASK) >> CHUNK_MAP_BININD_SHIFT;
                            3
                    先释放到cache中
                    tcache_dalloc_small(tsd, tcache, ptr, binind);
                        tbin = &tcache->tbins[binind];
                        tbin_info = &tcache_bin_info[binind];
                        tbin->avail[tbin->ncached] = ptr;
                        tbin->ncached++;
                        tcache_event(tsd, tcache);

                        
je_arena_dalloc_small,je_arena_dalloc_large在redis启动时没有执行
je_arena_dalloc_small最终调用arena_dalloc_bin_locked_impl
je_arena_dalloc_large最终调用arena_dalloc_large_locked_impl
最终都会调用arena_run_dalloc,在合适的时机,会调用
arena_chunk_dalloc(arena, chunk);
arena_maybe_purge(arena);

下面是手动跟踪代码得到的释放过程
arena_maybe_purge/arena_purge_all
arena_purge
arena_unstash_purged
chunk_dalloc_arena
const chunk_hooks_t    chunk_hooks_default.dalloc
chunk_dalloc_default
chunk_dalloc_mmap
pages_unmap
munmap

下面这个堆栈是redis某个timer线程定时会调用的
(gdb) bt
#0  arena_dalloc_bin_locked_impl (arena=0x7ffff7000180, chunk=0x7ffff6600000, ptr=0x7ffff6621568, bitselm=0x7ffff6600108, junked=true)
    at src/arena.c:2483
#1  0x0000000000608856 in je_arena_dalloc_bin_junked_locked (arena=0x7ffff7000180, chunk=0x7ffff6600000, ptr=0x7ffff6621568,
    bitselm=0x7ffff6600108) at src/arena.c:2511
#2  0x00000000006a4166 in je_tcache_bin_flush_small (tsd=0x7ffff7fd8730, tcache=0x7ffff660d000, tbin=0x7ffff660d060, binind=2, rem=9)
    at src/tcache.c:133
#3  0x00000000006a3bc3 in je_tcache_event_hard (tsd=0x7ffff7fd8730, tcache=0x7ffff660d000) at src/tcache.c:44
#4  0x00000000004e7c6e in je_tcache_event (tcache=0x7ffff660d000, tsd=0x7ffff7fd8730) at include/jemalloc/internal/tcache.h:246
#5  je_tcache_alloc_small (zero=false, size=16, tcache=0x7ffff660d000, arena=0x7ffff7000180, tsd=0x7ffff7fd8730)
    at include/jemalloc/internal/tcache.h:306
#6  je_arena_malloc (tcache=0x7ffff660d000, zero=false, size=16, arena=0x7ffff7000180, tsd=0x7ffff7fd8730)
    at include/jemalloc/internal/arena.h:1173
#7  je_iallocztm (arena=0x0, is_metadata=false, tcache=0x7ffff660d000, zero=false, size=16, tsd=0x7ffff7fd8730)
    at include/jemalloc/internal/jemalloc_internal.h:887
#8  je_imalloc (size=16, tsd=0x7ffff7fd8730) at include/jemalloc/internal/jemalloc_internal.h:906
#9  imalloc_body (usize=0x7fffffffc7f8, tsd=0x7fffffffc7f0, size=16) at src/jemalloc.c:1412
#10 je_malloc (size=16) at src/jemalloc.c:1427
#11 0x00000000004316b3 in zmalloc (size=16) at zmalloc.c:125
#12 0x000000000043e37f in createObject (type=0, ptr=0x2354) at object.c:40
#13 0x000000000042804b in createSharedObjects () at server.c:1434
#14 0x000000000042916e in initServer () at server.c:1889
#15 0x000000000042ea65 in main (argc=1, argv=0x7fffffffe3f8) at server.c:4079

搞清楚细节,需要好好扒扒代码了

原创粉丝点击