我正在深入研究go中优化一些高度使用的代码。我的问题归结为以下代码片段(使用pprof list命令的内存分配复制)。如您所见,所有分配都在填充地图的行中完成(第959行)。
ROUTINE ======================== cart.BenchmarkMapWithOutCapacityFixVal in /.../cart_test.go
3328966 3328966 (flat, cum) 15.50% of Total
. . 954:
. . 955:func BenchmarkMapWithOutCapacityFixVal(b *testing.B) {
. . 956: for i := 0; i < b.N; i++ {
. . 957: m := make(map[int]float32)
. . 958: for k := 0; k < 10; k++ {
3328966 3328966 959: m[k] = 0.434295723423
. . 960: }
. . 961: }
. . 962:}
这里我要做的是:我试图在(内部)循环之前分配内存,这样就不会发生不必要的分配:
ROUTINE ======================== cart.BenchmarkMapWithCapacityFixVal in /.../cart_test.go
3214263 3214263 (flat, cum) 14.97% of Total
. . 963:
. . 964:func BenchmarkMapWithCapacityFixVal(b *testing.B) {
. . 965: for i := 0; i < b.N; i++ {
3048075 3048075 966: m := make(map[int]float32, 10)
. . 967: for k := 0; k < 10; k++ {
166188 166188 968: m[k] = 0.434295723423
. . 969: }
. . 970: }
. . 971:}
为什么在第968行(第二个样本)中仍然会发生分配?如何在内循环之前正确分配地图?
答案 0 :(得分:8)
地图不是数组。您无法在其中预先分配空间,因为您无法知道要在地图中插入元素的位置。在make(map..., X)
X只是一个容量提示,它不绑定地图,绝对不能保证密钥完全散列到它中。因此,它会尽最大努力减少未来的分配数量,但没有办法消除所有分配。
在这个特定示例中,如果要完全控制分配,则应该使用数组而不是地图。使用正确的数组,您只需要一次分配。