英文:
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
类型int
、uintptr
和unsafe.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 < 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 < 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.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论