mirror of
https://github.com/golang/go
synced 2024-11-22 05:44:41 -07:00
testing: add -test.memprofile and -test.memprofilerate flags.
These allow a test to generate memory profiles automatically. R=golang-dev, rsc1 CC=golang-dev https://golang.org/cl/4273064
This commit is contained in:
parent
df184ff2f0
commit
afaa30694c
@ -38,11 +38,11 @@ interfere with the non-test installation.
|
|||||||
Usage:
|
Usage:
|
||||||
gotest [pkg_test.go ...]
|
gotest [pkg_test.go ...]
|
||||||
|
|
||||||
The resulting binary, called (for amd64) 6.out, has a couple of
|
The resulting binary, called (for amd64) 6.out, has several flags.
|
||||||
arguments.
|
|
||||||
|
|
||||||
Usage:
|
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
|
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
|
-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
|
non-zero code. The -test.bench flag is analogous to the -test.run
|
||||||
flag, but applies to benchmarks. No benchmarks run by default.
|
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
|
package documentation
|
||||||
|
@ -6,12 +6,10 @@ package gob
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"flag"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"os"
|
"os"
|
||||||
"runtime"
|
"runtime"
|
||||||
"runtime/pprof"
|
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -22,8 +20,6 @@ type Bench struct {
|
|||||||
D []byte
|
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) {
|
func benchmarkEndToEnd(r io.Reader, w io.Writer, b *testing.B) {
|
||||||
b.StopTimer()
|
b.StopTimer()
|
||||||
enc := NewEncoder(w)
|
enc := NewEncoder(w)
|
||||||
@ -54,7 +50,6 @@ func BenchmarkEndToEndByteBuffer(b *testing.B) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestCountEncodeMallocs(t *testing.T) {
|
func TestCountEncodeMallocs(t *testing.T) {
|
||||||
runtime.MemProfileRate = 1
|
|
||||||
var buf bytes.Buffer
|
var buf bytes.Buffer
|
||||||
enc := NewEncoder(&buf)
|
enc := NewEncoder(&buf)
|
||||||
bench := &Bench{7, 3.2, "now is the time", []byte("for all good men")}
|
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
|
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)
|
fmt.Printf("mallocs per encode of type Bench: %d\n", mallocs/count)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestCountDecodeMallocs(t *testing.T) {
|
func TestCountDecodeMallocs(t *testing.T) {
|
||||||
runtime.MemProfileRate = 1
|
|
||||||
var buf bytes.Buffer
|
var buf bytes.Buffer
|
||||||
enc := NewEncoder(&buf)
|
enc := NewEncoder(&buf)
|
||||||
bench := &Bench{7, 3.2, "now is the time", []byte("for all good men")}
|
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
|
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)
|
fmt.Printf("mallocs per decode of type Bench: %d\n", mallocs/count)
|
||||||
}
|
}
|
||||||
|
@ -5,14 +5,12 @@
|
|||||||
package rpc
|
package rpc
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"flag"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"http/httptest"
|
"http/httptest"
|
||||||
"log"
|
"log"
|
||||||
"net"
|
"net"
|
||||||
"os"
|
"os"
|
||||||
"runtime"
|
"runtime"
|
||||||
"runtime/pprof"
|
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
"testing"
|
"testing"
|
||||||
@ -25,8 +23,6 @@ var (
|
|||||||
once, newOnce, httpOnce sync.Once
|
once, newOnce, httpOnce sync.Once
|
||||||
)
|
)
|
||||||
|
|
||||||
var memprofile = flag.String("memprofile", "", "write the memory profile in TestCountMallocs to the named file")
|
|
||||||
|
|
||||||
const (
|
const (
|
||||||
second = 1e9
|
second = 1e9
|
||||||
newHttpPath = "/foo"
|
newHttpPath = "/foo"
|
||||||
@ -356,7 +352,6 @@ func testSendDeadlock(client *Client) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestCountMallocs(t *testing.T) {
|
func TestCountMallocs(t *testing.T) {
|
||||||
runtime.MemProfileRate = 1
|
|
||||||
once.Do(startServer)
|
once.Do(startServer)
|
||||||
client, err := Dial("tcp", serverAddr)
|
client, err := Dial("tcp", serverAddr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -365,7 +360,7 @@ func TestCountMallocs(t *testing.T) {
|
|||||||
args := &Args{7, 8}
|
args := &Args{7, 8}
|
||||||
reply := new(Reply)
|
reply := new(Reply)
|
||||||
mallocs := 0 - runtime.MemStats.Mallocs
|
mallocs := 0 - runtime.MemStats.Mallocs
|
||||||
const count = 10000
|
const count = 100
|
||||||
for i := 0; i < count; i++ {
|
for i := 0; i < count; i++ {
|
||||||
err = client.Call("Arith.Add", args, reply)
|
err = client.Call("Arith.Add", args, reply)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -376,16 +371,6 @@ func TestCountMallocs(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
mallocs += runtime.MemStats.Mallocs
|
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)
|
fmt.Printf("mallocs per rpc round trip: %d\n", mallocs/count)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -43,12 +43,17 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"runtime"
|
"runtime"
|
||||||
|
"runtime/pprof"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Report as tests are run; default is silent for success.
|
var (
|
||||||
var chatty = flag.Bool("test.v", false, "verbose: print additional output")
|
// Report as tests are run; default is silent for success.
|
||||||
var match = flag.String("test.run", "", "regular expression to select tests to run")
|
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.
|
// Insert final newline if needed and tabs after internal newlines.
|
||||||
@ -138,6 +143,8 @@ func tRunner(t *T, test *InternalTest) {
|
|||||||
// of gotest.
|
// 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) {
|
||||||
flag.Parse()
|
flag.Parse()
|
||||||
|
|
||||||
|
before()
|
||||||
ok := true
|
ok := true
|
||||||
if len(tests) == 0 {
|
if len(tests) == 0 {
|
||||||
println("testing: warning: no tests to run")
|
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)
|
print(t.errors)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
after()
|
||||||
if !ok {
|
if !ok {
|
||||||
println("FAIL")
|
println("FAIL")
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
println("PASS")
|
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()
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user