Add call trace command

This commit is contained in:
Tulir Asokan 2019-06-15 19:10:18 +03:00
parent ef509eb308
commit 6bb932212c
3 changed files with 31 additions and 31 deletions

View File

@ -34,8 +34,6 @@ import (
func init() {
gob.Register(map[string]interface{}{})
gob.Register([]interface{}{})
gob.Register(&Room{})
gob.Register(0)
}
type RoomNameSource int

View File

@ -109,6 +109,7 @@ func NewCommandProcessor(parent *MainView) *CommandProcessor {
"invite": cmdInvite,
"hprof": cmdHeapProfile,
"cprof": cmdCPUProfile,
"trace": cmdTrace,
},
}
}

View File

@ -19,10 +19,12 @@ package ui
import (
"encoding/json"
"fmt"
"io"
"os"
"runtime"
dbg "runtime/debug"
"runtime/pprof"
"runtime/trace"
"strconv"
"strings"
"time"
@ -92,38 +94,37 @@ func cmdHeapProfile(cmd *Command) {
}
}
func cmdCPUProfile(cmd *Command) {
func runTimedProfile(cmd *Command, start func(writer io.Writer) error, stop func(), task, file string) {
if len(cmd.Args) == 0 {
cmd.Reply("Usage: /cprof <seconds>")
return
}
dur, err := strconv.Atoi(cmd.Args[0])
if err != nil || dur < 0 {
cmd.Reply("Usage: /cprof <seconds>")
return
}
cpuProfile, err := os.Create("gomuks.cpu.prof")
if err != nil {
debug.Print("Failed to open gomuks.cpu.prof:", err)
return
}
err = pprof.StartCPUProfile(cpuProfile)
if err != nil {
cmd.Reply("Usage: /%s <seconds>", cmd.Command)
} else if dur, err := strconv.Atoi(cmd.Args[0]); err != nil || dur < 0 {
cmd.Reply("Usage: /%s <seconds>", cmd.Command)
} else if cpuProfile, err := os.Create(file); err != nil {
debug.Printf("Failed to open %s: %v", file, err)
} else if err = start(cpuProfile); err != nil {
_ = cpuProfile.Close()
debug.Print("CPU profile error:", err)
return
}
cmd.Reply("Started CPU profiling for %d seconds", dur)
go func() {
time.Sleep(time.Duration(dur) * time.Second)
pprof.StopCPUProfile()
cmd.Reply("CPU profiling finished.")
debug.Print(task, "error:", err)
} else {
cmd.Reply("Started %s for %d seconds", task, dur)
go func() {
time.Sleep(time.Duration(dur) * time.Second)
stop()
cmd.Reply("%s finished.", task)
err := cpuProfile.Close()
if err != nil {
debug.Print("Failed to close gomuks.cpu.prof:", err)
}
}()
err := cpuProfile.Close()
if err != nil {
debug.Print("Failed to close gomuks.cpu.prof:", err)
}
}()
}
}
func cmdCPUProfile(cmd *Command) {
runTimedProfile(cmd, pprof.StartCPUProfile, pprof.StopCPUProfile, "CPU profiling", "gomuks.cpu.prof")
}
func cmdTrace(cmd *Command) {
runTimedProfile(cmd, trace.Start, trace.Stop, "Call tracing", "gomuks.trace")
}
// TODO this command definitely belongs in a plugin once we have a plugin system.