2017-03-02 Richard Biener <rguenther@suse.de>
[official-gcc.git] / libgo / go / runtime / append_test.go
blob6bd8f3bd951fa6e8ded0576cfe8d08818e685ff8
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.
4 package runtime_test
6 import (
7 "fmt"
8 "testing"
11 const N = 20
13 func BenchmarkMakeSlice(b *testing.B) {
14 var x []byte
15 for i := 0; i < b.N; i++ {
16 x = make([]byte, 32)
17 _ = x
21 func BenchmarkGrowSliceBytes(b *testing.B) {
22 b.StopTimer()
23 var x = make([]byte, 9)
24 b.StartTimer()
25 for i := 0; i < b.N; i++ {
26 _ = append([]byte(nil), x...)
30 func BenchmarkGrowSliceInts(b *testing.B) {
31 b.StopTimer()
32 var x = make([]int, 9)
33 b.StartTimer()
34 for i := 0; i < b.N; i++ {
35 _ = append([]int(nil), x...)
39 func BenchmarkGrowSlicePtr(b *testing.B) {
40 b.StopTimer()
41 var x = make([]*byte, 9)
42 b.StartTimer()
43 for i := 0; i < b.N; i++ {
44 _ = append([]*byte(nil), x...)
48 type struct24 struct{ a, b, c int64 }
50 func BenchmarkGrowSliceStruct24Bytes(b *testing.B) {
51 b.StopTimer()
52 var x = make([]struct24, 9)
53 b.StartTimer()
54 for i := 0; i < b.N; i++ {
55 _ = append([]struct24(nil), x...)
59 func BenchmarkAppend(b *testing.B) {
60 b.StopTimer()
61 x := make([]int, 0, N)
62 b.StartTimer()
63 for i := 0; i < b.N; i++ {
64 x = x[0:0]
65 for j := 0; j < N; j++ {
66 x = append(x, j)
71 func BenchmarkAppendGrowByte(b *testing.B) {
72 for i := 0; i < b.N; i++ {
73 var x []byte
74 for j := 0; j < 1<<20; j++ {
75 x = append(x, byte(j))
80 func BenchmarkAppendGrowString(b *testing.B) {
81 var s string
82 for i := 0; i < b.N; i++ {
83 var x []string
84 for j := 0; j < 1<<20; j++ {
85 x = append(x, s)
90 func BenchmarkAppendSlice(b *testing.B) {
91 for _, length := range []int{1, 4, 7, 8, 15, 16, 32} {
92 b.Run(fmt.Sprint(length, "Bytes"), func(b *testing.B) {
93 x := make([]byte, 0, N)
94 y := make([]byte, length)
95 for i := 0; i < b.N; i++ {
96 x = x[0:0]
97 x = append(x, y...)
103 var (
104 blackhole []byte
107 func BenchmarkAppendSliceLarge(b *testing.B) {
108 for _, length := range []int{1 << 10, 4 << 10, 16 << 10, 64 << 10, 256 << 10, 1024 << 10} {
109 y := make([]byte, length)
110 b.Run(fmt.Sprint(length, "Bytes"), func(b *testing.B) {
111 for i := 0; i < b.N; i++ {
112 blackhole = nil
113 blackhole = append(blackhole, y...)
119 func BenchmarkAppendStr(b *testing.B) {
120 for _, str := range []string{
121 "1",
122 "1234",
123 "12345678",
124 "1234567890123456",
125 "12345678901234567890123456789012",
127 b.Run(fmt.Sprint(len(str), "Bytes"), func(b *testing.B) {
128 x := make([]byte, 0, N)
129 for i := 0; i < b.N; i++ {
130 x = x[0:0]
131 x = append(x, str...)
137 func BenchmarkAppendSpecialCase(b *testing.B) {
138 b.StopTimer()
139 x := make([]int, 0, N)
140 b.StartTimer()
141 for i := 0; i < b.N; i++ {
142 x = x[0:0]
143 for j := 0; j < N; j++ {
144 if len(x) < cap(x) {
145 x = x[:len(x)+1]
146 x[len(x)-1] = j
147 } else {
148 x = append(x, j)
154 var x []int
156 func f() int {
157 x[:1][0] = 3
158 return 2
161 func TestSideEffectOrder(t *testing.T) {
162 x = make([]int, 0, 10)
163 x = append(x, 1, f())
164 if x[0] != 1 || x[1] != 2 {
165 t.Error("append failed: ", x[0], x[1])
169 func TestAppendOverlap(t *testing.T) {
170 x := []byte("1234")
171 x = append(x[1:], x...) // p > q in runtimeĀ·appendslice.
172 got := string(x)
173 want := "2341234"
174 if got != want {
175 t.Errorf("overlap failed: got %q want %q", got, want)
179 func BenchmarkCopy(b *testing.B) {
180 for _, l := range []int{1, 2, 4, 8, 12, 16, 32, 128, 1024} {
181 buf := make([]byte, 4096)
182 b.Run(fmt.Sprint(l, "Byte"), func(b *testing.B) {
183 s := make([]byte, l)
184 var n int
185 for i := 0; i < b.N; i++ {
186 n = copy(buf, s)
188 b.SetBytes(int64(n))
190 b.Run(fmt.Sprint(l, "String"), func(b *testing.B) {
191 s := string(make([]byte, l))
192 var n int
193 for i := 0; i < b.N; i++ {
194 n = copy(buf, s)
196 b.SetBytes(int64(n))
201 var (
202 sByte []byte
203 s1Ptr []uintptr
204 s2Ptr [][2]uintptr
205 s3Ptr [][3]uintptr
206 s4Ptr [][4]uintptr
209 // BenchmarkAppendInPlace tests the performance of append
210 // when the result is being written back to the same slice.
211 // In order for the in-place optimization to occur,
212 // the slice must be referred to by address;
213 // using a global is an easy way to trigger that.
214 // We test the "grow" and "no grow" paths separately,
215 // but not the "normal" (occasionally grow) path,
216 // because it is a blend of the other two.
217 // We use small numbers and small sizes in an attempt
218 // to avoid benchmarking memory allocation and copying.
219 // We use scalars instead of pointers in an attempt
220 // to avoid benchmarking the write barriers.
221 // We benchmark four common sizes (byte, pointer, string/interface, slice),
222 // and one larger size.
223 func BenchmarkAppendInPlace(b *testing.B) {
224 b.Run("NoGrow", func(b *testing.B) {
225 const C = 128
227 b.Run("Byte", func(b *testing.B) {
228 for i := 0; i < b.N; i++ {
229 sByte = make([]byte, C)
230 for j := 0; j < C; j++ {
231 sByte = append(sByte, 0x77)
236 b.Run("1Ptr", func(b *testing.B) {
237 for i := 0; i < b.N; i++ {
238 s1Ptr = make([]uintptr, C)
239 for j := 0; j < C; j++ {
240 s1Ptr = append(s1Ptr, 0x77)
245 b.Run("2Ptr", func(b *testing.B) {
246 for i := 0; i < b.N; i++ {
247 s2Ptr = make([][2]uintptr, C)
248 for j := 0; j < C; j++ {
249 s2Ptr = append(s2Ptr, [2]uintptr{0x77, 0x88})
254 b.Run("3Ptr", func(b *testing.B) {
255 for i := 0; i < b.N; i++ {
256 s3Ptr = make([][3]uintptr, C)
257 for j := 0; j < C; j++ {
258 s3Ptr = append(s3Ptr, [3]uintptr{0x77, 0x88, 0x99})
263 b.Run("4Ptr", func(b *testing.B) {
264 for i := 0; i < b.N; i++ {
265 s4Ptr = make([][4]uintptr, C)
266 for j := 0; j < C; j++ {
267 s4Ptr = append(s4Ptr, [4]uintptr{0x77, 0x88, 0x99, 0xAA})
274 b.Run("Grow", func(b *testing.B) {
275 const C = 5
277 b.Run("Byte", func(b *testing.B) {
278 for i := 0; i < b.N; i++ {
279 sByte = make([]byte, 0)
280 for j := 0; j < C; j++ {
281 sByte = append(sByte, 0x77)
282 sByte = sByte[:cap(sByte)]
287 b.Run("1Ptr", func(b *testing.B) {
288 for i := 0; i < b.N; i++ {
289 s1Ptr = make([]uintptr, 0)
290 for j := 0; j < C; j++ {
291 s1Ptr = append(s1Ptr, 0x77)
292 s1Ptr = s1Ptr[:cap(s1Ptr)]
297 b.Run("2Ptr", func(b *testing.B) {
298 for i := 0; i < b.N; i++ {
299 s2Ptr = make([][2]uintptr, 0)
300 for j := 0; j < C; j++ {
301 s2Ptr = append(s2Ptr, [2]uintptr{0x77, 0x88})
302 s2Ptr = s2Ptr[:cap(s2Ptr)]
307 b.Run("3Ptr", func(b *testing.B) {
308 for i := 0; i < b.N; i++ {
309 s3Ptr = make([][3]uintptr, 0)
310 for j := 0; j < C; j++ {
311 s3Ptr = append(s3Ptr, [3]uintptr{0x77, 0x88, 0x99})
312 s3Ptr = s3Ptr[:cap(s3Ptr)]
317 b.Run("4Ptr", func(b *testing.B) {
318 for i := 0; i < b.N; i++ {
319 s4Ptr = make([][4]uintptr, 0)
320 for j := 0; j < C; j++ {
321 s4Ptr = append(s4Ptr, [4]uintptr{0x77, 0x88, 0x99, 0xAA})
322 s4Ptr = s4Ptr[:cap(s4Ptr)]