Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/go/7.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Dictionary 如何获取Go中变量的内存大小?_Dictionary_Go_Memory_Slice - Fatal编程技术网

Dictionary 如何获取Go中变量的内存大小?

Dictionary 如何获取Go中变量的内存大小?,dictionary,go,memory,slice,Dictionary,Go,Memory,Slice,我很好奇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]

我很好奇
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))
}
func getSlice(size int)[]int{
t:=时间。现在()
s:=make([]整数,大小*2)
对于i:=0;iindex:=i这是正确的方法,使用
unsafe.Sizeof(s)
。只是对于给定的类型(整数、字符串等),结果将保持不变,而不考虑确切的值

Sizeof接受任何类型的表达式x,并返回假设变量v的字节大小,就像v是通过var v=x声明的一样。该大小不包括x可能引用的任何内存。例如,如果x是一个片,Sizeof返回片描述符的大小,而不是片引用的内存大小

参考资料

更新:

您可以使用编组,然后将字节中的值表示形式与
Size()
进行比较。只需将数据转换为字节字符串。

reflect.Type.Size()
只返回传递值的大小,而不递归遍历数据结构并添加指向值的大小

切片是一个相对简单的结构:,因为我们知道它引用了一个支持数组,所以我们可以轻松地“手动”计算它的大小,例如:

输出(在上尝试):

地图的数据结构要复杂得多,我不会详细介绍,但请查看以下问题和答案:

计算任何变量或结构的大小(递归) 如果您想要“真实”数字,您可以利用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) }
}
输出为:

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
值告诉您每个op分配了多少字节。
allocs/op
告诉您每个op分配了多少(不同的)内存


在我的64位体系结构(其中
int
的大小为8字节)上,它告诉我们一个包含2000个元素的片的大小大约为16KB(与2000*8字节一致).1000对
int
的映射大约需要分配42 KB。

这会产生一些封送开销,但我发现这是运行时获取go中值大小的最简单方法。对于我的需要,封送开销不是一个大问题,所以我选择了这条路线

func getRealSizeOf(v接口{})(int,错误){
b:=新(字节.缓冲区)
如果错误:=gob.NewEncoder(b).Encode(v);错误!=nil{
返回0,错误
}
返回b.Len(),nil
}

那么,在我的情况下,如何获得真实的大小呢?这将导致编组开销。不知道是否有一种方法可以不用编组就完成。不需要这样做,因为您可以计算所需的空间:将切片的cap与每个元素的大小相乘。对于贴图来说,由于无法访问某些interna,这将更加困难(例如散列冲突)但基本上是相同的。
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) }
}
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