Esempio n. 1
0
//slabclass_t中slab的数目是慢慢增多的。该函数的作用就是为slabclass_t申请多一个slab  
//参数id指明是slabclass数组中的那个slabclass_t 
static int do_slabs_newslab(const unsigned int id) {
    slabclass_t *p = &slabclass[id];

    //settings.slab_reassign的默认值为false,这里就采用false
    int len = settings.slab_reassign ? settings.item_size_max
        : p->size * p->perslab;//其积 <= settings.item_size_max
    char *ptr;

    //mem_malloced的值通过环境变量设置,默认为0 
    if ((mem_limit && mem_malloced + len > mem_limit && p->slabs > 0) ||
        (grow_slab_list(id) == 0) ||//增长slab_list(失败返回0)。一般都会成功,除非无法分配内存
        ((ptr = memory_allocate((size_t)len)) == 0)) {//分配len字节内存(也就是一个页)

        MEMCACHED_SLABS_SLABCLASS_ALLOCATE_FAILED(id);
        return 0;
    }

    memset(ptr, 0, (size_t)len);//清零内存块是必须的
    //将这块内存切成一个个的item,当然item的大小有id所控制
    split_slab_page_into_freelist(ptr, id);

    //将分配得到的内存页交由slab_list掌管
    p->slab_list[p->slabs++] = ptr;
    mem_malloced += len;
    MEMCACHED_SLABS_SLABCLASS_ALLOCATE(id);

    return 1;
}
/**
 * 为slabclass[id]分配一个新的slab,成功返回1,否则返回0
 * 
 * 1. 确定slab的长度len
 * 2. 分配len大小的内存(预分配的内存中划分或者调malloc()分配)
 * 3. 把所分配的内存初始化成item链表,链接到slabclass[id]的slot中
 * 4. slabclass[i]属性的更新:slabs数增1
 * 5. 已分配内存数的更新
 */
static int do_slabs_newslab(const unsigned int id) {
    slabclass_t *p = &slabclass[id]; //指向第i个slabclass
    int len = settings.slab_reassign ? settings.item_size_max //是否开启可自定slab大小,否则使用默认的大小1M
        : p->size * p->perslab;
    char *ptr;
	//grow_slab_list初始化slabclass的slab_list,而slab_list中的指针指向每个slab  
    //memory_allocate从内存池申请1M的空间  
    if ((mem_limit && mem_malloced + len > mem_limit && p->slabs > 0) ||
        (grow_slab_list(id) == 0) ||
        ((ptr = memory_allocate((size_t)len)) == 0)) {

        MEMCACHED_SLABS_SLABCLASS_ALLOCATE_FAILED(id);
        return 0;
    }

    memset(ptr, 0, (size_t)len);
	//将申请到的1M空间按照slabclass的size进行切分
    split_slab_page_into_freelist(ptr, id);

    p->slab_list[p->slabs++] = ptr;//循环分配
    mem_malloced += len;
    MEMCACHED_SLABS_SLABCLASS_ALLOCATE(id);

    return 1;
}
Esempio n. 3
0
static int do_slabs_newslab(const unsigned int id) {
    slabclass_t *p = &slabclass[id];
    slabclass_t *g = &slabclass[SLAB_GLOBAL_PAGE_POOL];
    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
         && g->slabs == 0)) {
        mem_limit_reached = true;
        MEMCACHED_SLABS_SLABCLASS_ALLOCATE_FAILED(id);
        return 0;
    }

    if ((grow_slab_list(id) == 0) ||
        (((ptr = get_page_from_global_pool()) == NULL) &&
        ((ptr = memory_allocate((size_t)len)) == 0))) {

        MEMCACHED_SLABS_SLABCLASS_ALLOCATE_FAILED(id);
        return 0;
    }

    memset(ptr, 0, (size_t)len);
    split_slab_page_into_freelist(ptr, id);

    p->slab_list[p->slabs++] = ptr;
    MEMCACHED_SLABS_SLABCLASS_ALLOCATE(id);

    return 1;
}
Esempio n. 4
0
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;

    DBG_INFO(DBG_ASSOC_HOPSCOTCH, "%s:%d: mem_limit = %u, len = %u\n",
		__func__, __LINE__, (unsigned int)mem_limit, (unsigned int)len);
    DBG_INFO(DBG_ASSOC_HOPSCOTCH, "%s:%d: p->slabs = %u\n", __func__, __LINE__, p->slabs);
    if ((mem_limit && mem_malloced + len > mem_limit && p->slabs > 0) ||
	(grow_slab_list(id) == 0) ||
	((ptr = memory_allocate((size_t)len)) == 0)) {
        mem_limit_reached = true;
        MEMCACHED_SLABS_SLABCLASS_ALLOCATE_FAILED(id);
	DBG_INFO(DBG_ASSOC_HOPSCOTCH, "%s:%d: mem_limit = %u, mem_malloced = %u, len = %d\n", __func__, __LINE__,
		(unsigned int)mem_limit, (unsigned int)mem_malloced, len);
	DBG_INFO(DBG_ASSOC_HOPSCOTCH, "%s:%d: returning 0\n", __func__, __LINE__);
        return 0;
    }

    memset(ptr, 0, (size_t)len);
	// TODO: Should this be commented?
    split_slab_page_into_freelist(ptr, id);

    p->slab_list[p->slabs++] = ptr;
#ifdef HOPSCOTCH_CLOCK
	p->clock_max = p->slabs * p->perslab;
#endif
    mem_malloced += len;
    MEMCACHED_SLABS_SLABCLASS_ALLOCATE(id);

    return 1;
}
Esempio n. 5
0
static void slab_rebalance_finish(void) {
    slabclass_t *s_cls;
    slabclass_t *d_cls;

    pthread_mutex_lock(&cache_lock);
    pthread_mutex_lock(&slabs_lock);

    s_cls = &slabclass[slab_rebal.s_clsid];
    d_cls   = &slabclass[slab_rebal.d_clsid];

    /* At this point the stolen slab is completely clear */
    //相当于把指针赋NULL值
    s_cls->slab_list[s_cls->killing - 1] =
        s_cls->slab_list[s_cls->slabs - 1];
    s_cls->slabs--;//源slab class的内存页数减一 
    s_cls->killing = 0;
    
    //内存页所有字节清零,这个也很重要的 
    memset(slab_rebal.slab_start, 0, (size_t)settings.item_size_max);

    //将slab_rebal.slab_start指向的一个页内存馈赠给目标slab class  
    //slab_rebal.slab_start指向的页是从源slab class中得到的。
    d_cls->slab_list[d_cls->slabs++] = slab_rebal.slab_start;

    //按照目标slab class的item尺寸进行划分这个页,并且将这个页的  
    //内存并入到目标slab class的空闲item队列中  
    split_slab_page_into_freelist(slab_rebal.slab_start,
        slab_rebal.d_clsid);

    //清零
    slab_rebal.done       = 0;
    slab_rebal.s_clsid    = 0;
    slab_rebal.d_clsid    = 0;
    slab_rebal.slab_start = NULL;
    slab_rebal.slab_end   = NULL;
    slab_rebal.slab_pos   = NULL;

    slab_rebalance_signal = 0;//rebalance线程完成工作后,再次进入休眠状态

    pthread_mutex_unlock(&slabs_lock);
    pthread_mutex_unlock(&cache_lock);

    STATS_LOCK();
    stats.slab_reassign_running = false;
    stats.slabs_moved++;
    STATS_UNLOCK();

    if (settings.verbose > 1) {
        fprintf(stderr, "finished a slab move\n");
    }
}
Esempio n. 6
0
static void slab_rebalance_finish(void) {
    slabclass_t *s_cls;
    slabclass_t *d_cls;

    pthread_mutex_lock(&cache_lock);
    pthread_mutex_lock(&slabs_lock);

    s_cls = &slabclass[slab_rebal.s_clsid];
    d_cls   = &slabclass[slab_rebal.d_clsid];

    /* At this point the stolen slab is completely clear */
    s_cls->slab_list[s_cls->killing - 1] =
        s_cls->slab_list[s_cls->slabs - 1];
    s_cls->slabs--;
    s_cls->killing = 0;

    memset(slab_rebal.slab_start, 0, (size_t)settings.item_size_max);

    d_cls->slab_list[d_cls->slabs++] = slab_rebal.slab_start;
    split_slab_page_into_freelist(slab_rebal.slab_start,
                                  slab_rebal.d_clsid);

    slab_rebal.done       = 0;
    slab_rebal.s_clsid    = 0;
    slab_rebal.d_clsid    = 0;
    slab_rebal.slab_start = NULL;
    slab_rebal.slab_end   = NULL;
    slab_rebal.slab_pos   = NULL;

    slab_rebalance_signal = 0;

    pthread_mutex_unlock(&slabs_lock);
    pthread_mutex_unlock(&cache_lock);

    STATS_LOCK();
    stats.slab_reassign_running = false;
    stats.slabs_moved++;
    STATS_UNLOCK();

    if (settings.verbose > 1) {
        fprintf(stderr, "finished a slab move\n");
    }
}
Esempio n. 7
0
int Slab::do_slabs_newslab(unsigned int id) {
    slabclass& p = mem_base[id];
    int len = p.size * p.perslab;
    char* ptr;

    //异常情况
    //内存限制不为0,申请大小总计已超过限制,并且已经申请了一些slab数
    if ((mem_limit && mem_malloced+len > mem_limit && p.slabs > 0) ||
           (grow_slab_list(id) == 0)  ||
            ((ptr = memory_allocate((size_t)len)) == 0)) {
        return 0;
    }
    
    memset(ptr, 0, (size_t)len);
    //把内存分解为chunk
    split_slab_page_into_freelist(ptr, id);
    p.slab_list[p.slabs++] = ptr;
    mem_malloced += len;
    
    return 1;
}
Esempio n. 8
0
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) ||
            (grow_slab_list(id) == 0) ||
            ((ptr = memory_allocate((size_t)len)) == 0)) {

        MEMCACHED_SLABS_SLABCLASS_ALLOCATE_FAILED(id);
        return 0;
    }

    memset(ptr, 0, (size_t)len);
    split_slab_page_into_freelist(ptr, id);

    p->slab_list[p->slabs++] = ptr;
    mem_malloced += len;
    MEMCACHED_SLABS_SLABCLASS_ALLOCATE(id);

    return 1;
}
Esempio n. 9
0
static void slab_rebalance_finish(void) {
    slabclass_t *s_cls;
    slabclass_t *d_cls;
    int x;
    uint32_t rescues;
    uint32_t evictions_nomem;
    uint32_t inline_reclaim;

    pthread_mutex_lock(&slabs_lock);

    s_cls = &slabclass[slab_rebal.s_clsid];
    d_cls = &slabclass[slab_rebal.d_clsid];

#ifdef DEBUG_SLAB_MOVER
    /* If the algorithm is broken, live items can sneak in. */
    slab_rebal.slab_pos = slab_rebal.slab_start;
    while (1) {
        item *it = slab_rebal.slab_pos;
        assert(it->it_flags == (ITEM_SLABBED|ITEM_FETCHED));
        assert(memcmp(ITEM_key(it), "deadbeef", 8) == 0);
        it->it_flags = ITEM_SLABBED|ITEM_FETCHED;
        slab_rebal.slab_pos = (char *)slab_rebal.slab_pos + s_cls->size;
        if (slab_rebal.slab_pos >= slab_rebal.slab_end)
            break;
    }
#endif

    /* At this point the stolen slab is completely clear.
     * We always kill the "first"/"oldest" slab page in the slab_list, so
     * shuffle the page list backwards and decrement.
     */
    s_cls->slabs--;
    for (x = 0; x < s_cls->slabs; x++) {
        s_cls->slab_list[x] = s_cls->slab_list[x+1];
    }

    d_cls->slab_list[d_cls->slabs++] = slab_rebal.slab_start;
    /* Don't need to split the page into chunks if we're just storing it */
    if (slab_rebal.d_clsid > SLAB_GLOBAL_PAGE_POOL) {
        memset(slab_rebal.slab_start, 0, (size_t)settings.item_size_max);
        split_slab_page_into_freelist(slab_rebal.slab_start,
            slab_rebal.d_clsid);
    } else if (slab_rebal.d_clsid == SLAB_GLOBAL_PAGE_POOL) {
        /* mem_malloc'ed might be higher than mem_limit. */
        memory_release();
    }

    slab_rebal.done       = 0;
    slab_rebal.s_clsid    = 0;
    slab_rebal.d_clsid    = 0;
    slab_rebal.slab_start = NULL;
    slab_rebal.slab_end   = NULL;
    slab_rebal.slab_pos   = NULL;
    evictions_nomem    = slab_rebal.evictions_nomem;
    inline_reclaim = slab_rebal.inline_reclaim;
    rescues   = slab_rebal.rescues;
    slab_rebal.evictions_nomem    = 0;
    slab_rebal.inline_reclaim = 0;
    slab_rebal.rescues  = 0;

    slab_rebalance_signal = 0;

    pthread_mutex_unlock(&slabs_lock);

    STATS_LOCK();
    stats.slabs_moved++;
    stats.slab_reassign_rescues += rescues;
    stats.slab_reassign_evictions_nomem += evictions_nomem;
    stats.slab_reassign_inline_reclaim += inline_reclaim;
    stats_state.slab_reassign_running = false;
    STATS_UNLOCK();

    if (settings.verbose > 1) {
        fprintf(stderr, "finished a slab move\n");
    }
}