当前位置: 首页 > 面试题库 >

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

仲孙宇定
2023-03-14
问题内容

我对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。



 类似资料:
  • 问题内容: 有谁知道如何获得变量(内存大小,,等),并打印出来?可能吗? 问题答案: 您可以为此使用unsafe.Sizeof函数。它返回以字节为单位的大小,该大小由您传递给它的值占据。这是一个工作示例: 请注意,某些平台明确禁止使用不安全,因为它是不安全的。这曾经包括AppEngine。不知道今天是否仍然如此,但我想是这样。 正如@Timur Fayzrakhmanov指出的那样,它将为您提供相

  • 问题内容: 在Linux中,如何获取URL并在shell脚本的变量中获取其内容? 问题答案: 您可以使用命令下载页面并将其读取为变量,如下所示: 我们使用的选项允许我们指定将页面内容转储到的文件的名称。我们指定将转储放入标准输出并将其收集到变量中。您可以添加安静选项以关闭wget输出。 您还可以为此使用curl命令: 我们需要使用该选项,因为我们请求的页面可能已经移动。在这种情况下,我们需要从新位

  • 问题内容: 我想将内容放入javascript全局定义的变量中,我使用ajax call获得的内容。 http://pastebin.com/TqiJx3PA 感谢您的任何建议 问题答案: pastebin代码已经做到了。我猜您实际上面临的问题是存在的,因为您的ajax调用是 异步的 ,这意味着您正在(异步)发出ajax请求,并立即尝试访问全局变量中的值-但它尚未尚未设定。 解决方案是在回调中执行

  • Swift中的静态变量是如何存储的? > 如果我从未调用func usesticvar(),会发生什么?这些变量是否已初始化? 如果我调用useStaticVar()然后再也不访问它们,会发生什么?应收账

  • 问题内容: 我想要可以使用PHP访问的JavaScript变量的值。我正在使用下面的代码,但它没有在PHP中返回该变量的值。 这给了我以下错误:- 我使用的另一个PHP代码给出了空值 当我回声时,它什么也没显示。 问题答案: 您将需要使用JS将其中包含变量的URL发送回去,例如:http : //www.site.com/index.php?uid=1 通过在JS中使用如下代码: 然后在PHP代码

  • 问题内容: Python中是否有内置方法来获取所有类的实例变量的数组?例如,如果我有以下代码: 有没有办法让我做到这一点: 编辑:我最初是错误地要求类变量。 问题答案: 每个对象都有一个包含所有变量及其值的变量。 尝试这个