background
Go must test to run benchmark, which makes it more troublesome to test benchmark in main function in some cases. Therefore, I implemented a simple and overhead benchmark function, which is convenient for use! Secondly, it is convenient for everyone to learn how to implement aZero overheadbenchmark framework!
benchmark implementation
For benchamrks with timeout, the overhead of comparing (timeout) is very high every time, and the external function of benchmark cannot be an empty function, and it must have count, because function calls will probably deteriorate at the ns level!
Therefore, the general benchmark algorithm is a gradient benchmark, that is, the order of magnitude of 1, 10, 100, 10000, 100000, 1000000... is the advantage of avoiding a large amount of computing overhead, because the single time is about 30ns (in Linux environment), the overhead is very large!
package pprof import ( "fmt" "sync" "sync/atomic" "time" ) func ParallelBenchmark(name string, thread int, duration , execute func(count int)) { wg := {} (thread) totalCount := uint64(0) totalSpend := uint64(0) for i := 0; i < thread; i++ { go func() { defer () spend, count := Benchmark(duration, execute) atomic.AddUint64(&totalSpend, uint64(spend)) atomic.AddUint64(&totalCount, uint64(count)) }() } () ("name=%s thread=%d duration=%s total=%d avg=%s\n", name, thread, duration, totalCount, Avg((totalSpend), int(totalCount))) } func Avg(spend , count int) string { avg := float64(spend) / float64(count) if avg > 100 { return (avg).String() } return ("%.4fns", avg) } func Benchmark(duration , bench func(count int)) (, int) { const maxTotalCount = 1000000000 // 10E count := 1 totalSpend := (0) totalCount := 0 for { start := () bench(count) spend := (start) totalSpend = totalSpend + spend totalCount = totalCount + count if totalCount >= maxTotalCount { break } subSpend := duration - totalSpend if subSpend <= 0 { break } count = totalCount*10 - totalCount if subCount := int(float64(subSpend) / (float64(totalSpend) / float64(totalCount))); count > subCount { count = subCount } } return totalSpend, totalCount }
profile implementation
package pprof import ( "net/http" _ "net/http/pprof" "os" "runtime" "runtime/pprof" ) // InitPProf // go InitPProf() func InitPProf() { err := (":12345", ) if err != nil { panic(err) } } func StartCPUProfile(fileName string) (stop func()) { f, err := (fileName) if err != nil { panic(err) } if err := (f); err != nil { if err := (); err != nil { panic(err) } panic(err) } return func() { () if err := (); err != nil { panic(err) } } } func StartMemProfile(fileName string) (stop func()) { f, err := (fileName) if err != nil { panic(err) } return func() { defer func() { if err := (); err != nil { panic(err) } }() () // get up-to-date statistics if err := (f); err != nil { panic(err) } } }
example
package main import ( "/anthony-dong/golang/pkg/pprof" "sync" "time" ) func main() { // Record cup pprof //stop := ("") //defer stop() // Concurrently test the performance of sync map mm := {} ("test1", 64, , func(count int) { for i := 0; i < count; i++ { (i%10000, 1) } }) // name=test1 thread=32 duration=1s total=6708009 avg=4.772µs // name=test1 thread=64 duration=1s total=6883456 avg=9.3µs }
This is the end of this article about how Go language implements Benchmark functions. For more related Go Benchmark content, please search for my previous articles or continue browsing the related articles below. I hope everyone will support me in the future!