-
Notifications
You must be signed in to change notification settings - Fork 44
2.0 jcache内存池
yanjunli edited this page Feb 7, 2017
·
12 revisions
内存池部分代码在 DefaultSlabsImpl.java类里
1.chunk jcache 存储的最小单元.用于存储item.
2.slab 相当于page 的概念,一个slab会被切割成 多个chunk
3.slabclass 一个 slabclass 由多个slab组成.记录了当前已分配了多少slab,空闲列表 等信息.
4.pool 全局唯一的一个容器.负责 slabclass,slab,item 的生命周期.
# | 字段 | 说明 |
---|---|---|
1 | prev | 指向上一个item 的内存首地址,没有就是0. |
2 | next | 指向下一个item 的内存首地址,没有就是0. |
3 | hnext | hashtable 某一个桶内, 指向下一个item 的内存首地址.单向链表,出现hash冲突时,当前链表会有多个item.当hashtable中存储的item数量大于总量的1.5倍时,hashtable会扩容. |
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" . '' 代表 一个空的字符 例如: 如果 flags=32 (32 代表字符串), nbytes=15 ( 15 代表 value 的byte[] 长度.). 那么 nsuffix = ''32''15. |
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 的总大小.不包括空闲的. |
- jcache启动时,会预分配一整块内存给内存池.如果操作系统支持大内存页.建议开启
- 分配一个大小是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. - 初始化每个slabcalss 时,会预先分配一个slab,并初始化.
相关代码参见: DefaultSlabsImpl.slabs_init 方法.
####jcache 内存结构图1 ####jcache 内存结构图2
- 分配一个chunk 时,会先检查空闲列表中,是否有空闲的chunk,如果有就从空闲列表中获取.
- 如果没有,说明预分配的slab 已经用完,需要新分配一个slab.
- 如果分配成功,初始化这个slab,并将切割出来的chunk 放入到 空闲列表中.
- 从空闲列表中取出一个chunk,分配给item.
相关代码参见:DefaultSlabsImpl.slabs_alloc 方法.
- 当item 的引用计数recount=0 的时候,item会被释放掉.
- 释放item后,对应的chunk会被放进空闲列表中.
相关代码参见:DefaultSlabsImpl.slabs_free 方法.