缓存池 bytebufferpool 库实现原理

上一节《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

Runtime: Golang 之 sync.Pool 源码分析

Pool 指一组可以单独保存和恢复的 临时对象。Pool 中的对象随时都有可能在没有收到任何通知的情况下被GC自动销毁移除。

多个goroutine同时操作Pool是并发安全的。

源文件为 src/sync/pool.go go version: 1.16.2

为什么使用Pool

在开发高性能应用时,经常会有一些完全相同的对象需要频繁的创建和销毁,每次创建都需要在堆中分配对象,等使用完毕后,这些对象需要等待GC回收。我们知道在Golang中使用三色标记法进行垃圾回收的,在回收期间会有一个短暂STW(stop the world)的时间段,这样就会导致程序性能下降。

那么能否实现类似数据库连接池这种效果,用来避免对象的频繁创建和销毁,达到尽可能的资源复用呢?为了实现这种需求,标准库中有了sync.Pool 这个数据结构。看名字很知道它是一个池。但是它和我们想象中的数据库连接池还是有些差别的。对于数据库连接池这种资源只要不手动释放就可以一直利用,但对于 sync.Pool 则不一样,主要是因为Pool里的对象是随时都有可能被销毁,即这些都 临时对象。只要进行了GC,就会出现对象销毁的情况。所以不用使用Pool当作数据库连接池。

Continue reading