title: Array vs Slice: accessing speed
body: <p>This question is about the speed of <em>accessing elements</em> of arrays and slices, not about the efficiency of passing them to functions as arguments.</p>
  
  <p>I would expect <strong>arrays</strong> to be faster than <strong>slices</strong> in most cases because a slice is a data structure describing a contiguous section of an array and so there may be an extra step involved when accessing elements of a slice (indirectly the elements of its underlying array).</p>
  
  <p>So I wrote a little test to benchmark a batch of simple operations. There are 4 benchmark functions, the first 2 test a <strong>global</strong> slice and a global array, the other 2 test a <strong>local</strong> slice and a local array:</p>
  
  <pre><code>var gs = make([]byte, 1000) // Global slice
  var ga [1000]byte           // Global array
  
  func BenchmarkSliceGlobal(b *testing.B) {
      for i := 0; i &lt; 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 &lt; 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 &lt; 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 &lt; b.N; i++ {
          for j, v := range a {
              a[j]++; a[j] = a[j] + v + 10; a[j] += v
          }
      }
  }
  </code></pre>
  
  <p>I ran the test multiple times, here is the typical output (<code>go test -bench .*</code>):</p>
  
  <pre><code>BenchmarkSliceGlobal      300000              4210 ns/op
  BenchmarkArrayGlobal      300000              4123 ns/op
  BenchmarkSliceLocal       500000              3090 ns/op
  BenchmarkArrayLocal       500000              3768 ns/op
  </code></pre>
  
  <p><strong>Analyzing the results:</strong></p>
  
  <p>Accessing the global slice is slightly slower than accessing the global array which is as I expected:<br>
  <code>4210</code> vs <code>4123</code> ns/op</p>
  
  <p>But accessing the local slice is significantly faster than accessing the local array:<br>
  <code>3090</code> vs <code>3768</code> ns/op</p>
  
  <p>My question is: <strong>What is the reason for this?</strong></p>
  
  <p><strong>Notes</strong></p>
  
  <p>I tried varying the following things but none changed the outcome:</p>
  
  <ul>
  <li>the size of the array/slice (tried 100, 1000, 10000)</li>
  <li>the order of the benchmark functions</li>
  <li>the element type of the array/slice (tried <code>byte</code> and <code>int</code>)</li>
  </ul>