Commit ae1ea2aa authored by Dmitry Vyukov's avatar Dmitry Vyukov Committed by Russ Cox

runtime/trace: add new package

Move tracing functions from runtime/pprof to the new runtime/trace package.

Fixes #9710

Change-Id: I718bcb2ae3e5959d9f72cab5e6708289e5c8ebd5
Reviewed-on: https://go-review.googlesource.com/12511Reviewed-by: 's avatarRuss Cox <rsc@golang.org>
parent 1a99ba55
...@@ -874,8 +874,8 @@ pkg reflect, func FuncOf([]Type, []Type, bool) Type ...@@ -874,8 +874,8 @@ pkg reflect, func FuncOf([]Type, []Type, bool) Type
pkg runtime, func ReadTrace() []uint8 pkg runtime, func ReadTrace() []uint8
pkg runtime, func StartTrace() error pkg runtime, func StartTrace() error
pkg runtime, func StopTrace() pkg runtime, func StopTrace()
pkg runtime/pprof, func StartTrace(io.Writer) error pkg runtime/trace, func Start(io.Writer) error
pkg runtime/pprof, func StopTrace() pkg runtime/trace, func Stop()
pkg strings, func Compare(string, string) int pkg strings, func Compare(string, string) int
pkg strings, func LastIndexByte(string, uint8) int pkg strings, func LastIndexByte(string, uint8) int
pkg strings, method (*Reader) Size() int64 pkg strings, method (*Reader) Size() int64
......
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
Trace is a tool for viewing trace files. Trace is a tool for viewing trace files.
Trace files can be generated with: Trace files can be generated with:
- runtime/pprof.StartTrace - runtime/trace.Start
- net/http/pprof package - net/http/pprof package
- go test -trace - go test -trace
......
...@@ -151,9 +151,10 @@ var pkgDeps = map[string][]string{ ...@@ -151,9 +151,10 @@ var pkgDeps = map[string][]string{
"regexp/syntax": {"L2"}, "regexp/syntax": {"L2"},
"runtime/debug": {"L2", "fmt", "io/ioutil", "os", "time"}, "runtime/debug": {"L2", "fmt", "io/ioutil", "os", "time"},
"runtime/pprof": {"L2", "fmt", "text/tabwriter"}, "runtime/pprof": {"L2", "fmt", "text/tabwriter"},
"runtime/trace": {"L0"},
"text/tabwriter": {"L2"}, "text/tabwriter": {"L2"},
"testing": {"L2", "flag", "fmt", "os", "runtime/pprof", "time"}, "testing": {"L2", "flag", "fmt", "os", "runtime/pprof", "runtime/trace", "time"},
"testing/iotest": {"L2", "log"}, "testing/iotest": {"L2", "log"},
"testing/quick": {"L2", "flag", "fmt", "reflect"}, "testing/quick": {"L2", "flag", "fmt", "reflect"},
...@@ -331,7 +332,7 @@ var pkgDeps = map[string][]string{ ...@@ -331,7 +332,7 @@ var pkgDeps = map[string][]string{
"net/http/fcgi": {"L4", "NET", "OS", "net/http", "net/http/cgi"}, "net/http/fcgi": {"L4", "NET", "OS", "net/http", "net/http/cgi"},
"net/http/httptest": {"L4", "NET", "OS", "crypto/tls", "flag", "net/http"}, "net/http/httptest": {"L4", "NET", "OS", "crypto/tls", "flag", "net/http"},
"net/http/httputil": {"L4", "NET", "OS", "net/http", "net/http/internal"}, "net/http/httputil": {"L4", "NET", "OS", "net/http", "net/http/internal"},
"net/http/pprof": {"L4", "OS", "html/template", "net/http", "runtime/pprof"}, "net/http/pprof": {"L4", "OS", "html/template", "net/http", "runtime/pprof", "runtime/trace"},
"net/rpc": {"L4", "NET", "encoding/gob", "html/template", "net/http"}, "net/rpc": {"L4", "NET", "encoding/gob", "html/template", "net/http"},
"net/rpc/jsonrpc": {"L4", "NET", "encoding/json", "net/rpc"}, "net/rpc/jsonrpc": {"L4", "NET", "encoding/json", "net/rpc"},
......
...@@ -58,6 +58,7 @@ import ( ...@@ -58,6 +58,7 @@ import (
"os" "os"
"runtime" "runtime"
"runtime/pprof" "runtime/pprof"
"runtime/trace"
"strconv" "strconv"
"strings" "strings"
"time" "time"
...@@ -112,11 +113,11 @@ func Trace(w http.ResponseWriter, r *http.Request) { ...@@ -112,11 +113,11 @@ func Trace(w http.ResponseWriter, r *http.Request) {
sec = 1 sec = 1
} }
// Set Content Type assuming StartTrace will work, // Set Content Type assuming trace.Start will work,
// because if it does it starts writing. // because if it does it starts writing.
w.Header().Set("Content-Type", "application/octet-stream") w.Header().Set("Content-Type", "application/octet-stream")
if err := pprof.StartTrace(w); err != nil { if err := trace.Start(w); err != nil {
// StartTrace failed, so no writes yet. // trace.Start failed, so no writes yet.
// Can change header back to text content and send error code. // Can change header back to text content and send error code.
w.Header().Set("Content-Type", "text/plain; charset=utf-8") w.Header().Set("Content-Type", "text/plain; charset=utf-8")
w.WriteHeader(http.StatusInternalServerError) w.WriteHeader(http.StatusInternalServerError)
...@@ -124,7 +125,7 @@ func Trace(w http.ResponseWriter, r *http.Request) { ...@@ -124,7 +125,7 @@ func Trace(w http.ResponseWriter, r *http.Request) {
return return
} }
time.Sleep(time.Duration(sec) * time.Second) time.Sleep(time.Duration(sec) * time.Second)
pprof.StopTrace() trace.Stop()
} }
// Symbol looks up the program counters listed in the request, // Symbol looks up the program counters listed in the request,
......
...@@ -613,33 +613,6 @@ func StopCPUProfile() { ...@@ -613,33 +613,6 @@ func StopCPUProfile() {
<-cpu.done <-cpu.done
} }
// TODO(rsc): Decide if StartTrace belongs in this package.
// See golang.org/issue/9710.
// StartTrace enables tracing for the current process.
// While tracing, the trace will be buffered and written to w.
// StartTrace returns an error if profiling is tracing enabled.
func StartTrace(w io.Writer) error {
if err := runtime.StartTrace(); err != nil {
return err
}
go func() {
for {
data := runtime.ReadTrace()
if data == nil {
break
}
w.Write(data)
}
}()
return nil
}
// StopTrace stops the current tracing, if any.
// StopTrace only returns after all the writes for the trace have completed.
func StopTrace() {
runtime.StopTrace()
}
type byCycles []runtime.BlockProfileRecord type byCycles []runtime.BlockProfileRecord
func (x byCycles) Len() int { return len(x) } func (x byCycles) Len() int { return len(x) }
......
// Copyright 2015 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Go execution tracer.
// The tracer captures a wide range of execution events like goroutine
// creation/blocking/unblocking, syscall enter/exit/block, GC-related events,
// changes of heap size, processor start/stop, etc and writes them to an io.Writer
// in a compact form. A precise nanosecond-precision timestamp and a stack
// trace is captured for most events. A trace can be analyzed later with
// 'go tool trace' command.
package trace
import (
"io"
"runtime"
)
// Start enables tracing for the current program.
// While tracing, the trace will be buffered and written to w.
// Start returns an error if tracing is already enabled.
func Start(w io.Writer) error {
if err := runtime.StartTrace(); err != nil {
return err
}
go func() {
for {
data := runtime.ReadTrace()
if data == nil {
break
}
w.Write(data)
}
}()
return nil
}
// Stop stops the current tracing, if any.
// Stop only returns after all the writes for the trace have completed.
func Stop() {
runtime.StopTrace()
}
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
package pprof_test package trace_test
import ( import (
"bytes" "bytes"
...@@ -10,7 +10,7 @@ import ( ...@@ -10,7 +10,7 @@ import (
"net" "net"
"os" "os"
"runtime" "runtime"
. "runtime/pprof" . "runtime/trace"
"sync" "sync"
"testing" "testing"
"time" "time"
...@@ -25,7 +25,7 @@ func TestTraceSymbolize(t *testing.T) { ...@@ -25,7 +25,7 @@ func TestTraceSymbolize(t *testing.T) {
t.Skip("skipping: nacl tests fail with 'failed to symbolize trace: failed to start addr2line'") t.Skip("skipping: nacl tests fail with 'failed to symbolize trace: failed to start addr2line'")
} }
buf := new(bytes.Buffer) buf := new(bytes.Buffer)
if err := StartTrace(buf); err != nil { if err := Start(buf); err != nil {
t.Fatalf("failed to start tracing: %v", err) t.Fatalf("failed to start tracing: %v", err)
} }
...@@ -124,7 +124,7 @@ func TestTraceSymbolize(t *testing.T) { ...@@ -124,7 +124,7 @@ func TestTraceSymbolize(t *testing.T) {
wp.Write(data[:]) wp.Write(data[:])
<-pipeReadDone <-pipeReadDone
StopTrace() Stop()
events, _, err := parseTrace(buf) events, _, err := parseTrace(buf)
if err != nil { if err != nil {
t.Fatalf("failed to parse trace: %v", err) t.Fatalf("failed to parse trace: %v", err)
...@@ -146,87 +146,87 @@ func TestTraceSymbolize(t *testing.T) { ...@@ -146,87 +146,87 @@ func TestTraceSymbolize(t *testing.T) {
want := []eventDesc{ want := []eventDesc{
eventDesc{trace.EvGCStart, []frame{ eventDesc{trace.EvGCStart, []frame{
frame{"runtime.GC", 0}, frame{"runtime.GC", 0},
frame{"runtime/pprof_test.TestTraceSymbolize", 106}, frame{"runtime/trace_test.TestTraceSymbolize", 106},
frame{"testing.tRunner", 0}, frame{"testing.tRunner", 0},
}}, }},
eventDesc{trace.EvGoSched, []frame{ eventDesc{trace.EvGoSched, []frame{
frame{"runtime/pprof_test.TestTraceSymbolize", 107}, frame{"runtime/trace_test.TestTraceSymbolize", 107},
frame{"testing.tRunner", 0}, frame{"testing.tRunner", 0},
}}, }},
eventDesc{trace.EvGoCreate, []frame{ eventDesc{trace.EvGoCreate, []frame{
frame{"runtime/pprof_test.TestTraceSymbolize", 39}, frame{"runtime/trace_test.TestTraceSymbolize", 39},
frame{"testing.tRunner", 0}, frame{"testing.tRunner", 0},
}}, }},
eventDesc{trace.EvGoStop, []frame{ eventDesc{trace.EvGoStop, []frame{
frame{"runtime.block", 0}, frame{"runtime.block", 0},
frame{"runtime/pprof_test.TestTraceSymbolize.func1", 38}, frame{"runtime/trace_test.TestTraceSymbolize.func1", 38},
}}, }},
eventDesc{trace.EvGoStop, []frame{ eventDesc{trace.EvGoStop, []frame{
frame{"runtime.chansend1", 0}, frame{"runtime.chansend1", 0},
frame{"runtime/pprof_test.TestTraceSymbolize.func2", 42}, frame{"runtime/trace_test.TestTraceSymbolize.func2", 42},
}}, }},
eventDesc{trace.EvGoStop, []frame{ eventDesc{trace.EvGoStop, []frame{
frame{"runtime.chanrecv1", 0}, frame{"runtime.chanrecv1", 0},
frame{"runtime/pprof_test.TestTraceSymbolize.func3", 46}, frame{"runtime/trace_test.TestTraceSymbolize.func3", 46},
}}, }},
eventDesc{trace.EvGoBlockRecv, []frame{ eventDesc{trace.EvGoBlockRecv, []frame{
frame{"runtime.chanrecv1", 0}, frame{"runtime.chanrecv1", 0},
frame{"runtime/pprof_test.TestTraceSymbolize.func4", 50}, frame{"runtime/trace_test.TestTraceSymbolize.func4", 50},
}}, }},
eventDesc{trace.EvGoUnblock, []frame{ eventDesc{trace.EvGoUnblock, []frame{
frame{"runtime.chansend1", 0}, frame{"runtime.chansend1", 0},
frame{"runtime/pprof_test.TestTraceSymbolize", 109}, frame{"runtime/trace_test.TestTraceSymbolize", 109},
frame{"testing.tRunner", 0}, frame{"testing.tRunner", 0},
}}, }},
eventDesc{trace.EvGoBlockSend, []frame{ eventDesc{trace.EvGoBlockSend, []frame{
frame{"runtime.chansend1", 0}, frame{"runtime.chansend1", 0},
frame{"runtime/pprof_test.TestTraceSymbolize.func5", 54}, frame{"runtime/trace_test.TestTraceSymbolize.func5", 54},
}}, }},
eventDesc{trace.EvGoUnblock, []frame{ eventDesc{trace.EvGoUnblock, []frame{
frame{"runtime.chanrecv1", 0}, frame{"runtime.chanrecv1", 0},
frame{"runtime/pprof_test.TestTraceSymbolize", 110}, frame{"runtime/trace_test.TestTraceSymbolize", 110},
frame{"testing.tRunner", 0}, frame{"testing.tRunner", 0},
}}, }},
eventDesc{trace.EvGoBlockSelect, []frame{ eventDesc{trace.EvGoBlockSelect, []frame{
frame{"runtime.selectgo", 0}, frame{"runtime.selectgo", 0},
frame{"runtime/pprof_test.TestTraceSymbolize.func6", 59}, frame{"runtime/trace_test.TestTraceSymbolize.func6", 59},
}}, }},
eventDesc{trace.EvGoUnblock, []frame{ eventDesc{trace.EvGoUnblock, []frame{
frame{"runtime.selectgo", 0}, frame{"runtime.selectgo", 0},
frame{"runtime/pprof_test.TestTraceSymbolize", 111}, frame{"runtime/trace_test.TestTraceSymbolize", 111},
frame{"testing.tRunner", 0}, frame{"testing.tRunner", 0},
}}, }},
eventDesc{trace.EvGoBlockSync, []frame{ eventDesc{trace.EvGoBlockSync, []frame{
frame{"sync.(*Mutex).Lock", 0}, frame{"sync.(*Mutex).Lock", 0},
frame{"runtime/pprof_test.TestTraceSymbolize.func7", 67}, frame{"runtime/trace_test.TestTraceSymbolize.func7", 67},
}}, }},
eventDesc{trace.EvGoUnblock, []frame{ eventDesc{trace.EvGoUnblock, []frame{
frame{"sync.(*Mutex).Unlock", 0}, frame{"sync.(*Mutex).Unlock", 0},
frame{"runtime/pprof_test.TestTraceSymbolize", 115}, frame{"runtime/trace_test.TestTraceSymbolize", 115},
frame{"testing.tRunner", 0}, frame{"testing.tRunner", 0},
}}, }},
eventDesc{trace.EvGoBlockSync, []frame{ eventDesc{trace.EvGoBlockSync, []frame{
frame{"sync.(*WaitGroup).Wait", 0}, frame{"sync.(*WaitGroup).Wait", 0},
frame{"runtime/pprof_test.TestTraceSymbolize.func8", 73}, frame{"runtime/trace_test.TestTraceSymbolize.func8", 73},
}}, }},
eventDesc{trace.EvGoUnblock, []frame{ eventDesc{trace.EvGoUnblock, []frame{
frame{"sync.(*WaitGroup).Add", 0}, frame{"sync.(*WaitGroup).Add", 0},
frame{"sync.(*WaitGroup).Done", 0}, frame{"sync.(*WaitGroup).Done", 0},
frame{"runtime/pprof_test.TestTraceSymbolize", 116}, frame{"runtime/trace_test.TestTraceSymbolize", 116},
frame{"testing.tRunner", 0}, frame{"testing.tRunner", 0},
}}, }},
eventDesc{trace.EvGoBlockCond, []frame{ eventDesc{trace.EvGoBlockCond, []frame{
frame{"sync.(*Cond).Wait", 0}, frame{"sync.(*Cond).Wait", 0},
frame{"runtime/pprof_test.TestTraceSymbolize.func9", 78}, frame{"runtime/trace_test.TestTraceSymbolize.func9", 78},
}}, }},
eventDesc{trace.EvGoUnblock, []frame{ eventDesc{trace.EvGoUnblock, []frame{
frame{"sync.(*Cond).Signal", 0}, frame{"sync.(*Cond).Signal", 0},
frame{"runtime/pprof_test.TestTraceSymbolize", 117}, frame{"runtime/trace_test.TestTraceSymbolize", 117},
frame{"testing.tRunner", 0}, frame{"testing.tRunner", 0},
}}, }},
eventDesc{trace.EvGoSleep, []frame{ eventDesc{trace.EvGoSleep, []frame{
frame{"time.Sleep", 0}, frame{"time.Sleep", 0},
frame{"runtime/pprof_test.TestTraceSymbolize", 108}, frame{"runtime/trace_test.TestTraceSymbolize", 108},
frame{"testing.tRunner", 0}, frame{"testing.tRunner", 0},
}}, }},
} }
...@@ -237,14 +237,14 @@ func TestTraceSymbolize(t *testing.T) { ...@@ -237,14 +237,14 @@ func TestTraceSymbolize(t *testing.T) {
frame{"net.(*netFD).accept", 0}, frame{"net.(*netFD).accept", 0},
frame{"net.(*TCPListener).AcceptTCP", 0}, frame{"net.(*TCPListener).AcceptTCP", 0},
frame{"net.(*TCPListener).Accept", 0}, frame{"net.(*TCPListener).Accept", 0},
frame{"runtime/pprof_test.TestTraceSymbolize.func10", 86}, frame{"runtime/trace_test.TestTraceSymbolize.func10", 86},
}}, }},
eventDesc{trace.EvGoSysCall, []frame{ eventDesc{trace.EvGoSysCall, []frame{
frame{"syscall.read", 0}, frame{"syscall.read", 0},
frame{"syscall.Read", 0}, frame{"syscall.Read", 0},
frame{"os.(*File).read", 0}, frame{"os.(*File).read", 0},
frame{"os.(*File).Read", 0}, frame{"os.(*File).Read", 0},
frame{"runtime/pprof_test.TestTraceSymbolize.func11", 101}, frame{"runtime/trace_test.TestTraceSymbolize.func11", 101},
}}, }},
}...) }...)
} }
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
package pprof_test package trace_test
import ( import (
"bytes" "bytes"
...@@ -11,7 +11,7 @@ import ( ...@@ -11,7 +11,7 @@ import (
"net" "net"
"os" "os"
"runtime" "runtime"
. "runtime/pprof" . "runtime/trace"
"sync" "sync"
"testing" "testing"
"time" "time"
...@@ -39,10 +39,10 @@ func skipTraceTestsIfNeeded(t *testing.T) { ...@@ -39,10 +39,10 @@ func skipTraceTestsIfNeeded(t *testing.T) {
func TestTraceStartStop(t *testing.T) { func TestTraceStartStop(t *testing.T) {
skipTraceTestsIfNeeded(t) skipTraceTestsIfNeeded(t)
buf := new(bytes.Buffer) buf := new(bytes.Buffer)
if err := StartTrace(buf); err != nil { if err := Start(buf); err != nil {
t.Fatalf("failed to start tracing: %v", err) t.Fatalf("failed to start tracing: %v", err)
} }
StopTrace() Stop()
size := buf.Len() size := buf.Len()
if size == 0 { if size == 0 {
t.Fatalf("trace is empty") t.Fatalf("trace is empty")
...@@ -55,25 +55,25 @@ func TestTraceStartStop(t *testing.T) { ...@@ -55,25 +55,25 @@ func TestTraceStartStop(t *testing.T) {
func TestTraceDoubleStart(t *testing.T) { func TestTraceDoubleStart(t *testing.T) {
skipTraceTestsIfNeeded(t) skipTraceTestsIfNeeded(t)
StopTrace() Stop()
buf := new(bytes.Buffer) buf := new(bytes.Buffer)
if err := StartTrace(buf); err != nil { if err := Start(buf); err != nil {
t.Fatalf("failed to start tracing: %v", err) t.Fatalf("failed to start tracing: %v", err)
} }
if err := StartTrace(buf); err == nil { if err := Start(buf); err == nil {
t.Fatalf("succeed to start tracing second time") t.Fatalf("succeed to start tracing second time")
} }
StopTrace() Stop()
StopTrace() Stop()
} }
func TestTrace(t *testing.T) { func TestTrace(t *testing.T) {
skipTraceTestsIfNeeded(t) skipTraceTestsIfNeeded(t)
buf := new(bytes.Buffer) buf := new(bytes.Buffer)
if err := StartTrace(buf); err != nil { if err := Start(buf); err != nil {
t.Fatalf("failed to start tracing: %v", err) t.Fatalf("failed to start tracing: %v", err)
} }
StopTrace() Stop()
_, err := trace.Parse(buf) _, err := trace.Parse(buf)
if err != nil { if err != nil {
t.Fatalf("failed to parse trace: %v", err) t.Fatalf("failed to parse trace: %v", err)
...@@ -126,7 +126,7 @@ func TestTraceStress(t *testing.T) { ...@@ -126,7 +126,7 @@ func TestTraceStress(t *testing.T) {
time.Sleep(time.Millisecond) // give the goroutine above time to block time.Sleep(time.Millisecond) // give the goroutine above time to block
buf := new(bytes.Buffer) buf := new(bytes.Buffer)
if err := StartTrace(buf); err != nil { if err := Start(buf); err != nil {
t.Fatalf("failed to start tracing: %v", err) t.Fatalf("failed to start tracing: %v", err)
} }
...@@ -220,7 +220,7 @@ func TestTraceStress(t *testing.T) { ...@@ -220,7 +220,7 @@ func TestTraceStress(t *testing.T) {
runtime.GOMAXPROCS(procs) runtime.GOMAXPROCS(procs)
StopTrace() Stop()
_, _, err = parseTrace(buf) _, _, err = parseTrace(buf)
if err != nil { if err != nil {
t.Fatalf("failed to parse trace: %v", err) t.Fatalf("failed to parse trace: %v", err)
...@@ -356,11 +356,11 @@ func TestTraceStressStartStop(t *testing.T) { ...@@ -356,11 +356,11 @@ func TestTraceStressStartStop(t *testing.T) {
for i := 0; i < 3; i++ { for i := 0; i < 3; i++ {
buf := new(bytes.Buffer) buf := new(bytes.Buffer)
if err := StartTrace(buf); err != nil { if err := Start(buf); err != nil {
t.Fatalf("failed to start tracing: %v", err) t.Fatalf("failed to start tracing: %v", err)
} }
time.Sleep(time.Millisecond) time.Sleep(time.Millisecond)
StopTrace() Stop()
if _, _, err := parseTrace(buf); err != nil { if _, _, err := parseTrace(buf); err != nil {
t.Fatalf("failed to parse trace: %v", err) t.Fatalf("failed to parse trace: %v", err)
} }
...@@ -377,7 +377,7 @@ func TestTraceFutileWakeup(t *testing.T) { ...@@ -377,7 +377,7 @@ func TestTraceFutileWakeup(t *testing.T) {
} }
buf := new(bytes.Buffer) buf := new(bytes.Buffer)
if err := StartTrace(buf); err != nil { if err := Start(buf); err != nil {
t.Fatalf("failed to start tracing: %v", err) t.Fatalf("failed to start tracing: %v", err)
} }
...@@ -427,7 +427,7 @@ func TestTraceFutileWakeup(t *testing.T) { ...@@ -427,7 +427,7 @@ func TestTraceFutileWakeup(t *testing.T) {
} }
done.Wait() done.Wait()
StopTrace() Stop()
events, _, err := parseTrace(buf) events, _, err := parseTrace(buf)
if err != nil { if err != nil {
t.Fatalf("failed to parse trace: %v", err) t.Fatalf("failed to parse trace: %v", err)
......
...@@ -150,6 +150,7 @@ import ( ...@@ -150,6 +150,7 @@ import (
"os" "os"
"runtime" "runtime"
"runtime/pprof" "runtime/pprof"
"runtime/trace"
"strconv" "strconv"
"strings" "strings"
"sync" "sync"
...@@ -180,7 +181,7 @@ var ( ...@@ -180,7 +181,7 @@ var (
cpuProfile = flag.String("test.cpuprofile", "", "write a cpu profile to the named file during execution") cpuProfile = flag.String("test.cpuprofile", "", "write a cpu profile to the named file during execution")
blockProfile = flag.String("test.blockprofile", "", "write a goroutine blocking profile to the named file after execution") blockProfile = flag.String("test.blockprofile", "", "write a goroutine blocking profile to the named file after execution")
blockProfileRate = flag.Int("test.blockprofilerate", 1, "if >= 0, calls runtime.SetBlockProfileRate()") blockProfileRate = flag.Int("test.blockprofilerate", 1, "if >= 0, calls runtime.SetBlockProfileRate()")
trace = flag.String("test.trace", "", "write an execution trace to the named file after execution") traceFile = flag.String("test.trace", "", "write an execution trace to the named file after execution")
timeout = flag.Duration("test.timeout", 0, "if positive, sets an aggregate time limit for all tests") timeout = flag.Duration("test.timeout", 0, "if positive, sets an aggregate time limit for all tests")
cpuListStr = flag.String("test.cpu", "", "comma-separated list of number of CPUs to use for each test") cpuListStr = flag.String("test.cpu", "", "comma-separated list of number of CPUs to use for each test")
parallel = flag.Int("test.parallel", runtime.GOMAXPROCS(0), "maximum test parallelism") parallel = flag.Int("test.parallel", runtime.GOMAXPROCS(0), "maximum test parallelism")
...@@ -605,13 +606,13 @@ func before() { ...@@ -605,13 +606,13 @@ func before() {
} }
// Could save f so after can call f.Close; not worth the effort. // Could save f so after can call f.Close; not worth the effort.
} }
if *trace != "" { if *traceFile != "" {
f, err := os.Create(toOutputDir(*trace)) f, err := os.Create(toOutputDir(*traceFile))
if err != nil { if err != nil {
fmt.Fprintf(os.Stderr, "testing: %s", err) fmt.Fprintf(os.Stderr, "testing: %s", err)
return return
} }
if err := pprof.StartTrace(f); err != nil { if err := trace.Start(f); err != nil {
fmt.Fprintf(os.Stderr, "testing: can't start tracing: %s", err) fmt.Fprintf(os.Stderr, "testing: can't start tracing: %s", err)
f.Close() f.Close()
return return
...@@ -632,8 +633,8 @@ func after() { ...@@ -632,8 +633,8 @@ func after() {
if *cpuProfile != "" { if *cpuProfile != "" {
pprof.StopCPUProfile() // flushes profile to disk pprof.StopCPUProfile() // flushes profile to disk
} }
if *trace != "" { if *traceFile != "" {
pprof.StopTrace() // flushes trace to disk trace.Stop() // flushes trace to disk
} }
if *memProfile != "" { if *memProfile != "" {
f, err := os.Create(toOutputDir(*memProfile)) f, err := os.Create(toOutputDir(*memProfile))
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment