Этот вопрос касается скорости элементов доступа массивов и срезов, а не эффективности их передачи в функции в качестве аргументов.Array vs Slice: скорость доступа
Я бы ожидать массивов быть быстрее, чем ломтиков в большинстве случаев, так как срез представляет собой структуру данных, описывающая непрерывную секцию массива и поэтому может быть дополнительным шагом участвовать при доступе к элементам среза (косвенно - элементы его базового массива).
Итак, я написал небольшой тест, чтобы сравнить партию простых операций. Есть 4 эталонных функций, первые 2 испытания на глобальный срезе и глобальный массив, другие 2 теста местный среза и локальный массив:
var gs = make([]byte, 1000) // Global slice
var ga [1000]byte // Global array
func BenchmarkSliceGlobal(b *testing.B) {
for i := 0; i < b.N; i++ {
for j, v := range gs {
gs[j]++; gs[j] = gs[j] + v + 10; gs[j] += v
}
}
}
func BenchmarkArrayGlobal(b *testing.B) {
for i := 0; i < b.N; i++ {
for j, v := range ga {
ga[j]++; ga[j] = ga[j] + v + 10; ga[j] += v
}
}
}
func BenchmarkSliceLocal(b *testing.B) {
var s = make([]byte, 1000)
for i := 0; i < b.N; i++ {
for j, v := range s {
s[j]++; s[j] = s[j] + v + 10; s[j] += v
}
}
}
func BenchmarkArrayLocal(b *testing.B) {
var a [1000]byte
for i := 0; i < b.N; i++ {
for j, v := range a {
a[j]++; a[j] = a[j] + v + 10; a[j] += v
}
}
}
Я побежал тест несколько раз, здесь типичный выход (go test -bench .*
):
BenchmarkSliceGlobal 300000 4210 ns/op
BenchmarkArrayGlobal 300000 4123 ns/op
BenchmarkSliceLocal 500000 3090 ns/op
BenchmarkArrayLocal 500000 3768 ns/op
Анализ результатов:
Доступ к Glob аль ломтик немного медленнее, чем доступ в глобальный массив, который, как я ожидал:
4210
против 4123
нс/оп
Но доступ к локальному кусочком значительно быстрее, чем доступ к локальному массив:
3090
против 3768
нс/оп
Мой вопрос: В чем причина этого?
Примечания
Я пытался варьируя следующие вещи, но никто не изменил результат:
- размер массива/секции (пытался 100, 1000, 10000)
- заказ контрольных функций
- тип элемента массива/среза (исп.
byte
иint
)
Существует несколько факторов, которые влияют на такие микро-контрольные показатели: проверка границ, распределение (куча, стек), генерация кода, оптимизация заглавных букв и т. Д. Посмотрите на сгенерированный сборник в разных условиях, таких как отключенная проверка привязки или отключенная оптимизация. – Volker
Интересно, что если вы добавите [указатель на массив] (http://play.golang.org/p/nyynQgndDl) к эталонам, вы увидите, что они выполняют примерно так же, как срезы. –