/** Init the subsystem. 1st argument is the limit on no. of bytes to allocate, 0 if no limit. 2nd argument is the growth factor; each slab will use a chunk size equal to the previous slab's chunk size times this factor. 3rd argument specifies if the slab allocator should allocate all memory up front (if true), or allocate memory in chunks as it is needed (if false)*/voidslabs_init(constsize_tlimit,constdoublefactor,constboolprealloc);
/** * Determines the chunk sizes and initializes the slab class descriptors * accordingly. */voidslabs_init(constsize_tlimit,constdoublefactor,constboolprealloc){inti=POWER_SMALLEST-1;//真实占用大小=对象大小+48unsignedintsize=sizeof(item)+settings.chunk_size;mem_limit=limit;//开启预分配,则首先将limit大小(默认64M)的内存全部申请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");}}//清空所有的slabmemset(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);}}//最大chunksize的一个slab,chunksize为settings.item_size_max(默认1M)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);}}//开启了预分配,则为每种slab都分配一个page的空间if(prealloc){slabs_preallocate(power_largest);}}
其中settings.chunk_size默认为48:
settings.chunk_size = 48; /* space for a modest key and value */
staticvoidslabs_preallocate(constunsignedintmaxslabs){inti;unsignedintprealloc=0;/* pre-allocate a 1MB slab in every size class so people don't get confused by non-intuitive "SERVER_ERROR out of memory" messages. this is the most common question on the mailing list. if you really don't want this, you can rebuild without these three lines. */for(i=POWER_SMALLEST;i<=POWER_LARGEST;i++){if(++prealloc>maxslabs)return;if(do_slabs_newslab(i)==0){fprintf(stderr,"Error while preallocating slab memory!\n""If using -L or other prealloc options, max memory must be ""at least %d megabytes.\n",power_largest);exit(1);}}}
/* * Figures out which slab class (chunk size) is required to store an item of * a given size. * * Given object size, return id to use when allocating/freeing memory for object * 0 means error: can't store such a large object */unsignedintslabs_clsid(constsize_tsize){intres=POWER_SMALLEST;//最小slab编号if(size==0)return0;while(size>slabclass[res].size)if(res++==power_largest)/* won't fit in the biggest slab */return0;returnres;}
perlmemcached-tool10.0.0.5:11211display#showsslabsperlmemcached-tool10.0.0.5:11211#same.(defaultisdisplay)perlmemcached-tool10.0.0.5:11211stats#showsgeneralstatsperlmemcached-tool10.0.0.5:11211move79#takes1MBslabfromclass#7# to class #9.