Ваши решения b
и c
идентичны: при создании среза с make()
, где вы не указываете емкость, «отсутствующая» емкость по умолчанию равна заданной длине.
Также обратите внимание, что если вы создаете срез с длиной заранее, вы не можете использовать append()
для заполнения среза, потому что он добавляет новые элементы ксрез, и он не «повторно» использовать выделенные элементы.Таким образом, в этом случае вы должны присвоить значения элементам, используя индексное выражение , например, myslice[i] = value
.
Если вы начинаете со среза с емкостью 0, новый резервный массив долженВы должны быть выделены, а «старый» контент должен копироваться всякий раз, когда вы добавляете элемент, который не вписывается в емкость, поэтому решение должно быть медленнее по своей природе.
Я бы определил и рассмотрел следующие различные решения (Iиспользуйте срез []int
, чтобы fmt.Sprintf()
не вмешивался в наши тесты и не мешал им):
var s []int
func BenchmarkA(b *testing.B) {
for i := 0; i < b.N; i++ {
s = nil
for j := 0; j < 1e5; j++ {
s = append(s, j)
}
}
}
func BenchmarkB(b *testing.B) {
for i := 0; i < b.N; i++ {
s = make([]int, 0, 1e5)
for j := 0; j < 1e5; j++ {
s = append(s, j)
}
}
}
func BenchmarkBLocal(b *testing.B) {
for i := 0; i < b.N; i++ {
s := make([]int, 0, 1e5)
for j := 0; j < 1e5; j++ {
s = append(s, j)
}
}
}
func BenchmarkD(b *testing.B) {
for i := 0; i < b.N; i++ {
s = make([]int, 1e5)
for j := range s {
s[j] = j
}
}
}
Примечание. Я использую переменные уровня пакета в тестах производительности (кроме BLocal
), поскольку некоторыеОптимизация может (и в действительности происходит) при использовании локальной переменной слайса).
И результаты теста:
BenchmarkA-4 1000 1081599 ns/op 4654332 B/op 30 allocs/op
BenchmarkB-4 3000 371096 ns/op 802816 B/op 1 allocs/op
BenchmarkBLocal-4 10000 172427 ns/op 802816 B/op 1 allocs/op
BenchmarkD-4 10000 167305 ns/op 802816 B/op 1 allocs/op
A
: Как вы можете видеть, начиная сnil
слайс является самым медленным, использует больше всего памяти и выделений.
B
: Предварительное выделение слайса с емкостью (но все равно 0 длиной) и использованием добавления: для этого требуется только не замужемвыделение и намного быстрее, почти в три раза быстрее .
BLocal
: обратите внимание, что при использовании локального слайса вместо переменной пакета (оптимизация компилятора) происходят оптимизации ион становится намного быстрее: в два раза быстрее, почти так же быстро, как D
.
D
: если не использовать append()
, но присвоение элементов предварительно выделенному слайсу выигрывает во всех аспектахдаже при использовании нелокальной переменной.