如何在Go中获取变量的内存大小? [英] How to get memory size of variable in Go?

查看:306
本文介绍了如何在Go中获取变量的内存大小?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我对mapslice的内存成本感到好奇,因此我编写了一个程序来比较大小.我通过unsafe.Sizeof(s)获得内存大小,但是显然这是错误的,因为当我更改大小时,输出是相同的.

I am curious about the memory cost of map and slice, so I wrote a program to compare the sizes. I get the memory size by unsafe.Sizeof(s), but obviously it is wrong, because when I change the size, the output is the same.

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()仅返回传递的值的大小,而无需递归遍历数据结构和添加指针值的大小.

unsafe.SizeOf() and reflect.Type.Size() only return the size of the passed value without recursively traversing the data structure and adding sizes of pointed values.

切片是相对简单的结构: reflect.SliceHeader ,因为我们知道引用支持数组,我们可以轻松地手动"计算其大小,例如:

The slice is relatively a simple struct: reflect.SliceHeader, and since we know it references a backing array, we can easily compute its size "manually", e.g.:

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{}))

输出(在转到游乐场上尝试):

Size of []int32: 12
Size of [1000]int32: 4000
Real size of s: 4012

地图是更为复杂的数据结构,我不会详细介绍,但请查看以下问题并解答:

Maps are a lot more complex data structures, I won't go into details, but check out this question+answer: Golang: computing the memory footprint (or byte length) of a map

如果您需要实"数,则可以使用Go的测试工具,该工具还可以执行内存基准测试.传递-benchmem参数,并在基准函数内仅分配要测量的内存:

If you want "real" numbers, you may take advantage of the testing tool of Go, which can also perform memory benchmarking. Pass the -benchmem argument, and inside the benchmark function allocate only whose memory you want to measure:

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()中删除计时和打印呼叫.)

(Remove the timing and printing calls from getSlice() and getMap() of course.)

运行

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告诉每个操作发生了多少(不同的)内存分配.

B/op values tell you how many bytes were allocated per op. allocs/op tells how many (distinct) memory allocations occurred per op.

在我的64位体系结构(int的大小为8个字节)上,它告诉您具有2000个元素的切片的大小大约为16 KB(与2000 * 8字节一致).具有1000个int-int对的地图大约需要分配42 KB.

On my 64-bit architecture (where the size of int is 8 bytes) it tells that the size of a slice having 2000 elements is roughly 16 KB (in line with 2000 * 8 bytes). A map with 1000 int-int pairs required approximately to allocate 42 KB.

这篇关于如何在Go中获取变量的内存大小?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆