考虑下面的代码,其中我分配了4000个数组,每个数组的长度为100k:
parentMap := make(map[int][100_000]int)
for i := 0; i < 4000; i++ {
parentMap[i] = [100_000]int{}
time.Sleep(3 * time.Millisecond)
}
如果我在本地运行它,并分析它的内存使用情况,它开始使用2 GB的内存.
现在,如果我们稍微更改代码以使用数组片段(但长度也是100k),如下所示:
parentMap := make(map[int][]int)
for i := 0; i < 4000; i++ {
parentMap[i] = make([]int, 100_000)
time.Sleep(3 * time.Millisecond)
}
在我的机器上,内存峰值约为73MB.Why is this?个
我认为这两个代码片段使用的内存大致相同,原因如下:
- 在这两种情况下,Go运行时都将在堆上分配值
parentMap
.Go之所以这样做,是因为如果它在堆栈上分配了这些值,那么当前函数一旦超出作用域,parentMap
的值就会全部清除. - 因此,第一个代码片段直接在堆上分配4karray.
- 并且,第二个代码段在堆上分配4k切片标头.每个片标头都有一个指向大小为100k的唯一数组(也在堆上)的指针.
- 在这两种情况下,大小为100k的堆上都有4k个array.因此,在这两种情况下都应该使用大致相同的内存量.
我读到:https://go.dev/blog/slices-intro.但是找不到可以解释这一点的实现细节.