zoukankan      html  css  js  c++  java
  • memcached源码阅读笔记二

    这一次是关于内存使用的分析

    int main (int argc, char **argv) {
        //.......................
        //.......................
        //.......................
        slabs_init(settings.maxbytes, settings.factor, preallocate);
        
        //.......................
        //.......................
        //.......................
        
    }
    
    
    void slabs_init(const size_t limit, const double factor, const bool prealloc) {
        int i = POWER_SMALLEST - 1;
        unsigned int size = sizeof(item) + settings.chunk_size;
        
        mem_limit = limit;
        
        // 一个记录slab数据的结构体
        memset(slabclass, 0, sizeof(slabclass));
        
        while (++i < POWER_LARGEST && size <= settings.item_size_max / factor) {
            /* Make sure items are always n-byte aligned */
            // 取整
            if (size % CHUNK_ALIGN_BYTES)
                size += CHUNK_ALIGN_BYTES - (size % CHUNK_ALIGN_BYTES);
            
            // 一个slab大小为1MB
            // 定出一个item的大小
            slabclass[i].size = size;
            // 定出每一个slab有多少个item数量
            slabclass[i].perslab = settings.item_size_max / slabclass[i].size;
            // 下一种slab的item大小为当前的的factor倍,一般为1.25
            size *= factor;
        }
        
        // 最后一种slab。每一个item为item_size_max,一般为1MB,每个slab只有一个item
        power_largest = i;
        slabclass[power_largest].size = settings.item_size_max;
        slabclass[power_largest].perslab = 1;
    
    }
    
    
    
    // 分配一个新的slab出来
    static int do_slabs_newslab(const unsigned int id) {
        slabclass_t *p = &slabclass[id];
        int len = settings.slab_reassign ? settings.item_size_max
        : p->size * p->perslab;
        char *ptr;
        
        if (
            (mem_limit && mem_malloced + len > mem_limit && p->slabs > 0) ||
            // 如果没有超出mem_limit
            
            (grow_slab_list(id) == 0) ||
            // 判断这种slab,是否需要变大list_size
            // 并且grow_slab_list返回1
            
            ((ptr = memory_allocate((size_t)len)) == 0)
            //
            // 则调用memory_allocate分配一个slab的内存
            
            ) {
            
            return 0;
        }
        
        memset(ptr, 0, (size_t)len);
        split_slab_page_into_freelist(ptr, id);
        // 将新分配的内存放到slots中,也就是空闲列表中
        
        // add this new slab in the array of slab list
        p->slab_list[p->slabs++] = ptr;
        mem_malloced += len;
        
        return 1;
    }
    
    // slab的数组增长
    static int grow_slab_list (const unsigned int id) {
        slabclass_t *p = &slabclass[id];
        if (p->slabs == p->list_size) {
            size_t new_size =  (p->list_size != 0) ? p->list_size * 2 : 16;
            // 初始大小16,然后以后不够用了,增大一倍
            void *new_list = realloc(p->slab_list, new_size * sizeof(void *));
            if (new_list == 0) return 0;
            p->list_size = new_size;
            p->slab_list = new_list;
        }
        return 1;
    }
    
    
    
    // 我需要一个item,分一个给我吧
    static void *do_slabs_alloc(const size_t size, unsigned int id) {
        slabclass_t *p;
        void *ret = NULL;
        item *it = NULL;
        
        
        p = &slabclass[id];
        assert(p->sl_curr == 0 || ((item *)p->slots)->slabs_clsid == 0);
        //要么sl_curr空闲列表为空,不为空时slots指向的头一个item的cslid值必须为0
        
        //如果空闲列表不为空,直接从空闲列表中分配
        //如果空闲列表为空,则do_slabs_newslab来增加该slabclass的slabs
        if (! (p->sl_curr != 0 || do_slabs_newslab(id) != 0)) {
            /* We don't have more memory available */
            ret = NULL;
        } else if (p->sl_curr != 0) {
            /* return off our freelist */
            it = (item *)p->slots;
            p->slots = it->next;
            if (it->next) it->next->prev = 0;
            p->sl_curr--;
            ret = (void *)it;
        }
        
        if (ret) {
            p->requested += size;
            MEMCACHED_SLABS_ALLOCATE(size, id, p->size, ret);
        } else {
            MEMCACHED_SLABS_ALLOCATE_FAILED(size, id);
        }
        
        return ret;
    }
    
    
    
    // free并不是将内存返回给系统,而是将不使用的item占用的空间重新放到相对应的slabclass的slots中
    static void do_slabs_free(void *ptr, const size_t size, unsigned int id) {
        slabclass_t *p;
        item *it;
        
        p = &slabclass[id];
        
        it = (item *)ptr;
        it->it_flags |= ITEM_SLABBED;
        it->prev = 0;
        it->next = p->slots;
        if (it->next) it->next->prev = it;
        p->slots = it;
        // 把这个item放到slot中。上面是一连串双向链表的操作
        
        p->sl_curr++;
        p->requested -= size;
        return;
    }
  • 相关阅读:
    swift3.0更新内容
    Core Animation
    UIBezierPath精讲
    iOS-Core-Animation-Advanced-Techniques(原文来自cocoachina)
    iOS上图形和动画处理
    使用GCD(转自唐巧的技术博客)
    UITableView的cell的分割线位置
    swift深入理解闭包
    Swift控制器加载xib Swift Controller'view load from xib
    -[UIWindow viewForFirstBaselineLayout]: unrecognized selector sent to instance
  • 原文地址:https://www.cnblogs.com/yemsheng/p/3339044.html
Copyright © 2011-2022 走看看