1 // Copyright 2011 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
13 func BenchmarkMakeSlice(b
*testing
.B
) {
15 for i
:= 0; i
< b
.N
; i
++ {
22 struct24
struct{ a
, b
, c
int64 }
23 struct32
struct{ a
, b
, c
, d
int64 }
24 struct40
struct{ a
, b
, c
, d
, e
int64 }
27 func BenchmarkGrowSlice(b
*testing
.B
) {
28 b
.Run("Byte", func(b
*testing
.B
) {
30 for i
:= 0; i
< b
.N
; i
++ {
31 _
= append([]byte(nil), x
...)
34 b
.Run("Int16", func(b
*testing
.B
) {
36 for i
:= 0; i
< b
.N
; i
++ {
37 _
= append([]int16(nil), x
...)
40 b
.Run("Int", func(b
*testing
.B
) {
42 for i
:= 0; i
< b
.N
; i
++ {
43 _
= append([]int(nil), x
...)
46 b
.Run("Ptr", func(b
*testing
.B
) {
48 for i
:= 0; i
< b
.N
; i
++ {
49 _
= append([]*byte(nil), x
...)
52 b
.Run("Struct", func(b
*testing
.B
) {
53 b
.Run("24", func(b
*testing
.B
) {
54 x
:= make([]struct24
, 9)
55 for i
:= 0; i
< b
.N
; i
++ {
56 _
= append([]struct24(nil), x
...)
59 b
.Run("32", func(b
*testing
.B
) {
60 x
:= make([]struct32
, 9)
61 for i
:= 0; i
< b
.N
; i
++ {
62 _
= append([]struct32(nil), x
...)
65 b
.Run("40", func(b
*testing
.B
) {
66 x
:= make([]struct40
, 9)
67 for i
:= 0; i
< b
.N
; i
++ {
68 _
= append([]struct40(nil), x
...)
77 SinkIntPointerSlice
[]*int
80 func BenchmarkExtendSlice(b
*testing
.B
) {
81 var length
= 4 // Use a variable to prevent stack allocation of slices.
82 b
.Run("IntSlice", func(b
*testing
.B
) {
83 s
:= make([]int, 0, length
)
84 for i
:= 0; i
< b
.N
; i
++ {
85 s
= append(s
[:0:length
/2], make([]int, length
)...)
89 b
.Run("PointerSlice", func(b
*testing
.B
) {
90 s
:= make([]*int, 0, length
)
91 for i
:= 0; i
< b
.N
; i
++ {
92 s
= append(s
[:0:length
/2], make([]*int, length
)...)
94 SinkIntPointerSlice
= s
96 b
.Run("NoGrow", func(b
*testing
.B
) {
97 s
:= make([]int, 0, length
)
98 for i
:= 0; i
< b
.N
; i
++ {
99 s
= append(s
[:0:length
], make([]int, length
)...)
105 func BenchmarkAppend(b
*testing
.B
) {
107 x
:= make([]int, 0, N
)
109 for i
:= 0; i
< b
.N
; i
++ {
111 for j
:= 0; j
< N
; j
++ {
117 func BenchmarkAppendGrowByte(b
*testing
.B
) {
118 for i
:= 0; i
< b
.N
; i
++ {
120 for j
:= 0; j
< 1<<20; j
++ {
121 x
= append(x
, byte(j
))
126 func BenchmarkAppendGrowString(b
*testing
.B
) {
128 for i
:= 0; i
< b
.N
; i
++ {
130 for j
:= 0; j
< 1<<20; j
++ {
136 func BenchmarkAppendSlice(b
*testing
.B
) {
137 for _
, length
:= range []int{1, 4, 7, 8, 15, 16, 32} {
138 b
.Run(fmt
.Sprint(length
, "Bytes"), func(b
*testing
.B
) {
139 x
:= make([]byte, 0, N
)
140 y
:= make([]byte, length
)
141 for i
:= 0; i
< b
.N
; i
++ {
153 func BenchmarkAppendSliceLarge(b
*testing
.B
) {
154 for _
, length
:= range []int{1 << 10, 4 << 10, 16 << 10, 64 << 10, 256 << 10, 1024 << 10} {
155 y
:= make([]byte, length
)
156 b
.Run(fmt
.Sprint(length
, "Bytes"), func(b
*testing
.B
) {
157 for i
:= 0; i
< b
.N
; i
++ {
159 blackhole
= append(blackhole
, y
...)
165 func BenchmarkAppendStr(b
*testing
.B
) {
166 for _
, str
:= range []string{
171 "12345678901234567890123456789012",
173 b
.Run(fmt
.Sprint(len(str
), "Bytes"), func(b
*testing
.B
) {
174 x
:= make([]byte, 0, N
)
175 for i
:= 0; i
< b
.N
; i
++ {
177 x
= append(x
, str
...)
183 func BenchmarkAppendSpecialCase(b
*testing
.B
) {
185 x
:= make([]int, 0, N
)
187 for i
:= 0; i
< b
.N
; i
++ {
189 for j
:= 0; j
< N
; j
++ {
207 func TestSideEffectOrder(t
*testing
.T
) {
208 x
= make([]int, 0, 10)
209 x
= append(x
, 1, f())
210 if x
[0] != 1 || x
[1] != 2 {
211 t
.Error("append failed: ", x
[0], x
[1])
215 func TestAppendOverlap(t
*testing
.T
) {
217 x
= append(x
[1:], x
...) // p > q in runtimeĀ·appendslice.
221 t
.Errorf("overlap failed: got %q want %q", got
, want
)
225 func BenchmarkCopy(b
*testing
.B
) {
226 for _
, l
:= range []int{1, 2, 4, 8, 12, 16, 32, 128, 1024} {
227 buf
:= make([]byte, 4096)
228 b
.Run(fmt
.Sprint(l
, "Byte"), func(b
*testing
.B
) {
231 for i
:= 0; i
< b
.N
; i
++ {
236 b
.Run(fmt
.Sprint(l
, "String"), func(b
*testing
.B
) {
237 s
:= string(make([]byte, l
))
239 for i
:= 0; i
< b
.N
; i
++ {
255 // BenchmarkAppendInPlace tests the performance of append
256 // when the result is being written back to the same slice.
257 // In order for the in-place optimization to occur,
258 // the slice must be referred to by address;
259 // using a global is an easy way to trigger that.
260 // We test the "grow" and "no grow" paths separately,
261 // but not the "normal" (occasionally grow) path,
262 // because it is a blend of the other two.
263 // We use small numbers and small sizes in an attempt
264 // to avoid benchmarking memory allocation and copying.
265 // We use scalars instead of pointers in an attempt
266 // to avoid benchmarking the write barriers.
267 // We benchmark four common sizes (byte, pointer, string/interface, slice),
268 // and one larger size.
269 func BenchmarkAppendInPlace(b
*testing
.B
) {
270 b
.Run("NoGrow", func(b
*testing
.B
) {
273 b
.Run("Byte", func(b
*testing
.B
) {
274 for i
:= 0; i
< b
.N
; i
++ {
275 sByte
= make([]byte, C
)
276 for j
:= 0; j
< C
; j
++ {
277 sByte
= append(sByte
, 0x77)
282 b
.Run("1Ptr", func(b
*testing
.B
) {
283 for i
:= 0; i
< b
.N
; i
++ {
284 s1Ptr
= make([]uintptr, C
)
285 for j
:= 0; j
< C
; j
++ {
286 s1Ptr
= append(s1Ptr
, 0x77)
291 b
.Run("2Ptr", func(b
*testing
.B
) {
292 for i
:= 0; i
< b
.N
; i
++ {
293 s2Ptr
= make([][2]uintptr, C
)
294 for j
:= 0; j
< C
; j
++ {
295 s2Ptr
= append(s2Ptr
, [2]uintptr{0x77, 0x88})
300 b
.Run("3Ptr", func(b
*testing
.B
) {
301 for i
:= 0; i
< b
.N
; i
++ {
302 s3Ptr
= make([][3]uintptr, C
)
303 for j
:= 0; j
< C
; j
++ {
304 s3Ptr
= append(s3Ptr
, [3]uintptr{0x77, 0x88, 0x99})
309 b
.Run("4Ptr", func(b
*testing
.B
) {
310 for i
:= 0; i
< b
.N
; i
++ {
311 s4Ptr
= make([][4]uintptr, C
)
312 for j
:= 0; j
< C
; j
++ {
313 s4Ptr
= append(s4Ptr
, [4]uintptr{0x77, 0x88, 0x99, 0xAA})
320 b
.Run("Grow", func(b
*testing
.B
) {
323 b
.Run("Byte", func(b
*testing
.B
) {
324 for i
:= 0; i
< b
.N
; i
++ {
325 sByte
= make([]byte, 0)
326 for j
:= 0; j
< C
; j
++ {
327 sByte
= append(sByte
, 0x77)
328 sByte
= sByte
[:cap(sByte
)]
333 b
.Run("1Ptr", func(b
*testing
.B
) {
334 for i
:= 0; i
< b
.N
; i
++ {
335 s1Ptr
= make([]uintptr, 0)
336 for j
:= 0; j
< C
; j
++ {
337 s1Ptr
= append(s1Ptr
, 0x77)
338 s1Ptr
= s1Ptr
[:cap(s1Ptr
)]
343 b
.Run("2Ptr", func(b
*testing
.B
) {
344 for i
:= 0; i
< b
.N
; i
++ {
345 s2Ptr
= make([][2]uintptr, 0)
346 for j
:= 0; j
< C
; j
++ {
347 s2Ptr
= append(s2Ptr
, [2]uintptr{0x77, 0x88})
348 s2Ptr
= s2Ptr
[:cap(s2Ptr
)]
353 b
.Run("3Ptr", func(b
*testing
.B
) {
354 for i
:= 0; i
< b
.N
; i
++ {
355 s3Ptr
= make([][3]uintptr, 0)
356 for j
:= 0; j
< C
; j
++ {
357 s3Ptr
= append(s3Ptr
, [3]uintptr{0x77, 0x88, 0x99})
358 s3Ptr
= s3Ptr
[:cap(s3Ptr
)]
363 b
.Run("4Ptr", func(b
*testing
.B
) {
364 for i
:= 0; i
< b
.N
; i
++ {
365 s4Ptr
= make([][4]uintptr, 0)
366 for j
:= 0; j
< C
; j
++ {
367 s4Ptr
= append(s4Ptr
, [4]uintptr{0x77, 0x88, 0x99, 0xAA})
368 s4Ptr
= s4Ptr
[:cap(s4Ptr
)]