在可能的情况下指定容器容量,以便预先为容器分配内存。这将在添加元素时,最小化后续分配(通过复制和调整容器大小)。
指定Map容器提示
在尽可能的情况下,在使用 make()
初始化的时候提供容量信息
make(map[T1]T2, hint)
为make()提供容量提示,试图在初始化时调整映射的大小,这减少了在元素添加到map时,增长map和分配的需要.
注意,与slices不同。map capacity提示并不保证完全的抢占式分配,而是用于估计所需的hashmap bucket的数量。 因此,在将元素添加到map时,甚至在指定map容量时,仍可能发生分配。
Bad
m := make(map[string]os.FileInfo)
files, _ := ioutil.ReadDir("./files")
for _, f := range files {
m[f.Name()] = f
}
m
是在没有大小提示的情况下创建的; 在运行时可能会有更多分配。
Good
files, _ := ioutil.ReadDir("./files")
m := make(map[string]os.FileInfo, len(files))
for _, f := range files {
m[f.Name()] = f
}
m
是有大小提示创建的;在运行时可能会有更少的分配。
指定切片容量
在尽可能的情况下,在使用make()
初始化切片时提供容量信息,特别是在追加切片时
make([]T, length, capacity)
与map不同的是,slice容量并不是一个提示:编译器将按照make()所提供的值为slice的容量分配足够的内存,这意味着后续的append()操作将导致零分配(直到切片的长度与容量匹配,在此之后,任何append操作都将需要重新调整大小以确保能够保存其他元素)。
Bad
for n := 0; n < b.N; n++ {
data := make([]int, 0)
for k := 0; k < size; k++{
data = append(data, k)
}
}
// BenchmarkBad-4 100000000 2.48s
Good
for n := 0; n < b.N; n++ {
data := make([]int, 0, size)
for k := 0; k < size; k++{
data = append(data, k)
}
}
// BenchmarkGood-4 100000000 0.21s