Home | History | Annotate | Download | only in testing
      1 // Copyright 2013 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 testing
      6 
      7 import (
      8 	"runtime"
      9 )
     10 
     11 // AllocsPerRun returns the average number of allocations during calls to f.
     12 // Although the return value has type float64, it will always be an integral value.
     13 //
     14 // To compute the number of allocations, the function will first be run once as
     15 // a warm-up. The average number of allocations over the specified number of
     16 // runs will then be measured and returned.
     17 //
     18 // AllocsPerRun sets GOMAXPROCS to 1 during its measurement and will restore
     19 // it before returning.
     20 func AllocsPerRun(runs int, f func()) (avg float64) {
     21 	defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(1))
     22 
     23 	// Warm up the function
     24 	f()
     25 
     26 	// Measure the starting statistics
     27 	var memstats runtime.MemStats
     28 	runtime.ReadMemStats(&memstats)
     29 	mallocs := 0 - memstats.Mallocs
     30 
     31 	// Run the function the specified number of times
     32 	for i := 0; i < runs; i++ {
     33 		f()
     34 	}
     35 
     36 	// Read the final statistics
     37 	runtime.ReadMemStats(&memstats)
     38 	mallocs += memstats.Mallocs
     39 
     40 	// Average the mallocs over the runs (not counting the warm-up).
     41 	// We are forced to return a float64 because the API is silly, but do
     42 	// the division as integers so we can ask if AllocsPerRun()==1
     43 	// instead of AllocsPerRun()<2.
     44 	return float64(mallocs / uint64(runs))
     45 }
     46