golang本地缓存fastcache高性能实现原理

1. git仓库

https://github.com/abbothzhang/fastcache

2. 整体原理

  1. initCache时不会申请内存,只有第一次set时候才会申请,且会一次性申请64MB,后面不够了又一次性申请1024*64MB大小内存

2.1. 时序图

在这里插入图片描述

3. 高性能原因

  1. 将cache分为512个bucket,每个bucket一个锁,将锁竞争维度降低, 增加并发度
  2. map定义为map[uint64]uint64, value里只存索引,真正的值放在二维数组里,这样GC时无需遍历,减少stw
  3. 堆外内存申请二维数组,无需GC
  4. 使用很多位运算,快速且节省空间

4. 注意点

  1. 一次会申请1024个chunk大小的内存,即1024*64KB=64MB大小的内存,如果初始化cache时候设置的缓存大小小于64MB,也会申请这么大
  2. 没有过期时间设置,FIFO的过期方式, 只靠缓存环覆盖
  3. 内存申请到初始化时设置的最大内存后,就会一直保持,不会释放
  • 缓存数据大小超过 64K, 需要调用 SetBig 方法存储

5. 数据结构

  1. chunk为byte数组,作为环形缓冲区使用

img

6. 初始化

6.1. 初始化入口

func New(maxBytes int) *Cache {
   
    if maxBytes <= 0 {
   
        panic(fmt.Errorf("maxBytes must be greater than 0; got %d", maxBytes))
    }
    var c Cache
    maxBucketBytes := uint64((maxBytes + bucketsCount - 1) / bucketsCount)
    for i := range c.buckets[:] {
   
        c.buckets[i].Init(maxBucketBytes)
    }
    return &c
}

6.2. bucket初始化

下面是bucket的初始化方法,需要注意的是其仅仅初始化了b.chunks的大小,并没有初始化单个chunk的内存空间(即chunkSize字节)。chunk的初始化是在实际使用时从freeChunks申请的,这样可以避免预先分配冗余内存。这种方式有点类似底层的虚拟内存的概念,只有在真正使用的时候才会分配内存。后面会看到freeChunks是如何申请内存的

func (b *bucket) Init(maxBytes uint64) {
   
	if maxBytes == 0 {
   
		panic(fmt.Errorf("maxBytes cannot be zero"))
	}
	if maxBytes >= maxBucketSize {
   
		panic(fmt.Errorf("too big maxBytes=%d; should be smaller than %d", maxBytes, maxBucketSize))
	}
	maxChunks := (maxBytes + chunkSize - 1) / chunkSize
	b.chunks = make([][]byte, maxChunks)
	b.m = make(map[uint64]uint64)
	b.Reset()
}

6.3. 内存申请

func getChunk() []byte {
   
	freeChunksLock.Lock()
	// 检查是否有可用的内存块,如果没有,则开辟
	if len(freeChunks) == 0 {
   
		// Allocate offheap memory, so GOGC won't take into account cache size.
		// This should reduce free memory waste.
		//使用 unix.Mmap 分配一块较大的匿名内存区域 (chunkSize*chunksPerAlloc 字节),这块内存不会被 Go 的垃圾回收器(GOGCÿ
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值