Golang (1)

Source: Internet
Author: User
Tags benchmark rounds sprintf
This is a creation in Article, where the information may have evolved or changed.
Copyright: The Go Authors. All rights reserved.//Use of this source code are governed by a bsd-style//license so can be found in the license file. Package Testingimport ("Flag" "FMT" "Internal/race" "OS" "Runtime" "Sync" "sync/atomic" "Time") var Matchbenchmarks = flag. String ("Test.bench", "", "run only benchmarks matching ' regexp '") var benchtime = flag. Duration ("Test.benchtime", 1*time. Second, "run each benchmark for duration ' d '") var benchmarkmemory = flag.  Bool ("Test.benchmem", False, "print memory allocations for benchmarks")//Global lock to ensure-one benchmark runs at A Time.var benchmarklock sync. mutex//used for every benchmark for measuring memory.var memstats runtime. memstats//an internal type but exported because it is cross-package; Part of the implementation//of the ' Go test ' command.type internalbenchmark struct {Name stringf func (b *b)}//B is a Type passed to Benchmark functions to manage benchmark//timing and to specify the number of iterations to run.////A benchmark ends when it benchmark function returns or calls any of the methods//Failnow, Fatal, Fatalf, Skipnow, Skip, or SKIPF.  Those methods must is called//only from the goroutine running the Benchmark function.//the other reporting methods, such  As the variations of Log and error,//May is called simultaneously from multiple goroutines.////like in tests, benchmark Logs is accumulated during execution//and dumped to standard error when done. Unlike in tests, benchmark logs//is always printed, so as not to hide output whose existence may be//affecting Benchmar          K Results.type B struct {commonimportpath string//import path of the package containing the Benchmarkcontext *benchcontextn INTPREVIOUSN Int//number of iterations in the previous Runpreviousdur ation time. Duration//Total Duration of the previous runbenchfunc func (b *b) benchtime time. Durationbytes int64missingbytes BOOL//One of the SubbeNchmarks does not having bytes Set.timeron Boolshowallocresult boolresult benchmarkresultparallelism int//Runparallel creates Parallelism*gomaxprocs goroutines//the initial states of Memstats.mallocs and Memstats.total Alloc.startallocs Uint64startbytes uint64//The net total of this test after being Run.netallocs uint64netbytes uint64}/ /Starttimer starts timing a test.  This function was called automatically//before a benchmark starts, but it can also used to resume timing after//a call to Stoptimer.func (b *b) Starttimer () {if!b.timeron {runtime. Readmemstats (&memstats) B.startallocs = MemStats.Mallocsb.startBytes = MemStats.TotalAllocb.start = time. Now () B.timeron = true}}//Stoptimer stops timing a test.  This can is used to pause the timer//while performing complex initialization so you don ' t//want to Measure.func (b *b) Stoptimer () {if B.timeron {b.duration + = time. Now (). Sub (B.start) runtime. Readmemstats (&memstats) B.netallocs + = Memstats.mallocS-b.startallocsb.netbytes + = Memstats.totalalloc-b.startbytesb.timeron = false}}//ResetTimer Zeros the elapsed benchm Ark Time and memory allocation counters.//IT does not affect whether the timer is Running.func (b *b) Resettimer () {if B. timerOn {runtime. Readmemstats (&memstats) B.startallocs = MemStats.Mallocsb.startBytes = MemStats.TotalAllocb.start = time. Now ()}b.duration = 0b.netallocs = 0b.netbytes = 0}//SetBytes records the number of bytes processed in a single operation. If This is called, the benchmark would report Ns/op and Mb/s.func (b *b) setbytes (n Int64) {b.bytes = n}//reportalloc s enables malloc statistics for this benchmark.//it's equivalent to Setting-test.benchmem, but it's only affects the//be Nchmark function that calls Reportallocs.func (b *b) Reportallocs () {b.showallocresult = True}func (b *b) Nsperop () Int64 {if B.N <= 0 {return 0}return b.duration.nanoseconds ()/Int64 (B.N)}//Runn runs a single benchmark for the specified N Umber of ITERATIONS.FUNC (b *b) Runn (n int) {Benchmarklock.lock () defer benchmarklock.unlock ()//Try to get a comparable environment for each RU n//by clearing garbage from previous runs.runtime.GC () B.raceerrors =-race. Errors () B.N = Nb.parallelism = 1b. Resettimer () B.starttimer () B.benchfunc (b) b.stoptimer () B.previousn = Nb.previousduration = b.durationb.raceerrors + = Race.  Errors () If b.raceerrors > 0 {B.errorf ("race detected during execution of benchmark")}}func min (x, y int) int {if x > Y {return y}return x}func max (x, y int) int {if x < y {return Y}return x}//roundDown10 rounds a number down to the NE Arest Power of 10.func roundDown10 (n int) int {var Tens = 0//Tens = Floor (LOG_10 (n)) for n >= ten {n = n/10tens++}//r Esult = 10^tensresult: = 1for I: = 0; I < Tens; i++ {result *= 10}return result}//roundUp rounds x up to a number of the form [1eX, 2eX, 3eX, 5ex].func roundUp (n int.) in t {base: = ROUNDDOWN10 (n) switch {case n <= base:return basecase n <= (2 * Base): Return 2 * basecase N <= (3 * Base): Return 3 * basecase n <= (5 * Base): return 5 * Basedefault:return * base}}//run1 runs the first ite Ration of Benchfunc.  It returns whether more//iterations of this benchmarks should be Run.func (b *b) run1 () bool {if ctx: = B.context; CTX! = Nil {//Extend maxlen, if needed.if n: = Len (b.name) + Ctx.extlen + 1; n > Ctx.maxlen {ctx.maxlen = n + 8//ADD Addit ional slack to avoid too many jumps in size.}} Go func () {//Signal that we ' re do whether we return normally//or by Failnow ' s runtime. Goexit.defer func () {b.signal <-true} () B.runn (1)} () <-b.signalif b.failed {fmt. fprintf (B.W, "---FAIL:%s\n%s", B.name, B.output) return false}//only print the output if we know we is not going to pro ceed.//Otherwise It is printed in Processbench.if Atomic. LoadInt32 (&b.hassub)! = 0 | | b.finished {tag: = "BENCH" if b.skipped {tag = "SKIP"}if b.chatty && (len (b.output) > 0 | | b.finished) {B.trimou Tput () fmt. fprintf (B.W, "---%s:%s\n%s", Tag, B.name, B.OUtput)}return false}return true}var labelsonce sync. once//run executes the benchmark in a separate goroutine, including all of its//subbenchmarks. B must not has Subbenchmarks.func (b *b) run () Benchmarkresult {labelsonce.do (func () {FMT). fprintf (B.W, "GOOS:%s\n", runtime.) GOOS) fmt. fprintf (B.W, "Goarch:%s\n", runtime.) Goarch) if B.importpath! = "" {fmt.  fprintf (B.W, "pkg:%s\n", B.importpath)}) if B.context! = nil {//Running go Test--test.benchb.context.processbench (b)// Must call Dobench.} else {//Running func benchmark.b.dobench ()}return B.result}func (b *b) Dobench () Benchmarkresult {go b.launch () <-b.si Gnalreturn b.result}//launch launches the benchmark function.  It gradually increases the number//of benchmark iterations until the benchmark runs for the requested benchtime.//launch  is run by the Dobench function as a separate goroutine.//run1 must has been called on B.func (b *b) launch () {//Signal That we ' re do whether we return normally//or by Failnow ' s runtime. GoexIt.defer func () {b.signal <-true} ()//Run The benchmark for at least the specified amount of TIME.D: = B.benchtimefor N: = 1;!b.failed && B.duration < D && N < 1e9; {Last: = n//Predict Required ITERATIONS.N = Int (d.nanoseconds ()) if nsop: = B.nsperop (); Nsop! = 0 {n/= int (nsop)}//Run More iterations than we think we ' ll need (1.2X).//Don ' t grow too fast in case we had timing errors previously.//be sure To run at least one more than last TIME.N = max (min (N+N/5, 100*last), last+1)//Round up to something easy to READ.N = Rou Ndup (n) B.runn (n)}b.result = BENCHMARKRESULT{B.N, B.duration, B.bytes, B.netallocs, b.netbytes}}//the results of a benchm Ark Run.Type benchmarkresult struct {N int//The number of iterations. T time. Duration//The total time taken. Bytes Int64//Bytes processed in one iteration. Memallocs UInt64//The total number of memory allocations. Membytes UInt64//The total number of bytes AllocAted.} Func (R Benchmarkresult) Nsperop () Int64 {if R.N <= 0 {return 0}return r.t.nanoseconds ()/Int64 (R.N)}func (R Benchmark Result) mbpersec () float64 {if r.bytes <= 0 | | r.t <= 0 | | R.N <= 0 {return 0}return (float64 (r.bytes) * Float64 ( R.N)/1e6)/R.t.seconds ()}//Allocsperop returns R.memallocs/r.n.func (R Benchmarkresult) Allocsperop () Int64 {if R.N <= 0 {return 0}return int64 (R.memallocs)/Int64 (R.N)}//Allocedbytesperop returns R.membytes/r.n.func (R Benchmarkre Sult) Allocedbytesperop () Int64 {if R.N <= 0 {return 0}return int64 (r.membytes)/Int64 (R.N)}func (R Benchmarkresult) S Tring () string {mbs: = R.mbpersec () MB: = "" If MBS! = 0 {mb = fmt. Sprintf ("\t%7.2f MB/S", MBS)}nsop: = R.nsperop () ns: = FMT.  Sprintf ("%10d ns/op", Nsop) if R.N > 0 && Nsop < +//The format specifiers here make sure that//the ones Digits line up for all three possible formats.if Nsop < {ns = FMT. Sprintf ("%13.2f ns/op", Float64 (R.t.nanoseconds ())/float64 (R.N))}else {ns = FMT. Sprintf ("%12.1f ns/op", Float64 (R.t.nanoseconds ())/float64 (R.N))}}return FMT. Sprintf ("%8d\t%s%s", R.N, NS, MB)}//memstring returns R.allocedbytesperop and R.allocsperop in the same format as ' Go tes T '. Func (R Benchmarkresult) memstring () string {return FMT. Sprintf ("%8d b/op\t%8d allocs/op", R.allocedbytesperop (), R.allocsperop ())}//Benchmarkname returns full name of Benchmark including procs Suffix.func benchmarkname (name string, n int) string {if n! = 1 {return FMT.  Sprintf ("%s-%d", Name, N)}return name}type benchcontext struct {match *matchermaxlen int//The largest recorded benchmark Name.extlen int//Maximum extension length.} An internal function and exported because it is cross-package; Part of the implementation//of the "Go Test" Command.func runbenchmarks (matchstring func (Pat, str string) (bool, error), Benchmarks []internalbenchmark] {Runbenchmarks ("", matchstring, benchmarks)}func Runbenchmarks (ImportPath string, matchstring func (Pat, str string) (bool, ERROR), benchmarks []internalbenchmark) bool {//IF no flag was specified, don ' t run Benchmarks.if len (*matchbenchmarks) = = 0 {return true}//Collect matching benchmarks and determine longest name.maxprocs: = 1for _, procs: = Range Cpulist {if PR OCS > Maxprocs {maxprocs = Procs}}ctx: = &benchcontext{match:newmatcher (matchstring, *matchbenchmarks, "-test.be Nch "), Extlen:len (Benchmarkname (" ", Maxprocs)),}var BS []internalbenchmarkfor _, Benchmark: = Range Benchmarks {If _, MATC Hed, _: = Ctx.match.fullName (nil, benchmark.name);  matched {bs = append (BS, Benchmark) Benchname: = Benchmarkname (Benchmark.name, Maxprocs) if L: = Len (benchname) + Ctx.extlen + 1; L > Ctx.maxlen {ctx.maxlen = L}}}main: = &b{common:common{name: "Main", W:os. Stdout,chatty: *chatty,},importpath:importpath,benchfunc:func (b *b) {for _, Benchmark: = range bs {b.run (benchmark.name , Benchmark.f)}},benchtime: *benchtime,context:ctx,}main.runn (1) return!main.failed}//Processbench runs bench b for tHe configured CPU counts and prints the Results.func (ctx *benchcontext) processbench (b *b) {For I, procs: = Range cpulist {Runtime. Gomaxprocs (procs) Benchname: = Benchmarkname (B.name, procs) fmt. fprintf (B.W, "%-*s\t", Ctx.maxlen, Benchname)//Recompute The running time for all but the first iteration.if i > 0 {b = &b{common:common{signal:make (chan bool), Name:b.name,w:b.w,chatty:b.chatty,},benchfunc:b.benchfunc,bench TIME:B.BENCHTIME,}B.RUN1 ()}r: = B.dobench () if b.failed {//The output could is very long here, but probably isn ' t.//We p Rint it all, regardless, because we don't want to trim the reason//the benchmark failed.fmt.Fprintf (B.W, "---FAIL:%s\n% S ", Benchname, b.output) Continue}results: = R.string () If *benchmarkmemory | | B.showallocresult {results + = "\ T" + r.memstring ()}fmt. Fprintln (B.W, results)//Unlike with tests, we ignore The-chatty flag and always print output for//benchmarks Output generation time would skew the Results.if Len (b.output) &GT 0 {b.trimoutput () fmt. fprintf (B.W, "---BENCH:%s\n%s", Benchname, B.output)}if p: = runtime. Gomaxprocs (-1); P! = procs {fmt. fprintf (OS. Stderr, "Testing:%s left Gomaxprocs set to%d\n", Benchname, p)}}}//Run benchmarks F as a subbenchmark with the given NA Me. It reports//whether there were any failures.////A Subbenchmark are like any other benchmark. A benchmark that calls run at//least once would not be measured itself and would be called once with n=1.////run may CA lled simultaneously from multiple goroutines, but all such//calls must return before the outer benchmark function for B R Eturns.func (b *b) run (name string, f func (b *b)) bool {//Since B has subbenchmarks, we'll no longer Run it as a benchm Ark itself.//Release The lock and acquire it on exit to ensure locks stay paired.atomic.StoreInt32 (&b.hassub, 1) Bench Marklock.unlock () defer benchmarklock.lock () benchname, OK, partial: = B.name, True, falseif b.context! = Nil {benchname, OK , partial = B.context.match.fullName (&b.common, name)}if!ok {return true}sub: = &b{common:common{signal:make (chan bool), Name:benchname,paren T: &b.common,level:b.level + 1,w:b.w,chatty:b.chatty,},importpath:b.importpath,benchfunc:f,benchtime:b.b Enchtime,context:b.context,}if Partial {//partial name match, like-bench=x/y matching benchmarkx.//only process sub -benchmarks, if Any.atomic.StoreInt32 (&sub.hassub, 1)}if sub.run1 () {Sub.run ()}b.add (Sub.result) return! sub.failed}//add simulates running benchmarks in sequence in a single iteration. It is//used to give some meaningful results in case func Benchmark was used in//combination with Run.func (b *b) Add (othe R Benchmarkresult) {r: = &b.result//The aggregated benchmarkresults resemble running all Subbenchmarks as//in Sequen Ce in a single BENCHMARK.R.N = 1r. T + = time. Duration (Other. Nsperop ()) if other. Bytes = = 0 {//summing Bytes is meaningless in aggregate if not all subbenchmarks//set it.b.missingbytes = Truer. Bytes =0}if!b.missingbytes {r.bytes + = other. Bytes}r.memallocs + = UInt64 (other. Allocsperop ()) R.membytes + = UInt64 (other. Allocedbytesperop ())}//Trimoutput shortens the output from a benchmark, which can be very long.func (b *b) Trimoutput () { The output is likely to appear multiple times because the benchmark//are run multiple times, but at least it would be SE En. This isn't a big deal//because benchmarks rarely print, but just in case, we trim it ' s too long.const maxnewlines = 10for Nlcount, J: = 0, 0; J < Len (b.output); J + + {if b.output[j] = = ' \ n ' {nlcount++if nlcount >= maxnewlines {b.output = append (B.output[:j], "\n\t ... [Output truncated]\n ...] break}}}}//A PB is used by Runparallel for running parallel benchmarks.type PB struct {globaln *uint64//shared between  All worker Goroutines Iteration Countergrain UInt64//Acquire, many iterations from Globaln at Oncecache UInt64 Local cache of acquired ITERATIONSBN UInt64//Total number of iterations to EXecute (B.N)}//Next reports whether there is more iterations to Execute.func (PB *PB) Next () bool {if Pb.cache = = 0 {N: = Atomic. AddUint64 (PB.GLOBALN, Pb.grain) if n <= pb.bn {pb.cache = pb.grain} else if n < pb.bn+pb.grain {Pb.cache = pb.bn + PB . grain-n} else {return False}}pb.cache--return true}//Runparallel runs a benchmark in parallel.//It creates multiple g Oroutines and distributes B.N iterations among them.//the number of goroutines defaults to Gomaxprocs. To increase parallelism for//non-cpu-bound benchmarks, call Setparallelism before runparallel.//runparallel is usually u Sed with the go test-cpu flag.////the body function would be is run in each goroutine. It should set up any//goroutine-local, and then iterate until PB. Next returns false.//It should not use the Starttimer, Stoptimer, or Resettimer functions,//because they has global eff Ect. It should also not call Run.func (b *b) Runparallel (body func (*PB)) {if B.N = = 0 {return//Nothing to do when ProbiNg.} Calculate grain size As number of iterations that take ~100µs.//100µs are enough to amortize the overhead and provide s ufficient//dynamic load Balancing.grain: = UInt64 (0) if B.previousn > 0 && b.previousduration > 0 {grain = 1 e5 * UInt64 (B.PREVIOUSN)/UInt64 (b.previousduration)}if Grain < 1 {grain = 1}//We Expect the inner loop and function Call-to-take at least 10ns,//so does not does more than 100µs/10ns=1e4 Iterations.if grain > 1e4 {grain = 1e4}n: = UInt64 ( 0) Numprocs: = B.parallelism * runtime. Gomaxprocs (0) var wg sync. Waitgroupwg.add (Numprocs) for P: = 0; P < Numprocs; p++ {go func () {defer WG. Done () PB: = &pb{globaln: &n,grain:grain,bn:uint64 (B.N),}body (Pb)} ()}wg. Wait () if n <= uint64 (B.N) &&!b.failed () {b.fatal ("Runparallel:body exited without PB.  Next () = = False ")}}//Setparallelism sets the number of goroutines used by Runparallel to p*gomaxprocs.//there is usually No need to call setparallelism for Cpu-bound benchmarks.//if P is less than 1, this call would have no Effect.func (b *b) setparallelism (p int) {If P >= 1 {b.parallelism = p}}/ /Benchmark benchmarks a single function. Useful for creating//custom benchmarks the "Go test" command.////If F calls Run, the result would be a E Stimate of running all its//subbenchmarks this don ' t call Run in sequence in a single Benchmark.func benchmark (f func (b * b)) Benchmarkresult {b: = &b{common:common{signal:make (chan bool), W:discard{},},benchfunc:f,benchtime: *bench  Time,}if b.run1 () {b.run ()}return b.result}type discard Struct{}func (discard) Write (b []byte) (n int, err error) {return Len (b), nil}

The above refers to the go source, benchmark part;

Initialization of the 1,benchmark:

> (1) The test cycle of default one second can be set by itself; other reference flags

> (2), constant: 1e9 Max loop

> (3), benchmarkxxx function of the stack mode

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.