]> Cypherpunks repositories - gostls13.git/commitdiff
testing: add -test.memprofile and -test.memprofilerate flags.
authorRob Pike <r@golang.org>
Wed, 16 Mar 2011 16:53:58 +0000 (09:53 -0700)
committerRob Pike <r@golang.org>
Wed, 16 Mar 2011 16:53:58 +0000 (09:53 -0700)
These allow a test to generate memory profiles automatically.

R=golang-dev, rsc1
CC=golang-dev
https://golang.org/cl/4273064

src/cmd/gotest/doc.go
src/pkg/gob/timing_test.go
src/pkg/rpc/server_test.go
src/pkg/testing/testing.go

index 581eaaab9cc14e6b68517aea50b94b0adfcd6cda..517108629c467583428686f108b14e9acf66e076 100644 (file)
@@ -38,11 +38,11 @@ interfere with the non-test installation.
 Usage:
        gotest [pkg_test.go ...]
 
-The resulting binary, called (for amd64) 6.out, has a couple of
-arguments.
+The resulting binary, called (for amd64) 6.out, has several flags.
 
 Usage:
-       6.out [-test.v] [-test.run pattern] [-test.bench pattern]
+       6.out [-test.v] [-test.run pattern] [-test.bench pattern] \
+               [test.memprofile=prof.out] [-test.memprofilerate=1]
 
 The -test.v flag causes the tests to be logged as they run.  The
 -test.run flag causes only those tests whose names match the regular
@@ -52,5 +52,19 @@ exit code.  If any tests fail, it prints FAIL and exits with a
 non-zero code.  The -test.bench flag is analogous to the -test.run
 flag, but applies to benchmarks.  No benchmarks run by default.
 
+The -test.memprofile flag causes the testing software to write a
+memory profile to the specified file when all tests are complete.  Use
+-test.run or -test.bench to limit the profile to a particular test or
+benchmark.  The -test.memprofilerate flag enables more precise (and
+expensive) profiles by setting runtime.MemProfileRate;
+       godoc runtime MemProfileRate
+for details.  The defaults are no memory profile and the standard
+setting of MemProfileRate.  The memory profile records a sampling of
+the memory in use at the end of the test.  To profile all memory
+allocations, use -test.memprofilerate=1 to sample every byte and set
+the environment variable GOGC=off to disable the garbage collector,
+provided the test can run in the available memory without garbage
+collection.
+
 */
 package documentation
index 5f71f3f015ef4088303348874bc048b0d9c92595..645f4fe51c9058ce68d0e511cf466632cbb2f0bb 100644 (file)
@@ -6,12 +6,10 @@ package gob
 
 import (
        "bytes"
-       "flag"
        "fmt"
        "io"
        "os"
        "runtime"
-       "runtime/pprof"
        "testing"
 )
 
@@ -22,8 +20,6 @@ type Bench struct {
        D []byte
 }
 
-var memprofile = flag.String("memprofile", "", "write the memory profile in Test*Mallocs to the named file")
-
 func benchmarkEndToEnd(r io.Reader, w io.Writer, b *testing.B) {
        b.StopTimer()
        enc := NewEncoder(w)
@@ -54,7 +50,6 @@ func BenchmarkEndToEndByteBuffer(b *testing.B) {
 }
 
 func TestCountEncodeMallocs(t *testing.T) {
-       runtime.MemProfileRate = 1
        var buf bytes.Buffer
        enc := NewEncoder(&buf)
        bench := &Bench{7, 3.2, "now is the time", []byte("for all good men")}
@@ -67,21 +62,10 @@ func TestCountEncodeMallocs(t *testing.T) {
                }
        }
        mallocs += runtime.MemStats.Mallocs
-       if *memprofile != "" {
-               if fd, err := os.Open(*memprofile, os.O_WRONLY|os.O_CREAT|os.O_TRUNC, 0666); err != nil {
-                       t.Errorf("can't open %s: %s", *memprofile, err)
-               } else {
-                       if err = pprof.WriteHeapProfile(fd); err != nil {
-                               t.Errorf("can't write %s: %s", *memprofile, err)
-                       }
-                       fd.Close()
-               }
-       }
        fmt.Printf("mallocs per encode of type Bench: %d\n", mallocs/count)
 }
 
 func TestCountDecodeMallocs(t *testing.T) {
-       runtime.MemProfileRate = 1
        var buf bytes.Buffer
        enc := NewEncoder(&buf)
        bench := &Bench{7, 3.2, "now is the time", []byte("for all good men")}
@@ -102,15 +86,5 @@ func TestCountDecodeMallocs(t *testing.T) {
                }
        }
        mallocs += runtime.MemStats.Mallocs
-       if *memprofile != "" {
-               if fd, err := os.Open(*memprofile, os.O_WRONLY|os.O_CREAT|os.O_TRUNC, 0666); err != nil {
-                       t.Errorf("can't open %s: %s", *memprofile, err)
-               } else {
-                       if err = pprof.WriteHeapProfile(fd); err != nil {
-                               t.Errorf("can't write %s: %s", *memprofile, err)
-                       }
-                       fd.Close()
-               }
-       }
        fmt.Printf("mallocs per decode of type Bench: %d\n", mallocs/count)
 }
index 71c283ed844c8d56438b02b48b2e28df804a46ce..9e32b740f1e8b37a4cd54dabbcc55c2f4e7d3161 100644 (file)
@@ -5,14 +5,12 @@
 package rpc
 
 import (
-       "flag"
        "fmt"
        "http/httptest"
        "log"
        "net"
        "os"
        "runtime"
-       "runtime/pprof"
        "strings"
        "sync"
        "testing"
@@ -25,8 +23,6 @@ var (
        once, newOnce, httpOnce   sync.Once
 )
 
-var memprofile = flag.String("memprofile", "", "write the memory profile in TestCountMallocs to the named file")
-
 const (
        second      = 1e9
        newHttpPath = "/foo"
@@ -356,7 +352,6 @@ func testSendDeadlock(client *Client) {
 }
 
 func TestCountMallocs(t *testing.T) {
-       runtime.MemProfileRate = 1
        once.Do(startServer)
        client, err := Dial("tcp", serverAddr)
        if err != nil {
@@ -365,7 +360,7 @@ func TestCountMallocs(t *testing.T) {
        args := &Args{7, 8}
        reply := new(Reply)
        mallocs := 0 - runtime.MemStats.Mallocs
-       const count = 10000
+       const count = 100
        for i := 0; i < count; i++ {
                err = client.Call("Arith.Add", args, reply)
                if err != nil {
@@ -376,16 +371,6 @@ func TestCountMallocs(t *testing.T) {
                }
        }
        mallocs += runtime.MemStats.Mallocs
-       if *memprofile != "" {
-               if fd, err := os.Open(*memprofile, os.O_WRONLY|os.O_CREAT|os.O_TRUNC, 0666); err != nil {
-                       t.Errorf("can't open %s: %s", *memprofile, err)
-               } else {
-                       if err = pprof.WriteHeapProfile(fd); err != nil {
-                               t.Errorf("can't write %s: %s", *memprofile, err)
-                       }
-                       fd.Close()
-               }
-       }
        fmt.Printf("mallocs per rpc round trip: %d\n", mallocs/count)
 }
 
index 324b5a70e1fa3c64899c69c91f462c9de1139a93..0751436903ed69e3c12903b83570ad8536723a68 100644 (file)
@@ -43,12 +43,17 @@ import (
        "fmt"
        "os"
        "runtime"
+       "runtime/pprof"
        "time"
 )
 
-// Report as tests are run; default is silent for success.
-var chatty = flag.Bool("test.v", false, "verbose: print additional output")
-var match = flag.String("test.run", "", "regular expression to select tests to run")
+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")
+       memProfileRate = flag.Int("test.memprofilerate", 0, "if >=0, sets runtime.MemProfileRate")
+)
 
 
 // Insert final newline if needed and tabs after internal newlines.
@@ -138,6 +143,8 @@ func tRunner(t *T, test *InternalTest) {
 // of gotest.
 func Main(matchString func(pat, str string) (bool, os.Error), tests []InternalTest) {
        flag.Parse()
+
+       before()
        ok := true
        if len(tests) == 0 {
                println("testing: warning: no tests to run")
@@ -170,9 +177,33 @@ func Main(matchString func(pat, str string) (bool, os.Error), tests []InternalTe
                        print(t.errors)
                }
        }
+       after()
        if !ok {
                println("FAIL")
                os.Exit(1)
        }
        println("PASS")
 }
+
+// before runs before all testing.
+func before() {
+       if *memProfileRate > 0 {
+               runtime.MemProfileRate = *memProfileRate
+       }
+}
+
+// after runs after all testing.
+func after() {
+       if *memProfile == "" {
+               return
+       }
+       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 err = pprof.WriteHeapProfile(fd); err != nil {
+               fmt.Fprintf(os.Stderr, "testing: can't write %s: %s", *memProfile, err)
+       }
+       fd.Close()
+}