Source file
src/runtime/slice_test.go
1
2
3
4
5 package runtime_test
6
7 import (
8 "fmt"
9 "testing"
10 )
11
12 const N = 20
13
14 func BenchmarkMakeSliceCopy(b *testing.B) {
15 const length = 32
16 var bytes = make([]byte, 8*length)
17 var ints = make([]int, length)
18 var ptrs = make([]*byte, length)
19 b.Run("mallocmove", func(b *testing.B) {
20 b.Run("Byte", func(b *testing.B) {
21 var x []byte
22 for i := 0; i < b.N; i++ {
23 x = make([]byte, len(bytes))
24 copy(x, bytes)
25 }
26 })
27 b.Run("Int", func(b *testing.B) {
28 var x []int
29 for i := 0; i < b.N; i++ {
30 x = make([]int, len(ints))
31 copy(x, ints)
32 }
33 })
34 b.Run("Ptr", func(b *testing.B) {
35 var x []*byte
36 for i := 0; i < b.N; i++ {
37 x = make([]*byte, len(ptrs))
38 copy(x, ptrs)
39 }
40
41 })
42 })
43 b.Run("makecopy", func(b *testing.B) {
44 b.Run("Byte", func(b *testing.B) {
45 var x []byte
46 for i := 0; i < b.N; i++ {
47 x = make([]byte, 8*length)
48 copy(x, bytes)
49 }
50 })
51 b.Run("Int", func(b *testing.B) {
52 var x []int
53 for i := 0; i < b.N; i++ {
54 x = make([]int, length)
55 copy(x, ints)
56 }
57 })
58 b.Run("Ptr", func(b *testing.B) {
59 var x []*byte
60 for i := 0; i < b.N; i++ {
61 x = make([]*byte, length)
62 copy(x, ptrs)
63 }
64
65 })
66 })
67 b.Run("nilappend", func(b *testing.B) {
68 b.Run("Byte", func(b *testing.B) {
69 var x []byte
70 for i := 0; i < b.N; i++ {
71 x = append([]byte(nil), bytes...)
72 _ = x
73 }
74 })
75 b.Run("Int", func(b *testing.B) {
76 var x []int
77 for i := 0; i < b.N; i++ {
78 x = append([]int(nil), ints...)
79 _ = x
80 }
81 })
82 b.Run("Ptr", func(b *testing.B) {
83 var x []*byte
84 for i := 0; i < b.N; i++ {
85 x = append([]*byte(nil), ptrs...)
86 _ = x
87 }
88 })
89 })
90 }
91
92 type (
93 struct24 struct{ a, b, c int64 }
94 struct32 struct{ a, b, c, d int64 }
95 struct40 struct{ a, b, c, d, e int64 }
96 )
97
98 func BenchmarkMakeSlice(b *testing.B) {
99 const length = 2
100 b.Run("Byte", func(b *testing.B) {
101 var x []byte
102 for i := 0; i < b.N; i++ {
103 x = make([]byte, length, 2*length)
104 _ = x
105 }
106 })
107 b.Run("Int16", func(b *testing.B) {
108 var x []int16
109 for i := 0; i < b.N; i++ {
110 x = make([]int16, length, 2*length)
111 _ = x
112 }
113 })
114 b.Run("Int", func(b *testing.B) {
115 var x []int
116 for i := 0; i < b.N; i++ {
117 x = make([]int, length, 2*length)
118 _ = x
119 }
120 })
121 b.Run("Ptr", func(b *testing.B) {
122 var x []*byte
123 for i := 0; i < b.N; i++ {
124 x = make([]*byte, length, 2*length)
125 _ = x
126 }
127 })
128 b.Run("Struct", func(b *testing.B) {
129 b.Run("24", func(b *testing.B) {
130 var x []struct24
131 for i := 0; i < b.N; i++ {
132 x = make([]struct24, length, 2*length)
133 _ = x
134 }
135 })
136 b.Run("32", func(b *testing.B) {
137 var x []struct32
138 for i := 0; i < b.N; i++ {
139 x = make([]struct32, length, 2*length)
140 _ = x
141 }
142 })
143 b.Run("40", func(b *testing.B) {
144 var x []struct40
145 for i := 0; i < b.N; i++ {
146 x = make([]struct40, length, 2*length)
147 _ = x
148 }
149 })
150
151 })
152 }
153
154 func BenchmarkGrowSlice(b *testing.B) {
155 b.Run("Byte", func(b *testing.B) {
156 x := make([]byte, 9)
157 for i := 0; i < b.N; i++ {
158 _ = append([]byte(nil), x...)
159 }
160 })
161 b.Run("Int16", func(b *testing.B) {
162 x := make([]int16, 9)
163 for i := 0; i < b.N; i++ {
164 _ = append([]int16(nil), x...)
165 }
166 })
167 b.Run("Int", func(b *testing.B) {
168 x := make([]int, 9)
169 for i := 0; i < b.N; i++ {
170 _ = append([]int(nil), x...)
171 }
172 })
173 b.Run("Ptr", func(b *testing.B) {
174 x := make([]*byte, 9)
175 for i := 0; i < b.N; i++ {
176 _ = append([]*byte(nil), x...)
177 }
178 })
179 b.Run("Struct", func(b *testing.B) {
180 b.Run("24", func(b *testing.B) {
181 x := make([]struct24, 9)
182 for i := 0; i < b.N; i++ {
183 _ = append([]struct24(nil), x...)
184 }
185 })
186 b.Run("32", func(b *testing.B) {
187 x := make([]struct32, 9)
188 for i := 0; i < b.N; i++ {
189 _ = append([]struct32(nil), x...)
190 }
191 })
192 b.Run("40", func(b *testing.B) {
193 x := make([]struct40, 9)
194 for i := 0; i < b.N; i++ {
195 _ = append([]struct40(nil), x...)
196 }
197 })
198
199 })
200 }
201
202 var (
203 SinkIntSlice []int
204 SinkIntPointerSlice []*int
205 )
206
207 func BenchmarkExtendSlice(b *testing.B) {
208 var length = 4
209 b.Run("IntSlice", func(b *testing.B) {
210 s := make([]int, 0, length)
211 for i := 0; i < b.N; i++ {
212 s = append(s[:0:length/2], make([]int, length)...)
213 }
214 SinkIntSlice = s
215 })
216 b.Run("PointerSlice", func(b *testing.B) {
217 s := make([]*int, 0, length)
218 for i := 0; i < b.N; i++ {
219 s = append(s[:0:length/2], make([]*int, length)...)
220 }
221 SinkIntPointerSlice = s
222 })
223 b.Run("NoGrow", func(b *testing.B) {
224 s := make([]int, 0, length)
225 for i := 0; i < b.N; i++ {
226 s = append(s[:0:length], make([]int, length)...)
227 }
228 SinkIntSlice = s
229 })
230 }
231
232 func BenchmarkAppend(b *testing.B) {
233 b.StopTimer()
234 x := make([]int, 0, N)
235 b.StartTimer()
236 for i := 0; i < b.N; i++ {
237 x = x[0:0]
238 for j := 0; j < N; j++ {
239 x = append(x, j)
240 }
241 }
242 }
243
244 func BenchmarkAppendGrowByte(b *testing.B) {
245 for i := 0; i < b.N; i++ {
246 var x []byte
247 for j := 0; j < 1<<20; j++ {
248 x = append(x, byte(j))
249 }
250 }
251 }
252
253 func BenchmarkAppendGrowString(b *testing.B) {
254 var s string
255 for i := 0; i < b.N; i++ {
256 var x []string
257 for j := 0; j < 1<<20; j++ {
258 x = append(x, s)
259 }
260 }
261 }
262
263 func BenchmarkAppendSlice(b *testing.B) {
264 for _, length := range []int{1, 4, 7, 8, 15, 16, 32} {
265 b.Run(fmt.Sprint(length, "Bytes"), func(b *testing.B) {
266 x := make([]byte, 0, N)
267 y := make([]byte, length)
268 for i := 0; i < b.N; i++ {
269 x = x[0:0]
270 x = append(x, y...)
271 }
272 })
273 }
274 }
275
276 var (
277 blackhole []byte
278 )
279
280 func BenchmarkAppendSliceLarge(b *testing.B) {
281 for _, length := range []int{1 << 10, 4 << 10, 16 << 10, 64 << 10, 256 << 10, 1024 << 10} {
282 y := make([]byte, length)
283 b.Run(fmt.Sprint(length, "Bytes"), func(b *testing.B) {
284 for i := 0; i < b.N; i++ {
285 blackhole = nil
286 blackhole = append(blackhole, y...)
287 }
288 })
289 }
290 }
291
292 func BenchmarkAppendStr(b *testing.B) {
293 for _, str := range []string{
294 "1",
295 "1234",
296 "12345678",
297 "1234567890123456",
298 "12345678901234567890123456789012",
299 } {
300 b.Run(fmt.Sprint(len(str), "Bytes"), func(b *testing.B) {
301 x := make([]byte, 0, N)
302 for i := 0; i < b.N; i++ {
303 x = x[0:0]
304 x = append(x, str...)
305 }
306 })
307 }
308 }
309
310 func BenchmarkAppendSpecialCase(b *testing.B) {
311 b.StopTimer()
312 x := make([]int, 0, N)
313 b.StartTimer()
314 for i := 0; i < b.N; i++ {
315 x = x[0:0]
316 for j := 0; j < N; j++ {
317 if len(x) < cap(x) {
318 x = x[:len(x)+1]
319 x[len(x)-1] = j
320 } else {
321 x = append(x, j)
322 }
323 }
324 }
325 }
326
327 var x []int
328
329 func f() int {
330 x[:1][0] = 3
331 return 2
332 }
333
334 func TestSideEffectOrder(t *testing.T) {
335 x = make([]int, 0, 10)
336 x = append(x, 1, f())
337 if x[0] != 1 || x[1] != 2 {
338 t.Error("append failed: ", x[0], x[1])
339 }
340 }
341
342 func TestAppendOverlap(t *testing.T) {
343 x := []byte("1234")
344 x = append(x[1:], x...)
345 got := string(x)
346 want := "2341234"
347 if got != want {
348 t.Errorf("overlap failed: got %q want %q", got, want)
349 }
350 }
351
352 func BenchmarkCopy(b *testing.B) {
353 for _, l := range []int{1, 2, 4, 8, 12, 16, 32, 128, 1024} {
354 buf := make([]byte, 4096)
355 b.Run(fmt.Sprint(l, "Byte"), func(b *testing.B) {
356 s := make([]byte, l)
357 var n int
358 for i := 0; i < b.N; i++ {
359 n = copy(buf, s)
360 }
361 b.SetBytes(int64(n))
362 })
363 b.Run(fmt.Sprint(l, "String"), func(b *testing.B) {
364 s := string(make([]byte, l))
365 var n int
366 for i := 0; i < b.N; i++ {
367 n = copy(buf, s)
368 }
369 b.SetBytes(int64(n))
370 })
371 }
372 }
373
374 var (
375 sByte []byte
376 s1Ptr []uintptr
377 s2Ptr [][2]uintptr
378 s3Ptr [][3]uintptr
379 s4Ptr [][4]uintptr
380 )
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396 func BenchmarkAppendInPlace(b *testing.B) {
397 b.Run("NoGrow", func(b *testing.B) {
398 const C = 128
399
400 b.Run("Byte", func(b *testing.B) {
401 for i := 0; i < b.N; i++ {
402 sByte = make([]byte, C)
403 for j := 0; j < C; j++ {
404 sByte = append(sByte, 0x77)
405 }
406 }
407 })
408
409 b.Run("1Ptr", func(b *testing.B) {
410 for i := 0; i < b.N; i++ {
411 s1Ptr = make([]uintptr, C)
412 for j := 0; j < C; j++ {
413 s1Ptr = append(s1Ptr, 0x77)
414 }
415 }
416 })
417
418 b.Run("2Ptr", func(b *testing.B) {
419 for i := 0; i < b.N; i++ {
420 s2Ptr = make([][2]uintptr, C)
421 for j := 0; j < C; j++ {
422 s2Ptr = append(s2Ptr, [2]uintptr{0x77, 0x88})
423 }
424 }
425 })
426
427 b.Run("3Ptr", func(b *testing.B) {
428 for i := 0; i < b.N; i++ {
429 s3Ptr = make([][3]uintptr, C)
430 for j := 0; j < C; j++ {
431 s3Ptr = append(s3Ptr, [3]uintptr{0x77, 0x88, 0x99})
432 }
433 }
434 })
435
436 b.Run("4Ptr", func(b *testing.B) {
437 for i := 0; i < b.N; i++ {
438 s4Ptr = make([][4]uintptr, C)
439 for j := 0; j < C; j++ {
440 s4Ptr = append(s4Ptr, [4]uintptr{0x77, 0x88, 0x99, 0xAA})
441 }
442 }
443 })
444
445 })
446
447 b.Run("Grow", func(b *testing.B) {
448 const C = 5
449
450 b.Run("Byte", func(b *testing.B) {
451 for i := 0; i < b.N; i++ {
452 sByte = make([]byte, 0)
453 for j := 0; j < C; j++ {
454 sByte = append(sByte, 0x77)
455 sByte = sByte[:cap(sByte)]
456 }
457 }
458 })
459
460 b.Run("1Ptr", func(b *testing.B) {
461 for i := 0; i < b.N; i++ {
462 s1Ptr = make([]uintptr, 0)
463 for j := 0; j < C; j++ {
464 s1Ptr = append(s1Ptr, 0x77)
465 s1Ptr = s1Ptr[:cap(s1Ptr)]
466 }
467 }
468 })
469
470 b.Run("2Ptr", func(b *testing.B) {
471 for i := 0; i < b.N; i++ {
472 s2Ptr = make([][2]uintptr, 0)
473 for j := 0; j < C; j++ {
474 s2Ptr = append(s2Ptr, [2]uintptr{0x77, 0x88})
475 s2Ptr = s2Ptr[:cap(s2Ptr)]
476 }
477 }
478 })
479
480 b.Run("3Ptr", func(b *testing.B) {
481 for i := 0; i < b.N; i++ {
482 s3Ptr = make([][3]uintptr, 0)
483 for j := 0; j < C; j++ {
484 s3Ptr = append(s3Ptr, [3]uintptr{0x77, 0x88, 0x99})
485 s3Ptr = s3Ptr[:cap(s3Ptr)]
486 }
487 }
488 })
489
490 b.Run("4Ptr", func(b *testing.B) {
491 for i := 0; i < b.N; i++ {
492 s4Ptr = make([][4]uintptr, 0)
493 for j := 0; j < C; j++ {
494 s4Ptr = append(s4Ptr, [4]uintptr{0x77, 0x88, 0x99, 0xAA})
495 s4Ptr = s4Ptr[:cap(s4Ptr)]
496 }
497 }
498 })
499
500 })
501 }
502
View as plain text