如何在Go中获取变量的内存大小?
我对map
和的内存成本感到好奇slice
,因此我编写了一个程序来比较大小。我通过获得内存大小unsafe.Sizeof(s)
,但是显然这是错误的,因为当我更改大小时,输出是相同的。
func getSlice(size int) []int {
t := time.Now()
s := make([]int, size*2)
for i := 0; i < size; i++ {
index := i << 1
s[index] = i
s[index+1] = i
}
fmt.Println("slice time cost: ", time.Since(t))
return s
}
func getMap(size int) map[int]int {
t := time.Now()
m := make(map[int]int, size)
for i := 0; i < size; i++ {
m[i] = i
}
fmt.Println("map time cost: ", time.Since(t))
return m
}
func TestMem(t *testing.T) {
size := 1000
s := getSlice(size)
m := getMap(size)
fmt.Printf("slice size: %d\n", unsafe.Sizeof(s))
fmt.Printf("map size: %d\n", unsafe.Sizeof(m))
}
-
unsafe.SizeOf()
并且reflect.Type.Size()
仅返回传递值的大小,而无需递归遍历数据结构和添加指针值的大小。slice是相对简单的结构:
reflect.SliceHeader
,并且由于我们知道它引用了后备数组,因此我们可以轻松地“手动”计算其大小,例如:s := make([]int32, 1000) fmt.Println("Size of []int32:", unsafe.Sizeof(s)) fmt.Println("Size of [1000]int32:", unsafe.Sizeof([1000]int32{})) fmt.Println("Real size of s:", unsafe.Sizeof(s)+unsafe.Sizeof([1000]int32{}))
输出(在Go Playground上尝试):
Size of []int32: 12 Size of [1000]int32: 4000 Real size of s: 4012
地图是更复杂的数据结构,我不会详细介绍
计算任何变量或结构的大小(递归)
如果您需要“实数”数字,则可以利用Go的测试工具,该工具还可以执行内存基准测试。传递
-benchmem
参数,并且在基准函数内部仅分配要测量的内存:func BenchmarkSlice100(b *testing.B) { for i := 0; i < b.N; i++ { getSlice(100) } } func BenchmarkSlice1000(b *testing.B) { for i := 0; i < b.N; i++ { getSlice(1000) } } func BenchmarkSlice10000(b *testing.B) { for i := 0; i < b.N; i++ { getSlice(10000) } } func BenchmarkMap100(b *testing.B) { for i := 0; i < b.N; i++ { getMap(100) } } func BenchmarkMap1000(b *testing.B) { for i := 0; i < b.N; i++ { getMap(1000) } } func BenchmarkMap10000(b *testing.B) { for i := 0; i < b.N; i++ { getMap(10000) } }
(删除的定时和从印刷呼叫
getSlice()
和getMap()
当然)。与
go test -bench . -benchmem
输出为:
BenchmarkSlice100-4 3000000 471 ns/op 1792 B/op 1 allocs/op BenchmarkSlice1000-4 300000 3944 ns/op 16384 B/op 1 allocs/op BenchmarkSlice10000-4 50000 39293 ns/op 163840 B/op 1 allocs/op BenchmarkMap100-4 200000 11651 ns/op 2843 B/op 9 allocs/op BenchmarkMap1000-4 10000 111040 ns/op 41823 B/op 12 allocs/op BenchmarkMap10000-4 1000 1152011 ns/op 315450 B/op 135 allocs/op
B/op
值告诉您每个操作分配了多少字节。allocs/op
告诉每个操作发生了多少(不同的)内存分配。在我的64位体系结构(其中的大小
int
为8个字节)上,它告诉您具有2000个元素的切片的大小大约为16 KB(与2000 * 8字节一致)。包含1000int-int
对的地图大约需要分配42 KB。
-
如何获取变量的内存大小?
2021-02-01 关注 0 浏览103 1答案
-
Python中变量的内存大小
2021-01-29 关注 0 浏览127 1答案
-
如何获取Android中对象的内存大小或性能基准?
2021-01-30 关注 0 浏览95 1答案
-
从Java获取操作系统内存大小
2021-01-30 关注 0 浏览125 1答案
-
Java中ArrayList的内存大小是多少
2021-01-30 关注 0 浏览89 1答案
-
Java中的对象是否有任何内存大小限制?
2021-01-30 关注 0 浏览111 1答案
-
Linux odbc致命错误:允许的内存大小
2021-02-01 关注 0 浏览95 1答案
-
加载大于h2o中的内存大小的数据
2021-01-30 关注 0 浏览95 1答案
-
如何在Go中获取文件长度?
2021-02-01 关注 0 浏览134 1答案
-
如何在Go中获取文件长度?
2022-01-03 关注 0 浏览85 1答案