...
Run Format

Source file src/runtime/testdata/testprog/gc.go

Documentation: runtime/testdata/testprog

  // Copyright 2015 The Go Authors. All rights reserved.
  // Use of this source code is governed by a BSD-style
  // license that can be found in the LICENSE file.
  
  package main
  
  import (
  	"fmt"
  	"os"
  	"runtime"
  	"runtime/debug"
  	"sync/atomic"
  	"time"
  )
  
  func init() {
  	register("GCFairness", GCFairness)
  	register("GCFairness2", GCFairness2)
  	register("GCSys", GCSys)
  }
  
  func GCSys() {
  	runtime.GOMAXPROCS(1)
  	memstats := new(runtime.MemStats)
  	runtime.GC()
  	runtime.ReadMemStats(memstats)
  	sys := memstats.Sys
  
  	runtime.MemProfileRate = 0 // disable profiler
  
  	itercount := 100000
  	for i := 0; i < itercount; i++ {
  		workthegc()
  	}
  
  	// Should only be using a few MB.
  	// We allocated 100 MB or (if not short) 1 GB.
  	runtime.ReadMemStats(memstats)
  	if sys > memstats.Sys {
  		sys = 0
  	} else {
  		sys = memstats.Sys - sys
  	}
  	if sys > 16<<20 {
  		fmt.Printf("using too much memory: %d bytes\n", sys)
  		return
  	}
  	fmt.Printf("OK\n")
  }
  
  func workthegc() []byte {
  	return make([]byte, 1029)
  }
  
  func GCFairness() {
  	runtime.GOMAXPROCS(1)
  	f, err := os.Open("/dev/null")
  	if os.IsNotExist(err) {
  		// This test tests what it is intended to test only if writes are fast.
  		// If there is no /dev/null, we just don't execute the test.
  		fmt.Println("OK")
  		return
  	}
  	if err != nil {
  		fmt.Println(err)
  		os.Exit(1)
  	}
  	for i := 0; i < 2; i++ {
  		go func() {
  			for {
  				f.Write([]byte("."))
  			}
  		}()
  	}
  	time.Sleep(10 * time.Millisecond)
  	fmt.Println("OK")
  }
  
  func GCFairness2() {
  	// Make sure user code can't exploit the GC's high priority
  	// scheduling to make scheduling of user code unfair. See
  	// issue #15706.
  	runtime.GOMAXPROCS(1)
  	debug.SetGCPercent(1)
  	var count [3]int64
  	var sink [3]interface{}
  	for i := range count {
  		go func(i int) {
  			for {
  				sink[i] = make([]byte, 1024)
  				atomic.AddInt64(&count[i], 1)
  			}
  		}(i)
  	}
  	// Note: If the unfairness is really bad, it may not even get
  	// past the sleep.
  	//
  	// If the scheduling rules change, this may not be enough time
  	// to let all goroutines run, but for now we cycle through
  	// them rapidly.
  	//
  	// OpenBSD's scheduler makes every usleep() take at least
  	// 20ms, so we need a long time to ensure all goroutines have
  	// run. If they haven't run after 30ms, give it another 1000ms
  	// and check again.
  	time.Sleep(30 * time.Millisecond)
  	var fail bool
  	for i := range count {
  		if atomic.LoadInt64(&count[i]) == 0 {
  			fail = true
  		}
  	}
  	if fail {
  		time.Sleep(1 * time.Second)
  		for i := range count {
  			if atomic.LoadInt64(&count[i]) == 0 {
  				fmt.Printf("goroutine %d did not run\n", i)
  				return
  			}
  		}
  	}
  	fmt.Println("OK")
  }
  

View as plain text