Understanding The Memcached Source Code — Slab II
slab allocator (I, II — this article) is the core module of the cache system, which largely determines how efficient the bottleneck resource, memory, can be utilized. The other 3 parts, namely,
LRU algorithm (not complete) for entry expiration; and an
event driven model (not complete) based on libevent; and the
consistent harsh (not complete) for data distribution,
are built around it.
This time we continue examining how slabs memory is allocated.
Firstly we look at the two arguments for
slabs_init, which were passed over in the previous article. The first one is
settings.maxbytes, it limits the overall memory that can be used by the memcached instance. In
slabs_init, the value of
settings.maxbytes is assigned to the global variable
mem_limit which will be used very soon.
The other argument is preallocate. It determines whether to preallocate slab for each slab class. This argument is toggled with
L command line argument.
Next we look at the method for slabs memory allocation itself.
More specific, this method allocate one 1M sized slab for the slab class indicated by the parameter
slabclass[id] is one of the slab class, the initialization of which is discussed in last article.
settings.slab_reassign determines whether to enlist a rebalancing mechanism, which recycles the unused slabs and redistributes them across slab classes. This requires that slabs contained in all slab classes be of the same size, hence this setting also decides whether to use unanimous (i.e.,
settings.item_size_max, or 1M as mentioned before) or heterogeneous (i.e.,
p->size * p->perslab) slabs. Besides the its associated command line argument "slab_reassign", the value can be controlled by another argument
"modern". For the positivity the name “modern” implies, 1M will be used throughout the text.
N.b. *, rebalancing mechanism will be discussed later when we have a better understanding of the LRU module.
3) Check if the memory usage will exceeds the upper limit.
grow_slab_list checks if we need to increase
slabclass_t.slab_list, if so, grows it.
memory_allocate allocates the actual memory for the slab. As discussed, here the value of
len is 1M.
split_slab_page_into_freelist initializes (frees) the newly allocated
slab preparing for objects storing. This method will be discussed in the next section.
7) Add the newly allocated
slab to the
What has happened so far can be summarized with the following figure, (we assume
do_slabs_newslab(n) is called two times)
Now we look inside the 1M slab in step 6).
This method goes through all the item chunks (in the size of
slabclass_t.size) within a slab. And for each of them, the method initializes its meta data by calling
do_slabs_free. Another way to interpret this process is “split a slab into item free list”. As you might have already figured out, this “free list” will be used by item allocation in future.
This method works on item meta data that is populated in the beginning of an item memory chunk.
1) Initialize some fields.
item is another core data structure, we will come back to item data structure later.
2) Add the item to the front of the linked list (a.k.a., free list). And update the list head,
3) Update the available (free list) slot count,
slabclass_t.sl_curr; and updates the
slabclass_t.requested for statistic. Note that here we are not actually releasing an item, so the passed
size is 0.
Next we look at how
do_slabs_newslab is used. One place it gets called is from the discussed
preallocate is set to
This method simply goes through the
slabclass starting from the
POWER_SMALLEST, i.e., 1st entry, and allocate one slab for each of them. Note that the 0th is a special slab class used by mentioned rebalancing mechanism.
Same to the previous one.
Originally published at holmeshe.me.