CPU访问寄存器比访问内存快很多,所以有高速缓存弥补这部分性能差异。高速缓存以缓存线(cache line)为单位进行存取。缓存线的大小取决于具体的CPU,一般是64字节。高速缓存的信息可以从/sys/devices/system/cpu/cpuX/cache/indexX
中读取,比如:/sys/devices/system/cpu/cpu0/cache/index0
就是读取的cpu0的L1缓存的信息,其中coherency_line_size是缓存线的大小、level是缓存级别、type是缓存类型、shared_cpu_list是共享该缓存的cpu列表、size是该缓存的大小。
当缓存中的数据被修改,还没同步到内存,就称为该缓存线脏了,会做一个标记。当缓存不足时,会销毁一些缓存线,如果是脏的,就会回写内存。降级为访问内存的速度。
下面我们来做实验,通过不同的数据大小,相同的访问次数,来看随着数据增加,访问时间增加的现象。
cache.go
package main
import (
"fmt"
"log"
"os"
"strconv"
"time"
"golang.org/x/sys/unix"
)
const (
CACHE_LINE = 64
NUM_LOOP = 4 * 1024 * 1024 * 1024
)
func main() {
if len(os.Args) < 2 {
panic(fmt.Sprintf("usage: %s <size[KB]>\n", os.Args[0]))
}
sizeArg, _ := strconv.Atoi(os.Args[1])
size := sizeArg * 1024
if size < 1 {
panic(fmt.Sprintf("size must > 0, but got %d\n", size))
}
buffer, err := unix.Mmap(-1, 0, size, unix.PROT_READ|unix.PROT_WRITE, unix.MAP_PRIVATE|unix.MAP_ANON)
if err != nil {
log.Fatalf("mmap() failed with %s\n", err)
}
defer unix.Munmap(buffer)
start := time.Now()
for i := 0; i < NUM_LOOP/(size/CACHE_LINE); i++ {
for j := 0; j < size; j += CACHE_LINE {
buffer[j] = 0
}
}
log.Printf("cost %v\n", time.Now().Sub(start))
}
结果如下:
hoo@LAPTOP-CMIA23FA:/mnt/d/hoo/code$ go run cache.go 1
2022/08/04 09:24:46 cost 1.872088065s
hoo@LAPTOP-CMIA23FA:/mnt/d/hoo/code$ go run cache.go 2
2022/08/04 09:24:53 cost 2.674986682s
hoo@LAPTOP-CMIA23FA:/mnt/d/hoo/code$ go run cache.go 4
2022/08/04 09:24:58 cost 1.905968251s
hoo@LAPTOP-CMIA23FA:/mnt/d/hoo/code$ go run cache.go 8
2022/08/04 09:25:04 cost 1.724077179s
hoo@LAPTOP-CMIA23FA:/mnt/d/hoo/code$ go run cache.go 16
2022/08/04 09:25:09 cost 1.457848844s
hoo@LAPTOP-CMIA23FA:/mnt/d/hoo/code$ go run cache.go 32
2022/08/04 09:25:13 cost 1.311004971s
hoo@LAPTOP-CMIA23FA:/mnt/d/hoo/code$ go run cache.go 64
2022/08/04 09:25:20 cost 4.043168597s
hoo@LAPTOP-CMIA23FA:/mnt/d/hoo/code$ go run cache.go 128
2022/08/04 09:25:30 cost 4.04601697s
hoo@LAPTOP-CMIA23FA:/mnt/d/hoo/code$ go run cache.go 256
2022/08/04 09:25:38 cost 4.128703878s
hoo@LAPTOP-CMIA23FA:/mnt/d/hoo/code$ go run cache.go 512
2022/08/04 09:25:46 cost 3.919007785s
hoo@LAPTOP-CMIA23FA:/mnt/d/hoo/code$ go run cache.go 1024
2022/08/04 09:25:55 cost 4.573088897s
hoo@LAPTOP-CMIA23FA:/mnt/d/hoo/code$ go run cache.go 2048
2022/08/04 09:26:08 cost 7.934703355s
hoo@LAPTOP-CMIA23FA:/mnt/d/hoo/code$ go run cache.go 4096
2022/08/04 09:26:22 cost 8.495372193s
hoo@LAPTOP-CMIA23FA:/mnt/d/hoo/code$ go run cache.go 8192
2022/08/04 09:26:52 cost 17.472046494s
hoo@LAPTOP-CMIA23FA:/mnt/d/hoo/code/qt$ go run cache.go 16384
2022/08/04 09:28:23 cost 29.343755701s