Go Array vs Slice Benchmark

A benchmark to compare the performance of arrays, pre-allocated slices and dynamic slices.

Description:

This benchmark compares the performance of arrays, pre-allocated slices and dynamic slices. It shows that arrays are the fastest, but they are not very flexible. Pre-allocated slices are a good compromise between speed and flexibility. Dynamic slices are the slowest, but they are the most flexible.

Implementations

Green marks the fastest implementation, red marks the slowest

Comparison

This section compares the performance of Array vs Slice implementations with the functions: run

Different Run Count

Different CPU Core Count

Array

Arrays in Go are fixed-length sequences of elements of a single type.

Function ns/op ops/sec B/op allocs/op MB/s
run 83.00 19319693 0.0 0 0.0

Comparison

  • Array run is 98.37% faster than Dynamic Slice run.
  • Array run is 95.39% faster than Preallocated Slice run.
func BenchmarkArray_run(b *testing.B) {
	var arr [1000]int // Define an array of fixed size

	b.ResetTimer()

	for i := 0; i < 1_000; i++ {
		for j := range arr {
			arr[j] = i
		}

		arr = [1000]int{} // Reset the array
	}
}

Array run

ns/op ops/sec B/op allocs/op MB/s
83.00 19319693 0.0 0 0.0
By Run Count
By CPU Core Count

Dynamic Slice

Slices in Go are variable-length sequences of elements of a single type. They are built on top of arrays. Each time you append an element to a slice, the Go runtime checks if the underlying array is large enough to hold the new element. If it is not large enough, the runtime allocates a new array and copies the elements from the old array to the new one. This makes dynamic slices very flexible, but also slower.

Function ns/op ops/sec B/op allocs/op MB/s
run 5099.02 202924 25208.1 12 0.0

Comparison

  • Dynamic Slice run is 6043.18% slower than Array run.
  • Dynamic Slice run is 183.13% slower than Preallocated Slice run.
func BenchmarkDynamicSlice_run(b *testing.B) {
	var slice []int // Define a dynamic slice

	b.ResetTimer()

	for i := 0; i < b.N; i++ {
		for j := 0; j < 1000; j++ {
			slice = append(slice, i)
		}

		slice = []int{} // Reset the slice
	}
}

Dynamic Slice run

ns/op ops/sec B/op allocs/op MB/s
5099.02 202924 25208.1 12 0.0
By Run Count
By CPU Core Count

Preallocated Slice

Pre-allocated slices are slices, that have a fixed length and capacity. They are built on top of arrays. Each time you append an element to a pre-allocated slice, the Go runtime checks if the underlying array is large enough to hold the new element. If it is not large enough, the runtime allocates a new array and copies the elements from the old array to the new one. This makes pre-allocated slices very flexible, but also slower. The advantage of pre-allocated slices is, that you can pre-allocate the underlying array, so that the runtime does not need to allocate a new array each time you append an element. This makes pre-allocated slices faster than dynamic slices, but they are still slower than arrays.

Function ns/op ops/sec B/op allocs/op MB/s
run 1800.92 569692 8192.0 1 0.0

Comparison

  • Preallocated Slice run is 2069.71% slower than Array run.
  • Preallocated Slice run is 64.68% faster than Dynamic Slice run.
func BenchmarkPreallocatedSlice_run(b *testing.B) {
	slice := make([]int, 1000) // Define a slice with the same size as the array

	b.ResetTimer()

	for i := 0; i < b.N; i++ {
		for j := range slice {
			slice[j] = i
		}

		slice = make([]int, 1000) // Reset the slice
	}
}

Preallocated Slice run

ns/op ops/sec B/op allocs/op MB/s
1800.92 569692 8192.0 1 0.0
By Run Count
By CPU Core Count

Full Benchmark Code

func BenchmarkArray_run(b *testing.B) {
	var arr [1000]int // Define an array of fixed size

	b.ResetTimer()

	for i := 0; i < 1_000; i++ {
		for j := range arr {
			arr[j] = i
		}

		arr = [1000]int{} // Reset the array
	}
}

func BenchmarkDynamicSlice_run(b *testing.B) {
	var slice []int // Define a dynamic slice

	b.ResetTimer()

	for i := 0; i < b.N; i++ {
		for j := 0; j < 1000; j++ {
			slice = append(slice, i)
		}

		slice = []int{} // Reset the slice
	}
}

func BenchmarkPreallocatedSlice_run(b *testing.B) {
	slice := make([]int, 1000) // Define a slice with the same size as the array

	b.ResetTimer()

	for i := 0; i < b.N; i++ {
		for j := range slice {
			slice[j] = i
		}

		slice = make([]int, 1000) // Reset the slice
	}
}

Full Benchmark Output

Implementation Function Runs CPU Core Count ns/op ops/sec B/op allocs/op MB/s
Array run 1000 32 276.7 3614022.406938923 0 0 0
Array run 2000 32 138.3 7230657.989877079 0 0 0
Array run 3000 32 92.25 10840108.401084011 0 0 0
Array run 4000 32 69.17 14457134.595923088 0 0 0
Array run 5000 32 55.35 18066847.335140016 0 0 0
Array run 6000 32 49.65 20140986.90835851 0 0 0
Array run 7000 32 41.49 24102193.29959026 0 0 0
Array run 8000 32 34.89 28661507.595299512 0 0 0
Array run 9000 32 31.02 32237266.27981947 0 0 0
Array run 10000 32 27.67 36140224.06938923 0 0 0
Array run 1000 1 276.6 3615328.9949385393 0 0 0
Array run 2000 1 138.3 7230657.989877079 0 0 0
Array run 3000 1 106.6 9380863.039399626 0 0 0
Array run 4000 1 69.15 14461315.979754157 0 0 0
Array run 5000 1 55.32 18076644.9746927 0 0 0
Array run 6000 1 47.72 20955574.18273261 0 0 0
Array run 7000 1 46.02 21729682.746631898 0 0 0
Array run 8000 1 34.57 28926815.15765114 0 0 0
Array run 9000 1 30.73 32541490.400260333 0 0 0
Array run 10000 1 27.66 36153289.9493854 0 0 0
Array run 1000 8 304.1 3288391.9763235776 0 0 0
Array run 2000 8 138.3 7230657.989877079 0 0 0
Array run 3000 8 95.44 10477787.091366304 0 0 0
Array run 4000 8 71.36 14013452.914798206 0 0 0
Array run 5000 8 55.35 18066847.335140016 0 0 0
Array run 6000 8 48.78 20500205.00205002 0 0 0
Array run 7000 8 44.36 22542831.379621282 0 0 0
Array run 8000 8 34.6 28901734.10404624 0 0 0
Array run 9000 8 30.75 32520325.203252032 0 0 0
Array run 10000 8 29.05 34423407.91738382 0 0 0
Array run 1000 16 276.7 3614022.406938923 0 0 0
Array run 2000 16 138.3 7230657.989877079 0 0 0
Array run 3000 16 97.02 10307153.164296022 0 0 0
Array run 4000 16 69.19 14452955.629426219 0 0 0
Array run 5000 16 55.34 18070112.034694616 0 0 0
Array run 6000 16 46.12 21682567.21595837 0 0 0
Array run 7000 16 46.39 21556369.90730761 0 0 0
Array run 8000 16 36.23 27601435.274634283 0 0 0
Array run 9000 16 30.77 32499187.520311993 0 0 0
Array run 10000 16 27.67 36140224.06938923 0 0 0
Array run 1000 2 283.5 3527336.860670194 0 0 0
Array run 2000 2 138.3 7230657.989877079 0 0 0
Array run 3000 2 93.96 10642826.734780759 0 0 0
Array run 4000 2 69.16 14459224.985540776 0 0 0
Array run 5000 2 55.34 18070112.034694616 0 0 0
Array run 6000 2 46.11 21687269.57276079 0 0 0
Array run 7000 2 39.58 25265285.497726124 0 0 0
Array run 8000 2 34.59 28910089.621277824 0 0 0
Array run 9000 2 37.52 26652452.02558635 0 0 0
Array run 10000 2 27.67 36140224.06938923 0 0 0
Array run 1000 4 277 3610108.3032490974 0 0 0
Array run 2000 4 138.5 7220216.606498195 0 0 0
Array run 3000 4 96.09 10406910.188365074 0 0 0
Array run 4000 4 69.16 14459224.985540776 0 0 0
Array run 5000 4 62.37 16033349.3666827 0 0 0
Array run 6000 4 53.51 18688095.6830499 0 0 0
Array run 7000 4 39.53 25297242.600556538 0 0 0
Array run 8000 4 34.6 28901734.10404624 0 0 0
Array run 9000 4 30.74 32530904.359141186 0 0 0
Array run 10000 4 27.96 35765379.113018595 0 0 0
Dynamic Slice run 1000 2 5773 173220.16282695305 25208 12 0
Dynamic Slice run 2000 2 5607 178348.49295523454 25208 12 0
Dynamic Slice run 3000 2 5289 189071.65815844206 25208 12 0
Dynamic Slice run 4000 2 5694 175623.46329469618 25208 12 0
Dynamic Slice run 5000 2 5560 179856.11510791368 25208 12 0
Dynamic Slice run 6000 2 5245 190657.76930409914 25208 12 0
Dynamic Slice run 7000 2 5338 187336.08092918695 25208 12 0
Dynamic Slice run 8000 2 6378 156788.96205707118 25208 12 0
Dynamic Slice run 9000 2 5279 189429.81625307823 25208 12 0
Dynamic Slice run 10000 2 6157 162416.76140977748 25208 12 0
Dynamic Slice run 1000 32 4960 201612.90322580645 25208 12 0
Dynamic Slice run 2000 32 4618 216543.95842356 25208 12 0
Dynamic Slice run 3000 32 5013 199481.3484939158 25208 12 0
Dynamic Slice run 4000 32 4865 205549.84583761563 25208 12 0
Dynamic Slice run 5000 32 4894 204331.8348998774 25208 12 0
Dynamic Slice run 6000 32 4818 207555.00207555003 25208 12 0
Dynamic Slice run 7000 32 4625 216216.2162162162 25208 12 0
Dynamic Slice run 8000 32 5667 176460.20822304572 25208 12 0
Dynamic Slice run 9000 32 4973 201085.86366378443 25208 12 0
Dynamic Slice run 10000 32 5019 199242.87706714484 25208 12 0
Dynamic Slice run 1000 8 5637 177399.32588256165 25208 12 0
Dynamic Slice run 2000 8 5352 186846.03886397608 25209 12 0
Dynamic Slice run 3000 8 5346 187055.74261129816 25208 12 0
Dynamic Slice run 4000 8 5107 195809.6729978461 25208 12 0
Dynamic Slice run 5000 8 5363 186462.80067126607 25208 12 0
Dynamic Slice run 6000 8 5476 182615.04747991235 25208 12 0
Dynamic Slice run 7000 8 5384 185735.51263001485 25208 12 0
Dynamic Slice run 8000 8 6321 158202.81601012498 25208 12 0
Dynamic Slice run 9000 8 5589 178922.8842368939 25208 12 0
Dynamic Slice run 10000 8 6297 158805.7805304113 25208 12 0
Dynamic Slice run 1000 16 4991 200360.6491685033 25210 12 0
Dynamic Slice run 2000 16 4884 204750.20475020475 25208 12 0
Dynamic Slice run 3000 16 5284 189250.56775170326 25209 12 0
Dynamic Slice run 4000 16 4867 205465.3790836244 25209 12 0
Dynamic Slice run 5000 16 5014 199441.5636218588 25209 12 0
Dynamic Slice run 6000 16 4770 209643.60587002095 25208 12 0
Dynamic Slice run 7000 16 4866 205507.60378133992 25208 12 0
Dynamic Slice run 8000 16 6345 157604.41292356185 25208 12 0
Dynamic Slice run 9000 16 5329 187652.46762994933 25208 12 0
Dynamic Slice run 10000 16 6214 160926.939169617 25208 12 0
Dynamic Slice run 1000 1 4368 228937.72893772894 25208 12 0
Dynamic Slice run 2000 1 3438 290866.7830133799 25208 12 0
Dynamic Slice run 3000 1 3488 286697.247706422 25208 12 0
Dynamic Slice run 4000 1 3614 276701.7155506364 25208 12 0
Dynamic Slice run 5000 1 3252 307503.0750307503 25208 12 0
Dynamic Slice run 6000 1 3237 308928.0197713933 25208 12 0
Dynamic Slice run 7000 1 3495 286123.0329041488 25208 12 0
Dynamic Slice run 8000 1 3213 311235.60535325244 25208 12 0
Dynamic Slice run 9000 1 3463 288766.9650591972 25208 12 0
Dynamic Slice run 10000 1 3527 283527.0768358378 25208 12 0
Dynamic Slice run 1000 4 5688 175808.7201125176 25208 12 0
Dynamic Slice run 2000 4 5801 172384.07171177384 25208 12 0
Dynamic Slice run 3000 4 5098 196155.3550411926 25208 12 0
Dynamic Slice run 4000 4 5183 192938.45263360988 25208 12 0
Dynamic Slice run 5000 4 5739 174246.38438752395 25208 12 0
Dynamic Slice run 6000 4 5053 197902.23629527012 25208 12 0
Dynamic Slice run 7000 4 5384 185735.51263001485 25208 12 0
Dynamic Slice run 8000 4 6154 162495.93760155997 25208 12 0
Dynamic Slice run 9000 4 6406 156103.6528254761 25208 12 0
Dynamic Slice run 10000 4 6132 163078.93020221786 25208 12 0
Preallocated Slice run 1000 32 2062 484966.0523763337 8192 1 0
Preallocated Slice run 2000 32 1754 570125.4275940707 8192 1 0
Preallocated Slice run 3000 32 1829 546746.8562055768 8192 1 0
Preallocated Slice run 4000 32 1866 535905.6806002144 8192 1 0
Preallocated Slice run 5000 32 1741 574382.5387708214 8192 1 0
Preallocated Slice run 6000 32 2020 495049.50495049503 8192 1 0
Preallocated Slice run 7000 32 1756 569476.0820045559 8192 1 0
Preallocated Slice run 8000 32 2245 445434.29844097997 8192 1 0
Preallocated Slice run 9000 32 1739 575043.1282346176 8192 1 0
Preallocated Slice run 10000 32 1606 622665.0062266501 8192 1 0
Preallocated Slice run 1000 4 1743 573723.4652897303 8192 1 0
Preallocated Slice run 2000 4 1767 565930.9564233164 8192 1 0
Preallocated Slice run 3000 4 2144 466417.9104477612 8192 1 0
Preallocated Slice run 4000 4 1930 518134.71502590674 8192 1 0
Preallocated Slice run 5000 4 1754 570125.4275940707 8192 1 0
Preallocated Slice run 6000 4 1907 524383.8489774514 8192 1 0
Preallocated Slice run 7000 4 1974 506585.6129685917 8192 1 0
Preallocated Slice run 8000 4 1842 542888.1650380022 8192 1 0
Preallocated Slice run 9000 4 1822 548847.420417124 8192 1 0
Preallocated Slice run 10000 4 2123 471031.55911446066 8192 1 0
Preallocated Slice run 1000 8 1777 562746.2014631401 8192 1 0
Preallocated Slice run 2000 8 1984 504032.2580645161 8192 1 0
Preallocated Slice run 3000 8 1724 580046.403712297 8192 1 0
Preallocated Slice run 4000 8 2155 464037.12296983757 8192 1 0
Preallocated Slice run 5000 8 1752 570776.2557077626 8192 1 0
Preallocated Slice run 6000 8 2090 478468.8995215311 8192 1 0
Preallocated Slice run 7000 8 1829 546746.8562055768 8192 1 0
Preallocated Slice run 8000 8 1982 504540.86781029264 8192 1 0
Preallocated Slice run 9000 8 1903 525486.0746190225 8192 1 0
Preallocated Slice run 10000 8 2343 426803.2437046522 8192 1 0
Preallocated Slice run 1000 1 1544 647668.3937823834 8192 1 0
Preallocated Slice run 2000 1 1236 809061.4886731391 8192 1 0
Preallocated Slice run 3000 1 1424 702247.1910112359 8192 1 0
Preallocated Slice run 4000 1 1200 833333.3333333334 8192 1 0
Preallocated Slice run 5000 1 1459 685400.9595613434 8192 1 0
Preallocated Slice run 6000 1 1196 836120.4013377926 8192 1 0
Preallocated Slice run 7000 1 1237 808407.4373484236 8192 1 0
Preallocated Slice run 8000 1 1402 713266.7617689016 8192 1 0
Preallocated Slice run 9000 1 1206 829187.3963515755 8192 1 0
Preallocated Slice run 10000 1 1367 731528.895391368 8192 1 0
Preallocated Slice run 1000 2 1603 623830.3181534623 8192 1 0
Preallocated Slice run 2000 2 2081 480538.2027871216 8192 1 0
Preallocated Slice run 3000 2 1858 538213.1324004306 8192 1 0
Preallocated Slice run 4000 2 2034 491642.08456243854 8192 1 0
Preallocated Slice run 5000 2 1687 592768.2276229995 8192 1 0
Preallocated Slice run 6000 2 1992 502008.0321285141 8192 1 0
Preallocated Slice run 7000 2 2022 494559.84174085065 8192 1 0
Preallocated Slice run 8000 2 1963 509424.35048395314 8192 1 0
Preallocated Slice run 9000 2 1788 559284.1163310962 8192 1 0
Preallocated Slice run 10000 2 2105 475059.38242280285 8192 1 0
Preallocated Slice run 1000 16 1678 595947.5566150179 8192 1 0
Preallocated Slice run 2000 16 1822 548847.420417124 8192 1 0
Preallocated Slice run 3000 16 1804 554323.7250554324 8192 1 0
Preallocated Slice run 4000 16 2018 495540.1387512389 8192 1 0
Preallocated Slice run 5000 16 1567 638162.0931716656 8192 1 0
Preallocated Slice run 6000 16 2044 489236.7906066536 8192 1 0
Preallocated Slice run 7000 16 1729 578368.999421631 8192 1 0
Preallocated Slice run 8000 16 1975 506329.11392405065 8192 1 0
Preallocated Slice run 9000 16 1866 535905.6806002144 8192 1 0
Preallocated Slice run 10000 16 1985 503778.3375314861 8192 1 0