How much memory do golang maps reserve?

huangapple go评论76阅读模式
英文:

How much memory do golang maps reserve?

问题

给定一个未指定初始空间的映射分配,例如:

foo := make(map[string]int)

文档建议这里的内存分配是依赖于实现的。那么,(如何)我可以知道我的实现为这个映射分配了多少内存?

英文:

Given a map allocation where the initial space is not specified, for example:

foo := make(map[string]int)

The documentation suggests that the memory allocation here is implementation dependent. So (how) can I tell how much memory my implementation is allocating to this map?

答案1

得分: 17

如果你查看Go语言的map类型的源代码,你会发现一个map由一个头部(类型为hmap)和一个桶数组(类型为bmap)组成。当你创建一个新的map并且没有指定初始空间(hint),只会创建一个桶。

头部由几个字段组成:

  • 1个int
  • 2个uint8
  • 1个uint16
  • 1个uint32
  • 2个unsafe.Pointer
  • 1个uintptr

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

一个桶由一个8个uint8的数组组成。

这总共占用40 + 8 = 48字节(64位架构)。

英文:

If you look at the source of Go's map type, you will see, that a map consists of a header (type hmap) and an array of buckets (type bmap). When you create a new map and don't specify the initial space (hint), only one bucket is created.

A header consists of several fields:

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

Size of the types int, uintptr, and unsafe.Pointer equals the size of a word (8 bytes on 64 bit machines).

A bucket consists of an array of 8 * uint8.

This gives a total of 40 + 8 = 48 bytes (64 bit architecture)

答案2

得分: 15

你可以使用Go测试工具来测量任意复杂数据结构的大小。这在这个回答中有详细说明:https://stackoverflow.com/questions/44257522/how-to-get-variable-memory-size-of-variable-in-golang/44258164#44258164

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

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类型的map现在需要4176字节(在64位架构上)。

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

英文:

You may use the Go testing tool to measure size of arbitrary complex data structures. This is detailed in this answer: https://stackoverflow.com/questions/44257522/how-to-get-variable-memory-size-of-variable-in-golang/44258164#44258164

To measure the size of a map created by make(map[string]int), use the following benchmark function:

var x map[string]int

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

Executing with

go test -bench . -benchmem

The result is:

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

So the answer is on my 64-bit architecture: 48 bytes.

As hinted, size may depend on architecture. Also size may depend on the initial capacity you may pass to make(), as you can see in this example:

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

Output:

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

A map of type map[string]int with an initial capacity of 100 now requires 4176 bytes (on 64-bit arch).

The default initial capacity is around 7 if not specified explicitly.

答案3

得分: 0

我遇到了相同的需求,并最终在unsafe的帮助下完成了它,你可以查看MapSize,但值得注意的是它并不完全准确。

英文:

I encountered the same requirement, and finally I did it with the help of unsafe, and you can look at MapSize, but it's worth noting that it's not entirely accurate.

huangapple
  • 本文由 发表于 2017年9月18日 19:17:32
  • 转载请务必保留本文链接:https://go.coder-hub.com/46278003.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定