上一节《Runtime: Golang 之 sync.Pool 源码分析》我们介绍了sync.Pool 的源码分析,本节介绍一个 fasthttp
中引用的一缓存池库 bytebufferpool
,这两个库是同一个开发者。对于这个缓存池库与同类型的几个库的对比,可以参考 https://omgnull.github.io/go-benchmark/buffer/。
建议大家了解一下fasthttp
这个库,性能要比直接使用内置的 net/http
高出很多,其主要原因是大量的用到了缓存池 sync.Pool
进行性能提升。
全局变量
我们先看一下与其相关的一些常量
const ( // 定位数据索引位置,使用位操作性能比较高效 minBitSize = 6 // 2**6=64 is a CPU cache line size // 数组索引个数 0~19 steps = 20 // 最小缓存对象 和 最大缓存对象大小 minSize = 1 << minBitSize maxSize = 1 << (minBitSize + steps - 1) // 校准阈值, 这里指的调用次数 calibrateCallsThreshold = 42000 // 百分比,校准数据基数 maxPercentile = 0.95 )
对于常量上面已做了注释,如果现在不明白的话没有关系,看完下面就知道它们的作用了。
数据类型
主要有两个相关的数据结构,分别为 Pool
和 ByteBuffer
,其实现也比较的简单。
Pool 数据结构
// Pool represents byte buffer pool. // // Distinct pools may be used for distinct types of byte buffers. // Properly determined byte buffer types with their own pools may help reducing // memory waste. type Pool struct { calls [steps]uint64 calibrating uint64 defaultSize uint64 maxSize uint64 pool sync.Pool } var defaultPool Pool
字段解释
calls
缓存对象大小调用次数统计,steps
就是我们上面定义的常量。主要用来统计每类缓存大小的调用次数。steps 具体的值会使用一个index()
函数通过位操作的方式计算出来它在这个数组的索引位置;calibrating
校标标记。0 表示未校准,1表示正在校准。校准需要一个过程,校准完成后需要从1恢复为 0;defaultSize
缓存对象默认大小。我们知道当从 pool 中获取缓存对象时,如果池中没有对象可取,会通过调用 一个New()
函数创建一个新对象返回,这时新创建的对象大小为defaultSize
。当然这里没有使用New()
函数,而是直接创建了一个 指定默认大小的ByteBuffer
;maxSize
允许放入pool
池中的最大对象大小,只有<maxSize
的对象才允许放放池中
这里的变量 defaultPool 是一个全局的 Pool 对象。
Continue reading