Skip to content

2.0 jcache内存池

yanjunli edited this page Feb 3, 2017 · 12 revisions

内存池部分代码在 Slabs.java类里

JCache 内部池涉及到的概念:

1.chunk jcache 存储的最小单元.用于存储item.

2.slab  相当于page 的概念,一个slab会被切割成 多个chunk

3.slabclass 一个 slabclass 由多个slab组成.记录了当前已分配了多少slab,空间item链表 等信息.

4.pool  全局唯一的一个容器.负责 slabclass,slab,item 的生命周期.

item 可以分为两部分,分别是: 属性部分,和数据部分. 属性部分长度固定,数据部分长度不固定.

# 字段 说明
1 prev 指向上一个item 的内存首地址,没有就是0.
2 next 指向下一个item 的内存首地址,没有就是0.
3 hnext hashtable 某一个桶内, 指向下一个item 的内存首地址,hash单向链表
4 flushtime 当前item 最近一次访问时间. 每次访问都会刷新该字段.
5 exptime 过期时间
6 nbytes: value 的总大小, 包含最后两位\r\n 的长度. 客户端传递过来的数据并没有包含\r\n,存储的时候在最后两位附加上的.
7 refcount 当前item 被 引用的次数,只在内部使用.
8 slabs_clsid 当前 item 属于哪个slabclass
9 it_flags item 存储状态标记字段 位运算.
10 nsuffix suffix 的长度.        
11 nkey key 的长度
12 cas  cas  当前item cas 值.  如果 启用cas 的话, 当前字段有值,如果没有启用cas,item结构中没有该字段
13 suffix 格式为: '' "flags" '' "nbytes" \r \n . '' 代表  一个空的字符
例如: 如果 flags=32 (32 代表字符串), nbytes=15 ( 15 代表 value 的byte[] 长度.).
那么 nsuffix = ''32''15\r\n.
14 value 将客户端传递进来的value + \r\n后存储.
# 字段 说明
1 size 当前 slabclass 内 分配的item 的大小.
2 perslab 当前slabclass ,每个slab可以分配多少个item
3 slots 当前空闲的item 的空闲列表 对应的内存首地址,所有空闲的item 都放到 slots 空闲列表 里面
4 sl_curr 当前slabclass 空闲的item 的 数量.
5 slab_list 已分配的slab 的集合对应的内存首地址.
6 list_size slab_list 的 大小
7 requested 已经使用的所有 item 的总大小.不包括空闲的.

初始化

  1. jcache启动时,会预分配一整块内存给内存池.如果操作系统支持大内存页.建议开启
  2. 分配一个大小是64的slabclass数组.并根据增长因子factor(默认为1.25),初始化每个slabclass 的chunk 的大小,及对应的slab内可以容纳的chunk 的数量. 同一个slabclass 内, 所有的chunk大小相同.
    计算公式为:(1024*1024)/chunksize.
    一个slab 的大小固定为1M,一个chunksize 的最大大小也为1M.
    因为slab 和chunk最大值固定为1M,随着chunksize 的逐渐增加,slab内分配的chunk数量逐渐减少.当chunksize大于1M时,不再初始化新的slabclass.
  3. 初始化每个slabcalss 时,会预先分配一个slab,并初始化.

相关代码参见: DefaultSlabsImpl.slabs_init 方法.

####jcache 内存结构图1 slabclass和slab、item以及free list之间的关系 ####jcache 内存结构图2

为item分配合适的chunk

分配一个item

  1. 分配一个item 时,会先检查空闲列表中,是否有空闲的chunk,如果有就从空闲列表中获取.
  2. 如果没有,说明预分配的slab 已经用完,需要新分配一个slab.
  3. 如果分配成功,初始化这个slab,并将切割出来的chunk 放入到 空闲列表中.
  4. 从空闲列表中取出一个chunk,分配给item.

相关代码参见:DefaultSlabsImpl.slabs_alloc 方法.

释放一个item

  1. 当item 的引用计数recount=0 的时候,item会被释放掉.
  2. 释放item后,对应的chunk会被放进空闲列表中.

相关代码参见:DefaultSlabsImpl.slabs_free 方法.

Clone this wiki locally