/** * 内存初始化,预分配若干slab的内存空间 * Determines the chunk sizes and initializes the slab class descriptors * accordingly. */ void slabs_init(const size_t limit, const double factor, const bool prealloc) { int i = POWER_SMALLEST - 1; //size表示申请空间的大小,其值由配置的chunk_size和单个item的大小来指定 unsigned int size = sizeof(item) + settings.chunk_size; mem_limit = limit;//mem_limit是全局变量 //支持预分配 if (prealloc) { /* Allocate everything in a big chunk with malloc */ mem_base = malloc(mem_limit);//申请地址,mem_base指向申请的地址 if (mem_base != NULL) { mem_current = mem_base;//mem_current指向当前地址 mem_avail = mem_limit;//可用内存大小为mem_limit } else {//支持预分配失败 fprintf(stderr, "Warning: Failed to allocate requested memory in"" one large chunk.\nWill allocate in smaller chunks\n"); } } //置空slabclass数组 memset(slabclass, 0, sizeof(slabclass)); //开始分配,i<200 && 单个chunk的size<单个item最大大小/内存增长因子 while (++i < POWER_LARGEST && size <= settings.item_size_max / factor) { /* size 保证 n-byte aligned */ if (size % CHUNK_ALIGN_BYTES) size += CHUNK_ALIGN_BYTES - (size % CHUNK_ALIGN_BYTES); slabclass[i].size = size;//slab对应chunk的大小 slabclass[i].perslab = settings.item_size_max / slabclass[i].size;//slab对应的chunk的个数 size *= factor;//size下一个值为按增长因子的倍数增长 if (settings.verbose > 1) {//如果有打开调试信息,则输出调试信息 fprintf(stderr, "slab class %3d: chunk size %9u perslab %7u\n",i, slabclass[i].size, slabclass[i].perslab); } } //循环结束时,size已经增长到1M power_largest = i;//再增加一个slab slabclass[power_largest].size = settings.item_size_max;//slab的size为item_size_max slabclass[power_largest].perslab = 1;//chunk个数为1 if (settings.verbose > 1) { fprintf(stderr, "slab class %3d: chunk size %9u perslab %7u\n", i, slabclass[i].size, slabclass[i].perslab); } /* for the test suite: faking of how much we've already malloc'd */ //读取环境变量T_MEMD_INITIAL_MALLOC的值 { char *t_initial_malloc = getenv("T_MEMD_INITIAL_MALLOC"); if (t_initial_malloc) { mem_malloced = (size_t)atol(t_initial_malloc); } } if (prealloc) { //分配每个slab的内存空间,传入最大已经初始化的最大slab编号 slabs_preallocate(power_largest); } }
//内存初始化,settings.maxbytes是Memcached初始启动参数指定的内存值大小,settings.factor是内存增长因子 void slabs_init(const size_t limit, const double factor, const bool prealloc) { int i = POWER_SMALLEST - 1; // POWER_SMALLEST : slabclass数组的最小下标, 默认为1 //size表示申请空间的大小,其值由配置的chunk_size和单个item的大小来指定 unsigned int size = sizeof(item) + settings.chunk_size; mem_limit = limit;//总的内存大小 //支持预分配 if (prealloc) { /* Allocate everything in a big chunk with malloc */ mem_base = malloc(mem_limit);//申请地址,mem_base指向申请的地址 if (mem_base != NULL) { mem_current = mem_base; //mem_current指向当前地址 mem_avail = mem_limit; //可用内存大小为mem_limit } else {//支持预分配失败 fprintf(stderr, "Warning: Failed to allocate requested memory in" " one large chunk.\nWill allocate in smaller chunks\n"); } } //初始化置空slabclass 数组 memset(slabclass, 0, sizeof(slabclass)); //开始分配 i<200 && 单个chunk的size 小于等于最大item/内存增长因子的大小 while (++i < POWER_LARGEST && size <= settings.item_size_max / factor) { /* Make sure items are always n-byte aligned */ if (size % CHUNK_ALIGN_BYTES) //size执行8byte对齐 如果有余数就是没有对齐就进行差距的相加从而达到内存对齐 size += CHUNK_ALIGN_BYTES - (size % CHUNK_ALIGN_BYTES); //字节对齐 slabclass[i].size = size;//slab对应的chunk大小 slabclass[i].perslab = settings.item_size_max / slabclass[i].size; //slab对应的chunk个数 size *= factor;//size按增长因子编程下一个 if (settings.verbose > 1) { fprintf(stderr, "slab class %3d: chunk size %9u perslab %7u\n", i, slabclass[i].size, slabclass[i].perslab); } } power_largest = i; //如果增长完毕,size已经增长到1M slabclass[power_largest].size = settings.item_size_max;//再增加一个slab slab的size 为item_size_max slabclass[power_largest].perslab = 1;//chunk的个数为1 if (settings.verbose > 1) { fprintf(stderr, "slab class %3d: chunk size %9u perslab %7u\n", i, slabclass[i].size, slabclass[i].perslab); } /* for the test suite: faking of how much we've already malloc'd */ {//读取环境变量T_MEMD_INITIAL_MALLOC的值 char *t_initial_malloc = getenv("T_MEMD_INITIAL_MALLOC"); if (t_initial_malloc) { mem_malloced = (size_t)atol(t_initial_malloc); } } if (prealloc) { //分配每个slab的内存空间,传入最大已经初始化的最大slab编号 slabs_preallocate(power_largest); } }
/** * Determines the chunk sizes and initializes the slab class descriptors * accordingly. */ 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; if (prealloc) { /* Allocate everything in a big chunk with malloc */ mem_base = malloc(mem_limit); if (mem_base != NULL) { mem_current = mem_base; mem_avail = mem_limit; } else { fprintf(stderr, "Warning: Failed to allocate requested memory in" " one large chunk.\nWill allocate in smaller chunks\n"); } } 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); slabclass[i].size = size; slabclass[i].perslab = settings.item_size_max / slabclass[i].size; size *= factor; if (settings.verbose > 1) { fprintf(stderr, "slab class %3d: chunk size %9u perslab %7u\n", i, slabclass[i].size, slabclass[i].perslab); } } power_largest = i; slabclass[power_largest].size = settings.item_size_max; slabclass[power_largest].perslab = 1; if (settings.verbose > 1) { fprintf(stderr, "slab class %3d: chunk size %9u perslab %7u\n", i, slabclass[i].size, slabclass[i].perslab); } /* for the test suite: faking of how much we've already malloc'd */ { char *t_initial_malloc = getenv("T_MEMD_INITIAL_MALLOC"); if (t_initial_malloc) { mem_malloced = (size_t)atol(t_initial_malloc); } } if (prealloc) { slabs_preallocate(power_largest); } }
/* * Determines the chunk sizes and initializes the slab class descriptors * accordingly. */ void slabs_init(const size_t limit, const double factor) { int i = POWER_SMALLEST - 1; unsigned int size = sizeof(item) + settings.chunk_size; /* Factor of 2.0 means use the default memcached behavior */ if (factor == 2.0 && size < 128) size = 128; mem_limit = limit; memset(slabclass, 0, sizeof(slabclass)); while (++i < POWER_LARGEST && size <= POWER_BLOCK / 2) { /* Make sure items are always n-byte aligned */ if (size % CHUNK_ALIGN_BYTES) size += CHUNK_ALIGN_BYTES - (size % CHUNK_ALIGN_BYTES); slabclass[i].size = size; slabclass[i].perslab = POWER_BLOCK / slabclass[i].size; size *= factor; if (settings.verbose > 1) { fprintf(stderr, "slab class %3d: chunk size %6u perslab %5u\n", i, slabclass[i].size, slabclass[i].perslab); } } power_largest = i; slabclass[power_largest].size = POWER_BLOCK; slabclass[power_largest].perslab = 1; /* for the test suite: faking of how much we've already malloc'd */ { char *t_initial_malloc = getenv("T_MEMD_INITIAL_MALLOC"); if (t_initial_malloc) { mem_malloced = (size_t)atol(t_initial_malloc); } } #ifndef DONT_PREALLOC_SLABS { char *pre_alloc = getenv("T_MEMD_SLABS_ALLOC"); if (pre_alloc == NULL || atoi(pre_alloc) != 0) { slabs_preallocate(power_largest); } } #endif }
Slab::Slab(size_t limit, double factor, struct settings* mem_setting) : mem_limit(limit), mem_malloced(0) { int i = POWER_SMALLEST - 1; unsigned int size = sizeof(base_item) + mem_setting->chunk_size; slabclass temp;//only fill mem_base[0], no use mem_base.push_back(temp); while (++i < POWER_LARGEST && size <= mem_setting->item_size_max/factor) { //保证刚好字节对齐 if (size % CHUNK_ALION_BYTES) size += CHUNK_ALION_BYTES - (size % CHUNK_ALION_BYTES); slabclass temp_slab; temp_slab.size = size; temp_slab.perslab = mem_setting->item_size_max / temp_slab.size; mem_base.push_back(temp_slab); size *= factor; if (mem_setting->verbose > 1) { std::cerr << "slab class " << i << ": chunk size " << temp_slab.size << " perslab " << temp_slab.perslab << std::endl; } } power_largest = i; slabclass temp_slab; temp_slab.size = mem_setting->item_size_max; temp_slab.perslab = 1; mem_base.push_back(temp_slab); if (mem_setting->verbose > 1) { std::cerr << "slab class " << i << ": chunk size " << temp_slab.size << " perslab " << temp_slab.perslab << std::endl; } //可以关闭 slabs_preallocate(POWER_LARGEST); }
/** * Determines the chunk sizes and initializes the slab class descriptors * accordingly. */ ENGINE_ERROR_CODE slabs_init(struct default_engine *engine, const size_t limit, const double factor, const bool prealloc) { int i = POWER_SMALLEST - 1; unsigned int size = sizeof(hash_item) + (unsigned int)engine->config.chunk_size; engine->slabs.mem_limit = limit; if (prealloc) { /* Allocate everything in a big chunk with malloc */ engine->slabs.mem_base = my_allocate(engine, engine->slabs.mem_limit); if (engine->slabs.mem_base != NULL) { engine->slabs.mem_current = engine->slabs.mem_base; engine->slabs.mem_avail = engine->slabs.mem_limit; } else { return ENGINE_ENOMEM; } } memset(engine->slabs.slabclass, 0, sizeof(engine->slabs.slabclass)); while (++i < POWER_LARGEST && size <= engine->config.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); engine->slabs.slabclass[i].size = size; engine->slabs.slabclass[i].perslab = (unsigned int)engine->config.item_size_max / engine->slabs.slabclass[i].size; size = (unsigned int)(size * factor); if (engine->config.verbose > 1) { EXTENSION_LOGGER_DESCRIPTOR *logger; logger = (void*)engine->server.extension->get_extension(EXTENSION_LOGGER); logger->log(EXTENSION_LOG_INFO, NULL, "slab class %3d: chunk size %9u perslab %7u\n", i, engine->slabs.slabclass[i].size, engine->slabs.slabclass[i].perslab); } } engine->slabs.power_largest = i; engine->slabs.slabclass[engine->slabs.power_largest].size = (unsigned int)engine->config.item_size_max; engine->slabs.slabclass[engine->slabs.power_largest].perslab = 1; if (engine->config.verbose > 1) { EXTENSION_LOGGER_DESCRIPTOR *logger; logger = (void*)engine->server.extension->get_extension(EXTENSION_LOGGER); logger->log(EXTENSION_LOG_INFO, NULL, "slab class %3d: chunk size %9u perslab %7u\n", i, engine->slabs.slabclass[i].size, engine->slabs.slabclass[i].perslab); } /* for the test suite: faking of how much we've already malloc'd */ { char *t_initial_malloc = getenv("T_MEMD_INITIAL_MALLOC"); if (t_initial_malloc) { engine->slabs.mem_malloced = (size_t)atol(t_initial_malloc); } } #ifndef DONT_PREALLOC_SLABS { char *pre_alloc = getenv("T_MEMD_SLABS_ALLOC"); if (pre_alloc == NULL || atoi(pre_alloc) != 0) { slabs_preallocate(power_largest); } } #endif return ENGINE_SUCCESS; }
/** * Determines the chunk sizes and initializes the slab class descriptors * accordingly. */ 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; /* Factor of 2.0 means use the default memcached behavior */ if (factor == 2.0 && size < 128) size = 128; mem_limit = limit; if (prealloc) { /* Allocate everything in a big chunk with malloc */ mem_base = malloc(mem_limit); if (mem_base != NULL) { mem_current = mem_base; mem_avail = mem_limit; } else { fprintf(stderr, "Warning: Failed to allocate requested memory in" " one large chunk.\nWill allocate in smaller chunks\n"); } } memset(slabclass, 0, sizeof(slabclass)); while (++i < POWER_LARGEST && size <= POWER_BLOCK / 2) { /* Make sure items are always n-byte aligned */ if (size % CHUNK_ALIGN_BYTES) size += CHUNK_ALIGN_BYTES - (size % CHUNK_ALIGN_BYTES); slabclass[i].size = size; slabclass[i].perslab = POWER_BLOCK / slabclass[i].size; size *= factor; if (settings.verbose > 1) { fprintf(stderr, "slab class %3d: chunk size %6u perslab %5u\n", i, slabclass[i].size, slabclass[i].perslab); } } power_largest = i; slabclass[power_largest].size = POWER_BLOCK; slabclass[power_largest].perslab = 1; /* for the test suite: faking of how much we've already malloc'd */ { char *t_initial_malloc = getenv("T_MEMD_INITIAL_MALLOC"); if (t_initial_malloc) { mem_malloced = (size_t)atol(t_initial_malloc); } } #ifndef DONT_PREALLOC_SLABS { char *pre_alloc = getenv("T_MEMD_SLABS_ALLOC"); if (pre_alloc == NULL || atoi(pre_alloc) != 0) { slabs_preallocate(power_largest); } } #endif }
//参数factor是扩容因子,默认值是1.25 //limit参数就是memcached能分配的总内存 void slabs_init(const size_t limit, const double factor, const bool prealloc) { int i = POWER_SMALLEST - 1; //settings.chunk_size默认值为48,可以在启动memcached的时候通过-n选项设置 //size由两部分组成: item结构体本身 和 这个item对应的数据 //这里的数据也就是set、add命令中的那个数据.后面的循环可以看到这个size变量会 //根据扩容因子factor慢慢扩大,所以能存储的数据长度也会变大的 unsigned int size = sizeof(item) + settings.chunk_size; mem_limit = limit;//用户设置或者默认的内存最大限制 //用户要求预分配一大块的内存,以后需要内存,就向这块内存申请 if (prealloc) {//默认值为false /* Allocate everything in a big chunk with malloc */ mem_base = malloc(mem_limit); if (mem_base != NULL) { mem_current = mem_base; mem_avail = mem_limit; } else { fprintf(stderr, "Warning: Failed to allocate requested memory in" " one large chunk.\nWill allocate in smaller chunks\n"); } } //初始化数组,这个操作很重要,数组中所有元素的成员变量值都为0了 memset(slabclass, 0, sizeof(slabclass)); //slabclass数组中的第一个元素并不使用 //settings.item_size_max是memcached支持的最大item尺寸,默认为1M(也就是网上 //所说的memcached存储的数据最大为1MB)。 while (++i < POWER_LARGEST && size <= settings.item_size_max / factor) { /* Make sure items are always n-byte aligned */ if (size % CHUNK_ALIGN_BYTES)//8字节对齐 size += CHUNK_ALIGN_BYTES - (size % CHUNK_ALIGN_BYTES); //这个slabclass的slab分配器能分配的item大小 slabclass[i].size = size; //这个slabclass的slab分配器最多能分配多少个item(也决定了最多分配多少内存) slabclass[i].perslab = settings.item_size_max / slabclass[i].size; size *= factor;//扩容 if (settings.verbose > 1) { fprintf(stderr, "slab class %3d: chunk size %9u perslab %7u\n", i, slabclass[i].size, slabclass[i].perslab); } } power_largest = i;//最大的item slabclass[power_largest].size = settings.item_size_max; slabclass[power_largest].perslab = 1; if (settings.verbose > 1) { fprintf(stderr, "slab class %3d: chunk size %9u perslab %7u\n", i, slabclass[i].size, slabclass[i].perslab); } /* for the test suite: faking of how much we've already malloc'd */ { char *t_initial_malloc = getenv("T_MEMD_INITIAL_MALLOC"); if (t_initial_malloc) { mem_malloced = (size_t)atol(t_initial_malloc); } } if (prealloc) {//预分配内存 slabs_preallocate(power_largest); } }
/** * Determines the chunk sizes and initializes the slab class descriptors * accordingly. */ ENGINE_ERROR_CODE slabs_init(struct default_engine *engine, const size_t limit, const double factor, const bool prealloc) { int i = POWER_SMALLEST - 1; unsigned int size = sizeof(hash_item) + engine->config.chunk_size; logger = engine->server.log->get_logger(); engine->slabs.mem_limit = limit; engine->slabs.mem_reserved = (limit / 100) * RESERVED_SLAB_RATIO; if (engine->slabs.mem_reserved < (RESERVED_SLABS*engine->config.item_size_max)) engine->slabs.mem_reserved = (RESERVED_SLABS*engine->config.item_size_max); if (prealloc) { /* Allocate everything in a big chunk with malloc */ engine->slabs.mem_base = malloc(engine->slabs.mem_limit); if (engine->slabs.mem_base != NULL) { engine->slabs.mem_current = engine->slabs.mem_base; engine->slabs.mem_avail = engine->slabs.mem_limit; } else { return ENGINE_ENOMEM; } } else { engine->slabs.mem_base = NULL; engine->slabs.mem_current = NULL; engine->slabs.mem_avail = 0; } memset(engine->slabs.slabclass, 0, sizeof(engine->slabs.slabclass)); while (++i < POWER_LARGEST && size <= engine->config.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); engine->slabs.slabclass[i].size = size; engine->slabs.slabclass[i].perslab = engine->config.item_size_max / engine->slabs.slabclass[i].size; engine->slabs.slabclass[i].rsvd_slabs = RESERVED_SLABS; size *= factor; if (engine->config.verbose > 1) { fprintf(stderr, "slab class %3d: chunk size %9u perslab %7u\n", i, engine->slabs.slabclass[i].size, engine->slabs.slabclass[i].perslab); } } engine->slabs.power_largest = i; engine->slabs.slabclass[engine->slabs.power_largest].size = engine->config.item_size_max; engine->slabs.slabclass[engine->slabs.power_largest].perslab = 1; engine->slabs.slabclass[engine->slabs.power_largest].rsvd_slabs = RESERVED_SLABS; if (engine->config.verbose > 1) { fprintf(stderr, "slab class %3d: chunk size %9u perslab %7u\n", i, engine->slabs.slabclass[i].size, engine->slabs.slabclass[i].perslab); } /* for the test suite: faking of how much we've already malloc'd */ { char *t_initial_malloc = getenv("T_MEMD_INITIAL_MALLOC"); if (t_initial_malloc) { engine->slabs.mem_malloced = (size_t)atol(t_initial_malloc); } } #ifndef DONT_PREALLOC_SLABS { char *pre_alloc = getenv("T_MEMD_SLABS_ALLOC"); if (pre_alloc == NULL || atoi(pre_alloc) != 0) { slabs_preallocate(power_largest); } } #endif do_smmgr_init(engine); return ENGINE_SUCCESS; }
/** * Determines the chunk sizes and initializes the slab class descriptors * accordingly. */ void slabs_init(const size_t limit, const double* factors, const bool prealloc) { int i = POWER_SMALLEST - 1; unsigned int size = sizeof(item) + settings.chunk_size; mem_limit = limit; if (prealloc) { /* Allocate everything in a big chunk with malloc */ mem_base = malloc(mem_limit); if (mem_base != NULL) { mem_current = mem_base; mem_avail = mem_limit; } else { fprintf(stderr, "Warning: Failed to allocate requested memory in" " one large chunk.\nWill allocate in smaller chunks\n"); } } memset(slabclass, 0, sizeof(slabclass)); int factor_count = 0; // first factor is minumum value int factor_curr = 0; const double *f = factors; while (*f != 0) { factor_count++; f += 1; } int _perslab = -1; int _perslab_last = -1; while (i < POWER_LARGEST - 1) { factor_curr = (int) ( ( (double)i / (double)POWER_LARGEST ) * (double)factor_count ); double factor = factors[factor_curr]; /* Make sure items are always n-byte aligned */ if (size % CHUNK_ALIGN_BYTES) size += CHUNK_ALIGN_BYTES - (size % CHUNK_ALIGN_BYTES); _perslab = (int)(settings.item_size_max / size); if (size >= settings.item_size_max) break; if (_perslab <= 1) break; if (_perslab_last != _perslab) { i++; slabclass[i].size = size; slabclass[i].perslab = _perslab; if (settings.verbose > 1) { fprintf(stderr, "slab class %3d: chunk size %9u (factor #: %i) perslab %7u\n", i, slabclass[i].size, factor_curr+1, slabclass[i].perslab); } } _perslab_last = _perslab; if (factor > 0) { int _newsize = size * factor; if (_newsize <= size) size += 1; else size = _newsize; } else size += CHUNK_ALIGN_BYTES > -factor ? CHUNK_ALIGN_BYTES : -factor; } i++; power_largest = i; slabclass[power_largest].size = settings.item_size_max; slabclass[power_largest].perslab = 1; if (settings.verbose > 1) { fprintf(stderr, "slab class %3d: chunk size %9u perslab %7u\n", i, slabclass[i].size, slabclass[i].perslab); } /* for the test suite: faking of how much we've already malloc'd */ { char *t_initial_malloc = getenv("T_MEMD_INITIAL_MALLOC"); if (t_initial_malloc) { mem_malloced = (size_t)atol(t_initial_malloc); } } if (prealloc) { slabs_preallocate(power_largest); } }
/** * 初始话整个系统的一个存储空间。 * limit 分配内存的限制大小 0是没有限制 , * factor 是增长因子,每个快大小都会使用大小是上一个块的factor大小的 * prealloc 是否提前分配 * Determines the chunk sizes and initializes the slab class descriptors * accordingly. */ 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; if (prealloc) { /* Allocate everything in a big chunk with malloc */ mem_base = malloc(mem_limit); if (mem_base != NULL) { mem_current = mem_base; mem_avail = mem_limit; } else { fprintf(stderr, "Warning: Failed to allocate requested memory in" " one large chunk.\nWill allocate in smaller chunks\n"); } } memset(slabclass, 0, sizeof(slabclass)); while (++i < POWER_LARGEST && size <= settings.item_size_max / factor) { // item_size_max指的是每个内存快的大小,每个内存块的大小是现在在1M 大小以内的, // 也就是说item_size_max的大小是 1M ,详细可以查看memcached的init函数 /* Make sure items are always n-byte aligned */ if (size % CHUNK_ALIGN_BYTES) size += CHUNK_ALIGN_BYTES - (size % CHUNK_ALIGN_BYTES); //这个是用来确保每个size都是8的倍数 slabclass[i].size = size; slabclass[i].perslab = settings.item_size_max / slabclass[i].size; // item_size_max是每个slab的大小 size *= factor; if (settings.verbose > 1) { fprintf(stderr, "slab class %3d: chunk size %9u perslab %7u\n", i, slabclass[i].size, slabclass[i].perslab); } } power_largest = i;// i的最后一个,也就是内存大小最大的那个slabs slabclass[power_largest].size = settings.item_size_max;//最后的一个大小设置为1M slabclass[power_largest].perslab = 1;//而已只有一个 if (settings.verbose > 1) { fprintf(stderr, "slab class %3d: chunk size %9u perslab %7u\n", i, slabclass[i].size, slabclass[i].perslab); } /* for the test suite: faking of how much we've already malloc'd */ { char *t_initial_malloc = getenv("T_MEMD_INITIAL_MALLOC"); if (t_initial_malloc) { mem_malloced = (size_t)atol(t_initial_malloc); } } #ifndef DONT_PREALLOC_SLABS { char *pre_alloc = getenv("T_MEMD_SLABS_ALLOC"); if (pre_alloc == NULL || atoi(pre_alloc) != 0) { slabs_preallocate(power_largest); } } #endif }
/** * Determines the chunk sizes and initializes the slab class descriptors * accordingly. */ void slabs_init(const size_t limit, const size_t disk_cache_size, const double factor, const bool prealloc) { int i = POWER_SMALLEST - 1; unsigned int size = sizeof(item) + settings.chunk_size; mem_limit = limit; // limit == 0 means no limit disk_item_mem_limit = 1; if (limit && disk_cache_size) { const size_t M = 1024 * 1024; // settings.average_value_len + settings.average_key_len is ensured to be greater than 0 double k = (double)(sizeof(item) + settings.average_key_len + sizeof(DiskDataAddr)) / (settings.average_value_len + settings.average_key_len); disk_item_mem_limit = ((size_t)(disk_cache_size * k)) & ~(M - 1); if (disk_item_mem_limit >= limit) { disk_item_mem_limit = limit; mem_limit = 1;// 0 means unlimited, so it cannot be 0 } else if (disk_item_mem_limit == 0) { disk_item_mem_limit = 1; } else { mem_limit = limit - disk_item_mem_limit; } } fprintf(stderr, "slabs_init: mem_limit: %lu, disk_item_mem_limit: %lu\n", mem_limit, disk_item_mem_limit); if (prealloc) { /* Allocate everything in a big chunk with malloc */ mem_base = malloc(mem_limit); if (mem_base != NULL) { mem_current = mem_base; mem_avail = mem_limit; } else { fprintf(stderr, "Warning: Failed to allocate requested memory in" " one large chunk.\nWill allocate in smaller chunks\n"); } } 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); slabclass[i].size = size; slabclass[i].perslab = settings.item_size_max / slabclass[i].size; size *= factor; if (settings.verbose > 1) { fprintf(stderr, "slab class %3d: chunk size %9u perslab %7u\n", i, slabclass[i].size, slabclass[i].perslab); } } power_largest = i; slabclass[power_largest].size = settings.item_size_max; slabclass[power_largest].perslab = 1; if (settings.verbose > 1) { fprintf(stderr, "slab class %3d: chunk size %9u perslab %7u\n", i, slabclass[i].size, slabclass[i].perslab); } /* for the test suite: faking of how much we've already malloc'd */ { char *t_initial_malloc = getenv("T_MEMD_INITIAL_MALLOC"); if (t_initial_malloc) { mem_malloced = (size_t)atol(t_initial_malloc); } } #ifndef DONT_PREALLOC_SLABS { char *pre_alloc = getenv("T_MEMD_SLABS_ALLOC"); if (pre_alloc == NULL || atoi(pre_alloc) != 0) { slabs_preallocate(power_largest); } } #endif }