github.com/hikaru7719/go@v0.0.0-20181025140707-c8b2ac68906a/src/runtime/testdata/testprog/gc.go (about) 1 // Copyright 2015 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 5 package main 6 7 import ( 8 "fmt" 9 "os" 10 "runtime" 11 "runtime/debug" 12 "sync/atomic" 13 "time" 14 ) 15 16 func init() { 17 register("GCFairness", GCFairness) 18 register("GCFairness2", GCFairness2) 19 register("GCSys", GCSys) 20 } 21 22 func GCSys() { 23 runtime.GOMAXPROCS(1) 24 memstats := new(runtime.MemStats) 25 runtime.GC() 26 runtime.ReadMemStats(memstats) 27 sys := memstats.Sys 28 29 runtime.MemProfileRate = 0 // disable profiler 30 31 itercount := 100000 32 for i := 0; i < itercount; i++ { 33 workthegc() 34 } 35 36 // Should only be using a few MB. 37 // We allocated 100 MB or (if not short) 1 GB. 38 runtime.ReadMemStats(memstats) 39 if sys > memstats.Sys { 40 sys = 0 41 } else { 42 sys = memstats.Sys - sys 43 } 44 if sys > 16<<20 { 45 fmt.Printf("using too much memory: %d bytes\n", sys) 46 return 47 } 48 fmt.Printf("OK\n") 49 } 50 51 var sink []byte 52 53 func workthegc() []byte { 54 sink = make([]byte, 1029) 55 return sink 56 } 57 58 func GCFairness() { 59 runtime.GOMAXPROCS(1) 60 f, err := os.Open("/dev/null") 61 if os.IsNotExist(err) { 62 // This test tests what it is intended to test only if writes are fast. 63 // If there is no /dev/null, we just don't execute the test. 64 fmt.Println("OK") 65 return 66 } 67 if err != nil { 68 fmt.Println(err) 69 os.Exit(1) 70 } 71 for i := 0; i < 2; i++ { 72 go func() { 73 for { 74 f.Write([]byte(".")) 75 } 76 }() 77 } 78 time.Sleep(10 * time.Millisecond) 79 fmt.Println("OK") 80 } 81 82 func GCFairness2() { 83 // Make sure user code can't exploit the GC's high priority 84 // scheduling to make scheduling of user code unfair. See 85 // issue #15706. 86 runtime.GOMAXPROCS(1) 87 debug.SetGCPercent(1) 88 var count [3]int64 89 var sink [3]interface{} 90 for i := range count { 91 go func(i int) { 92 for { 93 sink[i] = make([]byte, 1024) 94 atomic.AddInt64(&count[i], 1) 95 } 96 }(i) 97 } 98 // Note: If the unfairness is really bad, it may not even get 99 // past the sleep. 100 // 101 // If the scheduling rules change, this may not be enough time 102 // to let all goroutines run, but for now we cycle through 103 // them rapidly. 104 // 105 // OpenBSD's scheduler makes every usleep() take at least 106 // 20ms, so we need a long time to ensure all goroutines have 107 // run. If they haven't run after 30ms, give it another 1000ms 108 // and check again. 109 time.Sleep(30 * time.Millisecond) 110 var fail bool 111 for i := range count { 112 if atomic.LoadInt64(&count[i]) == 0 { 113 fail = true 114 } 115 } 116 if fail { 117 time.Sleep(1 * time.Second) 118 for i := range count { 119 if atomic.LoadInt64(&count[i]) == 0 { 120 fmt.Printf("goroutine %d did not run\n", i) 121 return 122 } 123 } 124 } 125 fmt.Println("OK") 126 }