2015-05-29 François Dumont fdumont@gcc.gnu.org>
[official-gcc.git] / libgo / go / runtime / gc_test.go
blobfe9e83902001e1d8049810316e93402de3ae007d
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.
5 package runtime_test
7 import (
8 // "os"
9 "runtime"
10 "runtime/debug"
11 "testing"
12 "time"
13 "unsafe"
16 func TestGcSys(t *testing.T) {
17 /* gccgo does not have a go command
18 if os.Getenv("GOGC") == "off" {
19 t.Skip("skipping test; GOGC=off in environment")
21 data := struct{ Short bool }{testing.Short()}
22 got := executeTest(t, testGCSysSource, &data)
23 want := "OK\n"
24 if got != want {
25 t.Fatalf("expected %q, but got %q", want, got)
30 const testGCSysSource = `
31 package main
33 import (
34 "fmt"
35 "runtime"
38 func main() {
39 runtime.GOMAXPROCS(1)
40 memstats := new(runtime.MemStats)
41 runtime.GC()
42 runtime.ReadMemStats(memstats)
43 sys := memstats.Sys
45 runtime.MemProfileRate = 0 // disable profiler
47 itercount := 1000000
48 {{if .Short}}
49 itercount = 100000
50 {{end}}
51 for i := 0; i < itercount; i++ {
52 workthegc()
55 // Should only be using a few MB.
56 // We allocated 100 MB or (if not short) 1 GB.
57 runtime.ReadMemStats(memstats)
58 if sys > memstats.Sys {
59 sys = 0
60 } else {
61 sys = memstats.Sys - sys
63 if sys > 16<<20 {
64 fmt.Printf("using too much memory: %d bytes\n", sys)
65 return
67 fmt.Printf("OK\n")
70 func workthegc() []byte {
71 return make([]byte, 1029)
75 func TestGcDeepNesting(t *testing.T) {
76 type T [2][2][2][2][2][2][2][2][2][2]*int
77 a := new(T)
79 // Prevent the compiler from applying escape analysis.
80 // This makes sure new(T) is allocated on heap, not on the stack.
81 t.Logf("%p", a)
83 a[0][0][0][0][0][0][0][0][0][0] = new(int)
84 *a[0][0][0][0][0][0][0][0][0][0] = 13
85 runtime.GC()
86 if *a[0][0][0][0][0][0][0][0][0][0] != 13 {
87 t.Fail()
91 func TestGcHashmapIndirection(t *testing.T) {
92 defer debug.SetGCPercent(debug.SetGCPercent(1))
93 runtime.GC()
94 type T struct {
95 a [256]int
97 m := make(map[T]T)
98 for i := 0; i < 2000; i++ {
99 var a T
100 a.a[0] = i
101 m[a] = T{}
105 func TestGcArraySlice(t *testing.T) {
106 type X struct {
107 buf [1]byte
108 nextbuf []byte
109 next *X
111 var head *X
112 for i := 0; i < 10; i++ {
113 p := &X{}
114 p.buf[0] = 42
115 p.next = head
116 if head != nil {
117 p.nextbuf = head.buf[:]
119 head = p
120 runtime.GC()
122 for p := head; p != nil; p = p.next {
123 if p.buf[0] != 42 {
124 t.Fatal("corrupted heap")
129 func TestGcRescan(t *testing.T) {
130 type X struct {
131 c chan error
132 nextx *X
134 type Y struct {
136 nexty *Y
137 p *int
139 var head *Y
140 for i := 0; i < 10; i++ {
141 p := &Y{}
142 p.c = make(chan error)
143 if head != nil {
144 p.nextx = &head.X
146 p.nexty = head
147 p.p = new(int)
148 *p.p = 42
149 head = p
150 runtime.GC()
152 for p := head; p != nil; p = p.nexty {
153 if *p.p != 42 {
154 t.Fatal("corrupted heap")
159 func TestGcLastTime(t *testing.T) {
160 ms := new(runtime.MemStats)
161 t0 := time.Now().UnixNano()
162 runtime.GC()
163 t1 := time.Now().UnixNano()
164 runtime.ReadMemStats(ms)
165 last := int64(ms.LastGC)
166 if t0 > last || last > t1 {
167 t.Fatalf("bad last GC time: got %v, want [%v, %v]", last, t0, t1)
169 pause := ms.PauseNs[(ms.NumGC+255)%256]
170 // Due to timer granularity, pause can actually be 0 on windows
171 // or on virtualized environments.
172 if pause == 0 {
173 t.Logf("last GC pause was 0")
174 } else if pause > 10e9 {
175 t.Logf("bad last GC pause: got %v, want [0, 10e9]", pause)
179 var hugeSink interface{}
181 func TestHugeGCInfo(t *testing.T) {
182 // The test ensures that compiler can chew these huge types even on weakest machines.
183 // The types are not allocated at runtime.
184 if hugeSink != nil {
185 // 400MB on 32 bots, 4TB on 64-bits.
186 const n = (400 << 20) + (unsafe.Sizeof(uintptr(0))-4)<<40
187 hugeSink = new([n]*byte)
188 hugeSink = new([n]uintptr)
189 hugeSink = new(struct {
190 x float64
191 y [n]*byte
192 z []string
194 hugeSink = new(struct {
195 x float64
196 y [n]uintptr
197 z []string
202 func BenchmarkSetTypeNoPtr1(b *testing.B) {
203 type NoPtr1 struct {
204 p uintptr
206 var p *NoPtr1
207 for i := 0; i < b.N; i++ {
208 p = &NoPtr1{}
210 _ = p
212 func BenchmarkSetTypeNoPtr2(b *testing.B) {
213 type NoPtr2 struct {
214 p, q uintptr
216 var p *NoPtr2
217 for i := 0; i < b.N; i++ {
218 p = &NoPtr2{}
220 _ = p
222 func BenchmarkSetTypePtr1(b *testing.B) {
223 type Ptr1 struct {
224 p *byte
226 var p *Ptr1
227 for i := 0; i < b.N; i++ {
228 p = &Ptr1{}
230 _ = p
232 func BenchmarkSetTypePtr2(b *testing.B) {
233 type Ptr2 struct {
234 p, q *byte
236 var p *Ptr2
237 for i := 0; i < b.N; i++ {
238 p = &Ptr2{}
240 _ = p
243 func BenchmarkAllocation(b *testing.B) {
244 type T struct {
245 x, y *byte
247 ngo := runtime.GOMAXPROCS(0)
248 work := make(chan bool, b.N+ngo)
249 result := make(chan *T)
250 for i := 0; i < b.N; i++ {
251 work <- true
253 for i := 0; i < ngo; i++ {
254 work <- false
256 for i := 0; i < ngo; i++ {
257 go func() {
258 var x *T
259 for <-work {
260 for i := 0; i < 1000; i++ {
261 x = &T{}
264 result <- x
267 for i := 0; i < ngo; i++ {
268 <-result
272 func TestPrintGC(t *testing.T) {
273 if testing.Short() {
274 t.Skip("Skipping in short mode")
276 defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(2))
277 done := make(chan bool)
278 go func() {
279 for {
280 select {
281 case <-done:
282 return
283 default:
284 runtime.GC()
288 for i := 0; i < 1e4; i++ {
289 func() {
290 defer print("")
293 close(done)