分类: LINUX
2013-08-27 11:54:37
原文地址:memcached-1.4.15 SLAB页转移过程分析 作者:不要站在我背后
memcached-1.4.15 SLAB页转移过程分析
启动时指定参数 -o slab_reassign,slab_automove=1或2
此时程序将启动两个线程:slab_maintenance_thread、slab_rebalance_thread
一、 slab_maintenance_thread线程为SLAB主线程
代码如下
(一) slab_automove = 1 时
由上边的代码显示出,线程将自动选择符合条件的src slabclass和dest slabclass。选取规则如下:
(10秒检查一次){
1. 获取没给slabclass 发生LRU的次数(itemstats[id].evicted);
2. 找出一个检查了3次(10秒检查一次)并且LRU次数没有增加的、page页数3页以上的class作为src slabclass;
3. 如果本次检查中,LRU次数增加最多的slabclass为连续检查3次都是LRU增加最多的slabclass,则选取当前class为dest slabclass;
4. 当 src slabclass 和 dest slabclass 都选到时,通过pthread_cond_signal唤醒 slab_rebalance_thread线程进行slab转移,否则继续轮询检查(10秒检查一次)。
}
以上的LRU为没有指定-M选项,并且内存不足无法分配item时。
(二) slab_automove = 2时
当内存不足,无法分配新的item时,发生LRU后,进行slab页转移,转移到当前页。src slabclass选取规则为随机选取,选取规则如下:
1. 第一次LRU时,从slabclass1开始向后查找(查找范围为所有页数的上半部分)一个有2个slab page以上的slabclass作为src slabclass。
2. 第二次发生LRU后,会从上一次选取的class之后进行查找(查找范围为当前class到最大slabclass数量的上半部分)合适的class进作为src slabclass。
代码如下:
二、 slab_rebalance_thread线程为SLAB页移动线程。将src slabclass中的第一页移动到dest slabclass中,为最后一页。过程如下:
1. slab_rebalance_start:赋值 slab_rebal全局变量,将page页的起止位置、结束位置、src slabclass id、dest slabclass id赋值给全局变量 slab_rebal,用于后期处理;并检查dest slabclass的page页链表是否空间充足,如果空间不足则扩展空间为原来的两倍大小。
2. slab_rebalance_move:将 slab_rebal指向的 page页中chunk存储的所有item从hashtable中删除,并将其从原slabclass的head,tail链表中删除,并从回收链表中删除。
3. slab_rebalance_finish:重置slab_rebal全局变量,并初始化page为0,并将page分成chunk添加到dest slabclass的slots链表中。
slab_rebalance结构体如下:
struct slab_rebalance {
void *slab_start; //待转移page的内存起始地址
void *slab_end; //page页的尾地址
void *slab_pos; //当前处理的item所在该page中的位置(从前向后处理)
int s_clsid; //src slabclass id
int d_clsid; //dest slabclass id
int busy_items; //busy item的数量(当前item被加锁,所以无法处理)
uint8_t done; //是否该页中chunk存储的item已经全部处理完毕(从hashtable中删除、从原slabclass中的回收链表中删除)
};
代码如下: