2016-08-05 Vladimir Makarov <vmakarov@redhat.com>
[official-gcc.git] / libgo / go / runtime / append_test.go
blob6b8968e382d349632a8bbcf1c68a2a244477338e
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 func BenchmarkAppendStr(b *testing.B) {
104 for _, str := range []string{
105 "1",
106 "1234",
107 "12345678",
108 "1234567890123456",
109 "12345678901234567890123456789012",
111 b.Run(fmt.Sprint(len(str), "Bytes"), func(b *testing.B) {
112 x := make([]byte, 0, N)
113 for i := 0; i < b.N; i++ {
114 x = x[0:0]
115 x = append(x, str...)
121 func BenchmarkAppendSpecialCase(b *testing.B) {
122 b.StopTimer()
123 x := make([]int, 0, N)
124 b.StartTimer()
125 for i := 0; i < b.N; i++ {
126 x = x[0:0]
127 for j := 0; j < N; j++ {
128 if len(x) < cap(x) {
129 x = x[:len(x)+1]
130 x[len(x)-1] = j
131 } else {
132 x = append(x, j)
138 var x []int
140 func f() int {
141 x[:1][0] = 3
142 return 2
145 func TestSideEffectOrder(t *testing.T) {
146 x = make([]int, 0, 10)
147 x = append(x, 1, f())
148 if x[0] != 1 || x[1] != 2 {
149 t.Error("append failed: ", x[0], x[1])
153 func TestAppendOverlap(t *testing.T) {
154 x := []byte("1234")
155 x = append(x[1:], x...) // p > q in runtimeĀ·appendslice.
156 got := string(x)
157 want := "2341234"
158 if got != want {
159 t.Errorf("overlap failed: got %q want %q", got, want)
163 func BenchmarkCopy(b *testing.B) {
164 for _, l := range []int{1, 2, 4, 8, 12, 16, 32, 128, 1024} {
165 buf := make([]byte, 4096)
166 b.Run(fmt.Sprint(l, "Byte"), func(b *testing.B) {
167 s := make([]byte, l)
168 var n int
169 for i := 0; i < b.N; i++ {
170 n = copy(buf, s)
172 b.SetBytes(int64(n))
174 b.Run(fmt.Sprint(l, "String"), func(b *testing.B) {
175 s := string(make([]byte, l))
176 var n int
177 for i := 0; i < b.N; i++ {
178 n = copy(buf, s)
180 b.SetBytes(int64(n))
185 var (
186 sByte []byte
187 s1Ptr []uintptr
188 s2Ptr [][2]uintptr
189 s3Ptr [][3]uintptr
190 s4Ptr [][4]uintptr
193 // BenchmarkAppendInPlace tests the performance of append
194 // when the result is being written back to the same slice.
195 // In order for the in-place optimization to occur,
196 // the slice must be referred to by address;
197 // using a global is an easy way to trigger that.
198 // We test the "grow" and "no grow" paths separately,
199 // but not the "normal" (occasionally grow) path,
200 // because it is a blend of the other two.
201 // We use small numbers and small sizes in an attempt
202 // to avoid benchmarking memory allocation and copying.
203 // We use scalars instead of pointers in an attempt
204 // to avoid benchmarking the write barriers.
205 // We benchmark four common sizes (byte, pointer, string/interface, slice),
206 // and one larger size.
207 func BenchmarkAppendInPlace(b *testing.B) {
208 b.Run("NoGrow", func(b *testing.B) {
209 const C = 128
211 b.Run("Byte", func(b *testing.B) {
212 for i := 0; i < b.N; i++ {
213 sByte = make([]byte, C)
214 for j := 0; j < C; j++ {
215 sByte = append(sByte, 0x77)
220 b.Run("1Ptr", func(b *testing.B) {
221 for i := 0; i < b.N; i++ {
222 s1Ptr = make([]uintptr, C)
223 for j := 0; j < C; j++ {
224 s1Ptr = append(s1Ptr, 0x77)
229 b.Run("2Ptr", func(b *testing.B) {
230 for i := 0; i < b.N; i++ {
231 s2Ptr = make([][2]uintptr, C)
232 for j := 0; j < C; j++ {
233 s2Ptr = append(s2Ptr, [2]uintptr{0x77, 0x88})
238 b.Run("3Ptr", func(b *testing.B) {
239 for i := 0; i < b.N; i++ {
240 s3Ptr = make([][3]uintptr, C)
241 for j := 0; j < C; j++ {
242 s3Ptr = append(s3Ptr, [3]uintptr{0x77, 0x88, 0x99})
247 b.Run("4Ptr", func(b *testing.B) {
248 for i := 0; i < b.N; i++ {
249 s4Ptr = make([][4]uintptr, C)
250 for j := 0; j < C; j++ {
251 s4Ptr = append(s4Ptr, [4]uintptr{0x77, 0x88, 0x99, 0xAA})
258 b.Run("Grow", func(b *testing.B) {
259 const C = 5
261 b.Run("Byte", func(b *testing.B) {
262 for i := 0; i < b.N; i++ {
263 sByte = make([]byte, 0)
264 for j := 0; j < C; j++ {
265 sByte = append(sByte, 0x77)
266 sByte = sByte[:cap(sByte)]
271 b.Run("1Ptr", func(b *testing.B) {
272 for i := 0; i < b.N; i++ {
273 s1Ptr = make([]uintptr, 0)
274 for j := 0; j < C; j++ {
275 s1Ptr = append(s1Ptr, 0x77)
276 s1Ptr = s1Ptr[:cap(s1Ptr)]
281 b.Run("2Ptr", func(b *testing.B) {
282 for i := 0; i < b.N; i++ {
283 s2Ptr = make([][2]uintptr, 0)
284 for j := 0; j < C; j++ {
285 s2Ptr = append(s2Ptr, [2]uintptr{0x77, 0x88})
286 s2Ptr = s2Ptr[:cap(s2Ptr)]
291 b.Run("3Ptr", func(b *testing.B) {
292 for i := 0; i < b.N; i++ {
293 s3Ptr = make([][3]uintptr, 0)
294 for j := 0; j < C; j++ {
295 s3Ptr = append(s3Ptr, [3]uintptr{0x77, 0x88, 0x99})
296 s3Ptr = s3Ptr[:cap(s3Ptr)]
301 b.Run("4Ptr", func(b *testing.B) {
302 for i := 0; i < b.N; i++ {
303 s4Ptr = make([][4]uintptr, 0)
304 for j := 0; j < C; j++ {
305 s4Ptr = append(s4Ptr, [4]uintptr{0x77, 0x88, 0x99, 0xAA})
306 s4Ptr = s4Ptr[:cap(s4Ptr)]