From 543acc97f95a6453729d44bddf49647308ce660c Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Wed, 23 Mar 2011 18:17:14 -0400 Subject: [PATCH] testing: add -test.cpuprofile flag R=r CC=golang-dev https://golang.org/cl/4272066 --- src/cmd/gotest/gotest | 3 +-- src/cmd/prof/gopprof | 5 ++-- src/pkg/testing/testing.go | 48 +++++++++++++++++++++++++++----------- 3 files changed, 39 insertions(+), 17 deletions(-) diff --git a/src/cmd/gotest/gotest b/src/cmd/gotest/gotest index 4cadb5c94d..d00c9d4cd2 100755 --- a/src/cmd/gotest/gotest +++ b/src/cmd/gotest/gotest @@ -203,8 +203,7 @@ func matchString(pat, str string) (result bool, err __os__.Error) { } func main() { - testing.Main(matchString, tests) - testing.RunBenchmarks(matchString, benchmarks) + testing.Main(matchString, tests, benchmarks) }' }>_testmain.go diff --git a/src/cmd/prof/gopprof b/src/cmd/prof/gopprof index e391f36a0b..8fa00cbe8c 100755 --- a/src/cmd/prof/gopprof +++ b/src/cmd/prof/gopprof @@ -2476,7 +2476,8 @@ sub RemoveUninterestingFrames { # Nothing skipped for unknown types } - if ($main::profile_type eq 'cpu') { + # Go doesn't have the problem that this heuristic tries to fix. Disable. + if (0 && $main::profile_type eq 'cpu') { # If all the second-youngest program counters are the same, # this STRONGLY suggests that it is an artifact of measurement, # i.e., stack frames pushed by the CPU profiler signal handler. @@ -2976,7 +2977,7 @@ sub FetchDynamicProfile { $url = sprintf("http://$profile_name" . "seconds=%d", $main::opt_seconds); } - $curl_timeout = sprintf("--max-time=%d", + $curl_timeout = sprintf("--max-time %d", int($main::opt_seconds * 1.01 + 60)); } else { # For non-CPU profiles, we add a type-extension to diff --git a/src/pkg/testing/testing.go b/src/pkg/testing/testing.go index 0751436903..ab8cf999a2 100644 --- a/src/pkg/testing/testing.go +++ b/src/pkg/testing/testing.go @@ -51,8 +51,9 @@ var ( // Report as tests are run; default is silent for success. chatty = flag.Bool("test.v", false, "verbose: print additional output") match = flag.String("test.run", "", "regular expression to select tests to run") - memProfile = flag.String("test.memprofile", "", "after execution write the memory profile to the named file") + memProfile = flag.String("test.memprofile", "", "write a memory profile to the named file after execution") memProfileRate = flag.Int("test.memprofilerate", 0, "if >=0, sets runtime.MemProfileRate") + cpuProfile = flag.String("test.cpuprofile", "", "write a cpu profile to the named file during execution") ) @@ -141,10 +142,16 @@ func tRunner(t *T, test *InternalTest) { // An internal function but exported because it is cross-package; part of the implementation // of gotest. -func Main(matchString func(pat, str string) (bool, os.Error), tests []InternalTest) { +func Main(matchString func(pat, str string) (bool, os.Error), tests []InternalTest, benchmarks []InternalBenchmark) { flag.Parse() before() + RunTests(matchString, tests) + RunBenchmarks(matchString, benchmarks) + after() +} + +func RunTests(matchString func(pat, str string) (bool, os.Error), tests []InternalTest) { ok := true if len(tests) == 0 { println("testing: warning: no tests to run") @@ -177,7 +184,6 @@ func Main(matchString func(pat, str string) (bool, os.Error), tests []InternalTe print(t.errors) } } - after() if !ok { println("FAIL") os.Exit(1) @@ -190,20 +196,36 @@ func before() { if *memProfileRate > 0 { runtime.MemProfileRate = *memProfileRate } + if *cpuProfile != "" { + f, err := os.Open(*cpuProfile, os.O_WRONLY|os.O_CREAT|os.O_TRUNC, 0666) + if err != nil { + fmt.Fprintf(os.Stderr, "testing: %s", err) + return + } + if err := pprof.StartCPUProfile(f); err != nil { + fmt.Fprintf(os.Stderr, "testing: can't start cpu profile: %s", err) + f.Close() + return + } + // Could save f so after can call f.Close; not worth the effort. + } + } // after runs after all testing. func after() { - if *memProfile == "" { - return + if *cpuProfile != "" { + pprof.StopCPUProfile() // flushes profile to disk } - fd, err := os.Open(*memProfile, os.O_WRONLY|os.O_CREAT|os.O_TRUNC, 0666) - if err != nil { - fmt.Fprintf(os.Stderr, "testing: can't open %s: %s", *memProfile, err) - return + if *memProfile != "" { + f, err := os.Open(*memProfile, os.O_WRONLY|os.O_CREAT|os.O_TRUNC, 0666) + if err != nil { + fmt.Fprintf(os.Stderr, "testing: %s", err) + return + } + if err = pprof.WriteHeapProfile(f); err != nil { + fmt.Fprintf(os.Stderr, "testing: can't write %s: %s", *memProfile, err) + } + f.Close() } - if err = pprof.WriteHeapProfile(fd); err != nil { - fmt.Fprintf(os.Stderr, "testing: can't write %s: %s", *memProfile, err) - } - fd.Close() }