Go tool使用记录
1、trace
https://mp.weixin.qq.com/s/ugXT_l-fNHEGANoLvirRLA
示例程序
package main
import (
"os"
"runtime/trace"
)
func main() {
trace.Start(os.Stderr)
defer trace.Stop()
var ch1 = make(chan string)
go func() {
ch1 <- "hello world"
}()
<-ch1
}
生成trace文件
go run main.go. 2>trace.out
使用go tool trace打开
go tool trace trace.out
out
2021/09/01 10:15:26 Parsing trace...
2021/09/01 10:15:26 Splitting trace...
2021/09/01 10:15:26 Opening browser. Trace viewer is listening on http://127.0.0.1:57123
浏览器显示:
解释:
- View trace:查看跟踪
- Goroutine analysis:Goroutine 分析
- Network blocking profile:网络阻塞概况
- Synchronization blocking profile:同步阻塞概况
- Syscall blocking profile:系统调用阻塞概况
- Scheduler latency profile:调度延迟概况
- User defined tasks:用户自定义任务
- User defined regions:用户自定义区域
- Minimum mutator utilization:最低 Mutator 利用率
打开goroutine分析
按理来说,N应该是3,目前还不清楚为什么是4.链接中的演示显示的是3
详细使用看上面的链接
方法二
package main
import (
"os"
"runtime/trace"
)
func main() {
f, err := os.Create("trace1.out")
if err != nil {
panic(err)
}
defer f.Close()
err = trace.Start(f)
if err != nil {
panic(err)
}
defer trace.Stop()
// trace.Start(os.Stderr)
// defer trace.Stop()
ch1 := make(chan string)
go func() {
ch1 <- "hello world"
}()
<-ch1
}
直接启动就可以得到trace1.out文件
2、pprof
1)查看内存使用情况
示例代码
package main
import (
"log"
"net/http"
_ "net/http/pprof"
"os"
"runtime"
"runtime/trace"
"time"
)
func readMemStats() {
var ms runtime.MemStats
runtime.ReadMemStats(&ms)
log.Printf(" ===> Alloc:%d(bytes) HeapIdle:%d(bytes) HeapReleased:%d(bytes)", ms.Alloc, ms.HeapIdle, ms.HeapReleased)
}
func test() {
//slice 会动态扩容,用slice来做堆内存申请
container := make([]int, 8)
log.Println(" ===> loop begin.")
for i := 0; i < 32*1000*1000; i++ {
container = append(container, i)
if i == 16*1000*1000 {
readMemStats()
}
}
log.Println(" ===> loop end.")
}
func main() {
f, err := os.Create("trace1.out")
if err != nil {
panic(err)
}
defer f.Close()
err = trace.Start(f)
if err != nil {
panic(err)
}
defer trace.Stop()
//启动pprof
go func() {
log.Println(http.ListenAndServe("0.0.0.0:10000", nil))
}()
log.Println(" ===> [Start].")
readMemStats()
test()
readMemStats()
log.Println(" ===> [force gc].")
runtime.GC() //强制调用gc回收
log.Println(" ===> [Done].")
readMemStats()
go func() {
for {
readMemStats()
time.Sleep(5 * time.Second)
}
}()
time.Sleep(20 * time.Second) //睡眠,保持程序不退出
}
启动
go run main.go
pprof
"打开浏览器"
http://127.0.0.1:10000/debug/pprof/heap?debug=1
就能看到目前的内存状态
代码中38–48的代码是为了程序结束后生成trace.out文件,同样可以使用trace工具查看
2)查看cpu使用
示例代码
package main
import (
"bytes"
"math/rand"
"time"
"log"
"net/http"
_ "net/http/pprof"
)
func test() {
log.Println(" ===> loop begin.")
for i := 0; i < 1000; i++ {
log.Println(genSomeBytes())
}
log.Println(" ===> loop end.")
}
//生成一个随机字符串
func genSomeBytes() *bytes.Buffer {
var buff bytes.Buffer
for i := 1; i < 20000; i++ {
buff.Write([]byte{'0' + byte(rand.Intn(10))})
}
return &buff
}
func main() {
go func() {
for {
test()
time.Sleep(time.Second * 1)
}
}()
//启动pprof
http.ListenAndServe("0.0.0.0:10000", nil)
}
编译后启动
go build .
浏览器打开
http://127.0.0.1:10000/debug/pprof/
点击profile,程序需要运行30s就能得到一个可以下载到本地的二进制文件profile。
使用pprof工具
go tool pprof [binary] [profile]
binary: 必须指向生成这个性能分析数据的那个二进制可执行文件;
profile: 必须是该二进制可执行文件所生成的性能分析数据文件
二者要严格匹配
执行命令后出现:
ype: cpu
Time: Sep 1, 2021 at 2:30pm (CST)
Duration: 10s, Total samples = 1.38s (13.79%)
Entering interactive mode (type "help" for commands, "o" for options)
(pprof) top
Showing nodes accounting for 1230ms, 89.13% of 1380ms total
Showing top 10 nodes out of 86
flat flat% sum% cum cum%
610ms 44.20% 44.20% 610ms 44.20% syscall.syscall
140ms 10.14% 54.35% 140ms 10.14% runtime.nanotime1
100ms 7.25% 61.59% 100ms 7.25% runtime.madvise
100ms 7.25% 68.84% 100ms 7.25% runtime.usleep
90ms 6.52% 75.36% 90ms 6.52% runtime.pthread_cond_wait
50ms 3.62% 78.99% 50ms 3.62% sync.(*Mutex).Unlock (inline)
40ms 2.90% 81.88% 90ms 6.52% math/rand.(*lockedSource).Int63
40ms 2.90% 84.78% 40ms 2.90% runtime.pthread_cond_signal
30ms 2.17% 86.96% 50ms 3.62% bytes.(*Buffer).Write
30ms 2.17% 89.13% 30ms 2.17% runtime.kevent
可以查看程序中各个函数的耗时和cpu使用情况