golang maps 预留多少内存?

Posted

技术标签:

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

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

foo := make(map[string]int)

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

【问题讨论】:

【参考方案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 位架构)

【讨论】:

以上是关于golang maps 预留多少内存?的主要内容,如果未能解决你的问题,请参考以下文章

Golang源码学习:使用gdb调试探究Golang函数调用栈结构

golang map源码浅析

golang之map的声明

golang make()的第三个参数

Java map和golang map的一些点

golang快速入门数据类型特别之处(下)