【问题标题】:How much memory do golang maps reserve?golang maps 预留多少内存?
【发布时间】:2018-02-26 21:57:03
【问题描述】:

给定一个未指定初始space 的地图分配,例如:

foo := make(map[string]int)

documentation 表明这里的内存分配取决于实现。那么(如何)我可以知道我的实现分配了多少内存给这个映射?

【问题讨论】:

    标签: dictionary go heap-memory


    【解决方案1】:

    您可以使用 Go 测试工具来测量任意复杂数据结构的大小。此答案中对此进行了详细说明:How to get variable memory size of variable in golang?

    要测量make(map[string]int) 创建的地图的大小,请使用以下基准函数:

    var x map[string]int
    
    func BenchmarkEmptyMap(b *testing.B) {
        for i := 0; i < b.N; i++ {
            x = make(map[string]int)
        }
    }
    

    执行

    go test -bench . -benchmem
    

    结果是:

    BenchmarkEmptyMap-4     20000000   110 ns/op      48 B/op    1 allocs/op
    

    所以答案在我的 64 位架构上:48 字节

    如前所述,大小可能取决于架构。此外,大小可能取决于您可能传递给 make() 的初始容量,如您在此示例中所见:

    func BenchmarkEmptyMapCap100(b *testing.B) {
        for i := 0; i < b.N; i++ {
            x = make(map[string]int, 100)
        }
    }
    

    输出:

    BenchmarkEmptyMapCap100-4   1000000    1783 ns/op   4176 B/op    3 allocs/op
    

    初始容量为 100 的 map[string]int 类型的映射现在需要 4176 字节(在 64 位架构上)。

    如果未明确指定,默认初始容量约为 7。

    【讨论】:

    • 如果我分配一个大小为 1000 的映射,即使映射中的值少于 1000 个,映射的内存使用量会增加吗?我想确定地图的内存使用情况,或者至少确定一个上限。它是评估缓存的内存使用成本。
    • @chmike 这个答案为您提供了测试它的工具。你有没有尝试过?顺便说一句,是的,由于 hashmap 内部(存储桶的使用和分配),内存使用和分配可能会增加一点。但与整个地图的内存占用相比,这“微不足道”。
    【解决方案2】:

    如果你看一下 Go 的 map 类型的 source,你会看到,一个 map 由一个 header(type hmap)和一个 bucket 数组(type bmap)组成。当您创建新地图并且不指定初始空间 (hint) 时,只会创建一个存储桶。

    一个标头由几个字段组成:

    1 * int,
    2 * uint8,
    1 * uint16,
    1 * uint32,
    2 * unsafe.Pointer,
    1 * uintptr

    intuintptrunsafe.Pointer 类型的大小等于一个字的大小(在 64 位机器上为 8 个字节)。

    一个存储桶由 8 * uint8 的数组组成。

    这总共有 40 + 8 = 48 个字节(64 位架构)

    【讨论】:

      猜你喜欢
      • 2014-08-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-10-23
      • 1970-01-01
      相关资源
      最近更新 更多