zoukankan      html  css  js  c++  java
  • jemalloc源码结构分析(一):内存申请处理过程

    一、5种malloc方法

    1)tcache_alloc_small

    2)arena_malloc_small

    3)tcache_alloc_large

    4)arena_malloc_large

    5)huge_malloc

    //written in jemalloc_internal.h file
    imalloct(size_t size, bool try_tcache, arena_t *arena)
    {
            assert(size != 0);
    
            if (size <= arena_maxclass)
                    return (arena_malloc(arena, size, false, try_tcache));
            else
                    return (huge_malloc(size, false, huge_dss_prec_get(arena)));
    }
    
    JEMALLOC_ALWAYS_INLINE void *
    imalloc(size_t size)
    {
    
            return (imalloct(size, true, NULL));
    }
    //written in arena.h
    JEMALLOC_ALWAYS_INLINE void *
    arena_malloc(arena_t *arena, size_t size, bool zero, bool try_tcache)
    {
            tcache_t *tcache;
    
            assert(size != 0);
            assert(size <= arena_maxclass);
    
            if (size <= SMALL_MAXCLASS) {
                    if (try_tcache && (tcache = tcache_get(true)) != NULL)
                            return (tcache_alloc_small(tcache, size, zero));
                    else {
                            return (arena_malloc_small(choose_arena(arena), size,
                                zero));
                    }
            } else {
                    /*
                     * Initialize tcache after checking size in order to avoid
                     * infinite recursion during tcache initialization.
                     */
                    if (try_tcache && size <= tcache_maxclass && (tcache =
                        tcache_get(true)) != NULL)
                            return (tcache_alloc_large(tcache, size, zero));
                    else {
                            return (arena_malloc_large(choose_arena(arena), size,
                                zero));
                    }
            }
    }

     二、malloc时选择arena的机制

    1)先用arenas_tsd_get获得线程绑定变量arena;

    2)如果1)获得值为null,则扫描arenas数组,找到threads number为0或者最小的未卸载的arena;

    3)如果2)中扫描发现存在null插槽,则需要调用arenas_extend进行初始化null插槽;

    4)调用arenas_tsd_set设置线程绑定比变量arena。

    //详细见jemalloc.c中函数
    arena_t *choose_arena_hard(void)

    三、arenas_extend处理过程 

    在choose_arena处理过程中,找到一个null空arena后,需要对该arena做初始化,即调用arenas_extend函数,它的处理过程如下:

    1)base_alloc arena_t对象;

    2)arena_new arena_t对象;

    arena_t *arenas_extend(unsigned ind)
    {
            arena_t *ret;
    
            ret = (arena_t *)base_alloc(sizeof(arena_t));
            if (ret != NULL && arena_new(ret, ind) == false) {
                    arenas[ind] = ret;
                    return (ret);
            }
            /* Only reached if there is an OOM error. */
    
            /*
             * OOM here is quite inconvenient to propagate, since dealing with it
             * would require a check for failure in the fast path.  Instead, punt
             * by using arenas[0].  In practice, this is an extremely unlikely
             * failure.
             */
            malloc_write("<jemalloc>: Error initializing arena
    ");
            if (opt_abort)
                    abort();
    
            return (arenas[0]);
    }

    四、base_alloc处理过程

    1)数据对齐CACHELINE_CEILING,即64位对齐(8字节);

    2)调用base_pages_alloc申请足够内存,从而调用chunk_alloc申请chunk对象;

    3)chunk_alloc过程:如果采用dss优先的申请方式,则尝试sbrk这种方式申请,再尝试mmap这种方式;反之,则反序。 

    chunk_alloc(size_t size, size_t alignment, bool base, bool *zero,
        dss_prec_t dss_prec)
    {
            void *ret;
    
            assert(size != 0);
            assert((size & chunksize_mask) == 0);
            assert(alignment != 0);
            assert((alignment & chunksize_mask) == 0);
    
            /* "primary" dss. */
            if (config_dss && dss_prec == dss_prec_primary) {
                    if ((ret = chunk_recycle(&chunks_szad_dss, &chunks_ad_dss, size,
                        alignment, base, zero)) != NULL)
                            goto label_return;
                    if ((ret = chunk_alloc_dss(size, alignment, zero)) != NULL)
                            goto label_return;
            }
            /* mmap. */
            if ((ret = chunk_recycle(&chunks_szad_mmap, &chunks_ad_mmap, size,
                alignment, base, zero)) != NULL)
                    goto label_return;
            if ((ret = chunk_alloc_mmap(size, alignment, zero)) != NULL)
                    goto label_return;
            /* "secondary" dss. */
            if (config_dss && dss_prec == dss_prec_secondary) {
                    if ((ret = chunk_recycle(&chunks_szad_dss, &chunks_ad_dss, size,
                        alignment, base, zero)) != NULL)
                            goto label_return;
                    if ((ret = chunk_alloc_dss(size, alignment, zero)) != NULL)
                            goto label_return;
            }
            /* All strategies for allocation failed. */
            ret = NULL;
    label_return:
            if (ret != NULL) {
                    if (config_ivsalloc && base == false) {
                            if (rtree_set(chunks_rtree, (uintptr_t)ret, 1)) {
                                    chunk_dealloc(ret, size, true);
                                    return (NULL);
                            }
                    }
                    if (config_stats || config_prof) {
                            bool gdump;
                            malloc_mutex_lock(&chunks_mtx);
                            if (config_stats)
                                    stats_chunks.nchunks += (size / chunksize);
                            stats_chunks.curchunks += (size / chunksize);
                            if (stats_chunks.curchunks > stats_chunks.highchunks) {
                                    stats_chunks.highchunks =
                                        stats_chunks.curchunks;
                                    if (config_prof)
                                            gdump = true;
                            } else if (config_prof)
                                    gdump = false;
                            malloc_mutex_unlock(&chunks_mtx);
                            if (config_prof && opt_prof && opt_prof_gdump && gdump)
                                    prof_gdump();
                    }
                    if (config_valgrind)
                            VALGRIND_MAKE_MEM_UNDEFINED(ret, size);
            }
                                                                                                                                        1
           return ret;
    }
  • 相关阅读:
    nginx启动时指定配置文件
    idea修改忽视文件产生得bug
    SpringBoot整合RabbitMQ出现org.springframework.amqp.AmqpException: No method found for class
    解决git速度太慢的问题,亲测有效
    HttpRequestException encountered解决方法
    mybatis大于等于小于等于的写法
    Could not initialize class sun.awt.X11GraphicsEnvironment异常处理
    CF377C Captains Mode
    AT1251 たのしいたのしい家庭菜園
    CF1057C Tanya and Colored Candies
  • 原文地址:https://www.cnblogs.com/feika/p/3675711.html
Copyright © 2011-2022 走看看