When creating an array in Go, it seems the array will always be zeroed, even if different values will be set right after the initialization, for example when the value should be set to the index in the array.
a = [5]int{0,1,2,3,4}
Surprisingly, the named return function outperforms the composite literal initialization for large arrays.
I've created the following benchmark to compare the performance:
package main
import "testing"
const N = 1000000
var result [N]int
func arrayLiteral() [N]int {
// Replace the 3 dots with the actual value
// I copy-pasted the output of an other program to do this
return [N]int{0,1,2,3,...,N-1}
}
func arrayLoopNamedReturn() (a [N]int) {
for i := 0; i < N; i++ {
a[i] = i
}
return
}
func arrayLoop() [N]int {
var a [N]int
for i := 0; i < N; i++ {
a[i] = i
}
return a
}
func BenchmarkArrayLoop(b *testing.B) {
var r [N]int
for n := 0; n < b.N; n++ {
r = arrayLoop()
}
result = r
}
func BenchmarkArrayLoopNamedReturn(b *testing.B) {
var r [N]int
for n := 0; n < b.N; n++ {
r = arrayLoopNamedReturn()
}
result = r
}
func BenchmarkArrayLiteral(b *testing.B) {
var r [N]int
for n := 0; n < b.N; n++ {
r = arrayLiteral()
}
result = r
}
Results:
N = 10,000
BenchmarkArrayLoop-8 200000 9041 ns/op
BenchmarkArrayLoopNamedReturn-8 200000 6327 ns/op
BenchmarkArrayLiteral-8 300000 4300 ns/op
N = 100,000
BenchmarkArrayLoop-8 10000 191582 ns/op
BenchmarkArrayLoopNamedReturn-8 20000 76125 ns/op
BenchmarkArrayLiteral-8 20000 62714 ns/op
N = 1,000,000
BenchmarkArrayLoop-8 500 2635713 ns/op
BenchmarkArrayLoopNamedReturn-8 1000 1537282 ns/op
BenchmarkArrayLiteral-8 1000 1854348 ns/op
Observations:
I did not expect that naming the return value would make a difference for the loop, I thought surely the compiler would do some optimization. For 1,000,000, it becomes faster than the literal initialization.
I expected a linear scaling, I do not understand why it is not the case, for either of the methods.
I'm not sure how to explain this, even though it seems to be extremely basic. Any ideas ?
Edit: There is an open issue on Github complaining that naming the return value should not make a difference. I also found this to be a surprising behavior.