今天在读《Go语言学习笔记》5.4 字典章节的时候。看到有一个例子通过benchmark介绍 map的一个知识点--创建map的时候最好预估一个足够的大小,这样可以避免频繁的扩容导致申请内存和rehash的操作。

因为之前自己也没有写过benchmark,所以就想着动手操作一下。但是发现书上的代码并不完整。也没有运行命令。自己捣鼓了一下,也顺便分享给小伙伴们。

整个代码如下

这里一开始我的文件名:map_expansion.go

当我运行 benchmark 命令时,发现没有效果。

因为这个benchmark也是一个测试,所以文件名要以_test结尾。

可以看到结果如下

刚开始看到这个结果其实比较懵,后面3个带单位的还可以猜一下。但是前面2个就完全不知道啥意思了。

第一列 就是测试方法名 -12 表示GOMAXPROCS(线程数)的值为12。

第二列 18309和43518表示执行了多少次。对应代码里的b.N的数量。

第三列 从单位(ns/op)也可以猜到每个操作耗时多少ns。

第四列 每个操作需要申请多少内存。

第五列 每个操作申请了几次内存。

从测试结果来看TestCap的效果 确实比Test的效果要好很多尤其是申请内存的次数上要少很多。不进行预分配的情况 每次操作要申请64次内存而预分配1000后每次操作,需要申请6次内存。

但是我们又知道 map的负载因子是 0.65 , 也就是说就算预分配了1000,也会触发扩容。于是我又做了一组实验用在Cap函数里预分配1650

可以看到结果还是每次操作申请了6次内存。

直到加到预申请1665才会每次操作申请2次内存。但是每次操作申请的内存数量又上来了。

哪位大佬可以指点一二?