aboutsummaryrefslogtreecommitdiff
path: root/src/runtime
diff options
context:
space:
mode:
Diffstat (limited to 'src/runtime')
-rw-r--r--src/runtime/pprof/pprof.go27
-rw-r--r--src/runtime/trace/trace.go42
-rw-r--r--src/runtime/trace/trace_stack_test.go (renamed from src/runtime/pprof/trace_stack_test.go)50
-rw-r--r--src/runtime/trace/trace_test.go (renamed from src/runtime/pprof/trace_test.go)34
4 files changed, 84 insertions, 69 deletions
diff --git a/src/runtime/pprof/pprof.go b/src/runtime/pprof/pprof.go
index 43fe6e85a1..7d888e4ab0 100644
--- a/src/runtime/pprof/pprof.go
+++ b/src/runtime/pprof/pprof.go
@@ -613,33 +613,6 @@ func StopCPUProfile() {
<-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
func (x byCycles) Len() int { return len(x) }
diff --git a/src/runtime/trace/trace.go b/src/runtime/trace/trace.go
new file mode 100644
index 0000000000..7cbb8a6e82
--- /dev/null
+++ b/src/runtime/trace/trace.go
@@ -0,0 +1,42 @@
+// 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()
+}
diff --git a/src/runtime/pprof/trace_stack_test.go b/src/runtime/trace/trace_stack_test.go
index 984879dc92..061274a4f6 100644
--- a/src/runtime/pprof/trace_stack_test.go
+++ b/src/runtime/trace/trace_stack_test.go
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-package pprof_test
+package trace_test
import (
"bytes"
@@ -10,7 +10,7 @@ import (
"net"
"os"
"runtime"
- . "runtime/pprof"
+ . "runtime/trace"
"sync"
"testing"
"time"
@@ -25,7 +25,7 @@ func TestTraceSymbolize(t *testing.T) {
t.Skip("skipping: nacl tests fail with 'failed to symbolize trace: failed to start addr2line'")
}
buf := new(bytes.Buffer)
- if err := StartTrace(buf); err != nil {
+ if err := Start(buf); err != nil {
t.Fatalf("failed to start tracing: %v", err)
}
@@ -124,7 +124,7 @@ func TestTraceSymbolize(t *testing.T) {
wp.Write(data[:])
<-pipeReadDone
- StopTrace()
+ Stop()
events, _, err := parseTrace(buf)
if err != nil {
t.Fatalf("failed to parse trace: %v", err)
@@ -146,87 +146,87 @@ func TestTraceSymbolize(t *testing.T) {
want := []eventDesc{
eventDesc{trace.EvGCStart, []frame{
frame{"runtime.GC", 0},
- frame{"runtime/pprof_test.TestTraceSymbolize", 106},
+ frame{"runtime/trace_test.TestTraceSymbolize", 106},
frame{"testing.tRunner", 0},
}},
eventDesc{trace.EvGoSched, []frame{
- frame{"runtime/pprof_test.TestTraceSymbolize", 107},
+ frame{"runtime/trace_test.TestTraceSymbolize", 107},
frame{"testing.tRunner", 0},
}},
eventDesc{trace.EvGoCreate, []frame{
- frame{"runtime/pprof_test.TestTraceSymbolize", 39},
+ frame{"runtime/trace_test.TestTraceSymbolize", 39},
frame{"testing.tRunner", 0},
}},
eventDesc{trace.EvGoStop, []frame{
frame{"runtime.block", 0},
- frame{"runtime/pprof_test.TestTraceSymbolize.func1", 38},
+ frame{"runtime/trace_test.TestTraceSymbolize.func1", 38},
}},
eventDesc{trace.EvGoStop, []frame{
frame{"runtime.chansend1", 0},
- frame{"runtime/pprof_test.TestTraceSymbolize.func2", 42},
+ frame{"runtime/trace_test.TestTraceSymbolize.func2", 42},
}},
eventDesc{trace.EvGoStop, []frame{
frame{"runtime.chanrecv1", 0},
- frame{"runtime/pprof_test.TestTraceSymbolize.func3", 46},
+ frame{"runtime/trace_test.TestTraceSymbolize.func3", 46},
}},
eventDesc{trace.EvGoBlockRecv, []frame{
frame{"runtime.chanrecv1", 0},
- frame{"runtime/pprof_test.TestTraceSymbolize.func4", 50},
+ frame{"runtime/trace_test.TestTraceSymbolize.func4", 50},
}},
eventDesc{trace.EvGoUnblock, []frame{
frame{"runtime.chansend1", 0},
- frame{"runtime/pprof_test.TestTraceSymbolize", 109},
+ frame{"runtime/trace_test.TestTraceSymbolize", 109},
frame{"testing.tRunner", 0},
}},
eventDesc{trace.EvGoBlockSend, []frame{
frame{"runtime.chansend1", 0},
- frame{"runtime/pprof_test.TestTraceSymbolize.func5", 54},
+ frame{"runtime/trace_test.TestTraceSymbolize.func5", 54},
}},
eventDesc{trace.EvGoUnblock, []frame{
frame{"runtime.chanrecv1", 0},
- frame{"runtime/pprof_test.TestTraceSymbolize", 110},
+ frame{"runtime/trace_test.TestTraceSymbolize", 110},
frame{"testing.tRunner", 0},
}},
eventDesc{trace.EvGoBlockSelect, []frame{
frame{"runtime.selectgo", 0},
- frame{"runtime/pprof_test.TestTraceSymbolize.func6", 59},
+ frame{"runtime/trace_test.TestTraceSymbolize.func6", 59},
}},
eventDesc{trace.EvGoUnblock, []frame{
frame{"runtime.selectgo", 0},
- frame{"runtime/pprof_test.TestTraceSymbolize", 111},
+ frame{"runtime/trace_test.TestTraceSymbolize", 111},
frame{"testing.tRunner", 0},
}},
eventDesc{trace.EvGoBlockSync, []frame{
frame{"sync.(*Mutex).Lock", 0},
- frame{"runtime/pprof_test.TestTraceSymbolize.func7", 67},
+ frame{"runtime/trace_test.TestTraceSymbolize.func7", 67},
}},
eventDesc{trace.EvGoUnblock, []frame{
frame{"sync.(*Mutex).Unlock", 0},
- frame{"runtime/pprof_test.TestTraceSymbolize", 115},
+ frame{"runtime/trace_test.TestTraceSymbolize", 115},
frame{"testing.tRunner", 0},
}},
eventDesc{trace.EvGoBlockSync, []frame{
frame{"sync.(*WaitGroup).Wait", 0},
- frame{"runtime/pprof_test.TestTraceSymbolize.func8", 73},
+ frame{"runtime/trace_test.TestTraceSymbolize.func8", 73},
}},
eventDesc{trace.EvGoUnblock, []frame{
frame{"sync.(*WaitGroup).Add", 0},
frame{"sync.(*WaitGroup).Done", 0},
- frame{"runtime/pprof_test.TestTraceSymbolize", 116},
+ frame{"runtime/trace_test.TestTraceSymbolize", 116},
frame{"testing.tRunner", 0},
}},
eventDesc{trace.EvGoBlockCond, []frame{
frame{"sync.(*Cond).Wait", 0},
- frame{"runtime/pprof_test.TestTraceSymbolize.func9", 78},
+ frame{"runtime/trace_test.TestTraceSymbolize.func9", 78},
}},
eventDesc{trace.EvGoUnblock, []frame{
frame{"sync.(*Cond).Signal", 0},
- frame{"runtime/pprof_test.TestTraceSymbolize", 117},
+ frame{"runtime/trace_test.TestTraceSymbolize", 117},
frame{"testing.tRunner", 0},
}},
eventDesc{trace.EvGoSleep, []frame{
frame{"time.Sleep", 0},
- frame{"runtime/pprof_test.TestTraceSymbolize", 108},
+ frame{"runtime/trace_test.TestTraceSymbolize", 108},
frame{"testing.tRunner", 0},
}},
}
@@ -237,14 +237,14 @@ func TestTraceSymbolize(t *testing.T) {
frame{"net.(*netFD).accept", 0},
frame{"net.(*TCPListener).AcceptTCP", 0},
frame{"net.(*TCPListener).Accept", 0},
- frame{"runtime/pprof_test.TestTraceSymbolize.func10", 86},
+ frame{"runtime/trace_test.TestTraceSymbolize.func10", 86},
}},
eventDesc{trace.EvGoSysCall, []frame{
frame{"syscall.read", 0},
frame{"syscall.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},
}},
}...)
}
diff --git a/src/runtime/pprof/trace_test.go b/src/runtime/trace/trace_test.go
index ec88516cc1..e987564d8b 100644
--- a/src/runtime/pprof/trace_test.go
+++ b/src/runtime/trace/trace_test.go
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-package pprof_test
+package trace_test
import (
"bytes"
@@ -11,7 +11,7 @@ import (
"net"
"os"
"runtime"
- . "runtime/pprof"
+ . "runtime/trace"
"sync"
"testing"
"time"
@@ -39,10 +39,10 @@ func skipTraceTestsIfNeeded(t *testing.T) {
func TestTraceStartStop(t *testing.T) {
skipTraceTestsIfNeeded(t)
buf := new(bytes.Buffer)
- if err := StartTrace(buf); err != nil {
+ if err := Start(buf); err != nil {
t.Fatalf("failed to start tracing: %v", err)
}
- StopTrace()
+ Stop()
size := buf.Len()
if size == 0 {
t.Fatalf("trace is empty")
@@ -55,25 +55,25 @@ func TestTraceStartStop(t *testing.T) {
func TestTraceDoubleStart(t *testing.T) {
skipTraceTestsIfNeeded(t)
- StopTrace()
+ Stop()
buf := new(bytes.Buffer)
- if err := StartTrace(buf); err != nil {
+ if err := Start(buf); err != nil {
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")
}
- StopTrace()
- StopTrace()
+ Stop()
+ Stop()
}
func TestTrace(t *testing.T) {
skipTraceTestsIfNeeded(t)
buf := new(bytes.Buffer)
- if err := StartTrace(buf); err != nil {
+ if err := Start(buf); err != nil {
t.Fatalf("failed to start tracing: %v", err)
}
- StopTrace()
+ Stop()
_, err := trace.Parse(buf)
if err != nil {
t.Fatalf("failed to parse trace: %v", err)
@@ -126,7 +126,7 @@ func TestTraceStress(t *testing.T) {
time.Sleep(time.Millisecond) // give the goroutine above time to block
buf := new(bytes.Buffer)
- if err := StartTrace(buf); err != nil {
+ if err := Start(buf); err != nil {
t.Fatalf("failed to start tracing: %v", err)
}
@@ -220,7 +220,7 @@ func TestTraceStress(t *testing.T) {
runtime.GOMAXPROCS(procs)
- StopTrace()
+ Stop()
_, _, err = parseTrace(buf)
if err != nil {
t.Fatalf("failed to parse trace: %v", err)
@@ -356,11 +356,11 @@ func TestTraceStressStartStop(t *testing.T) {
for i := 0; i < 3; i++ {
buf := new(bytes.Buffer)
- if err := StartTrace(buf); err != nil {
+ if err := Start(buf); err != nil {
t.Fatalf("failed to start tracing: %v", err)
}
time.Sleep(time.Millisecond)
- StopTrace()
+ Stop()
if _, _, err := parseTrace(buf); err != nil {
t.Fatalf("failed to parse trace: %v", err)
}
@@ -377,7 +377,7 @@ func TestTraceFutileWakeup(t *testing.T) {
}
buf := new(bytes.Buffer)
- if err := StartTrace(buf); err != nil {
+ if err := Start(buf); err != nil {
t.Fatalf("failed to start tracing: %v", err)
}
@@ -427,7 +427,7 @@ func TestTraceFutileWakeup(t *testing.T) {
}
done.Wait()
- StopTrace()
+ Stop()
events, _, err := parseTrace(buf)
if err != nil {
t.Fatalf("failed to parse trace: %v", err)