Go性能调优1 – 性能调优工具

准备工作

  • 安装 graphviz
    • brew install graphviz
  • 将 $GOPATH/bin 加入 $PATH
    • Mac.OS:在 .bash_profile中修改路径
  • 安装 go-torch (火炬图)

通过文件方式输出 Profile

Go支持的多种 Profile

go help testflag

https://golang.org/src/runtime/pprof/pprof.go

我们来看一下 用于生成profile的示例代码:

prof.go

package main

import (
    "log"
    "math/rand"
    "os"
    "runtime/pprof"
    "time"
)

const (
    row = 10000
    col = 10000
)

func fillMatrix(m *[row][col]int) {
    s := rand.New(rand.NewSource(time.Now().UnixNano()))

    for i := 0; i < row; i++ {
        for j := 0; j < col; j++ {
            m[i][j] = s.Intn(100000)
        }
    }
}

func calculate(m *[row][col]int) {
    tmp := 0
    for i := 0; i < row; i++ {
        for j := 0; j < col; j++ {
            tmp += m[i][j]
        }
    }
}

func main() {
    // 创建输出文件
    f, err := os.Create("cpu.prof")
    if err != nil {
        log.Fatal("could not create CPU profile:", err)
    }

    // 获取系统信息
    if err := pprof.StartCPUProfile(f); err != nil { //监控cpu
        log.Fatal("could not start CPU profile:", err)
    }
    defer pprof.StopCPUProfile()

    // 主逻辑区,进行一些简单的代码运算
    x := [row][col]int{}
    fillMatrix(&x)
    calculate(&x)

    f1, err := os.Create("mem.prof")
    if err != nil {
        log.Fatal("could not create CPU profile:", err)
    }
    // runtime.GC()                                       // GC,获取最新的数据信息
    if err := pprof.WriteHeapProfile(f1); err != nil { //写入内存信息
        log.Fatal("could not write memory profile:", err)
    }
    f1.Close()

    f2, err := os.Create("goroutine.prof")
    if err != nil {
        log.Fatal("could not create goroutine profile:", err)
    }
    if gProf := pprof.Lookup("goroutine"); gProf == nil {
        log.Fatal("could not write goroutine profile")
    } else {
        gProf.WriteTo(f2, 0)
    }
    f2.Close()
}

pprof

  • 编译:go build ./prof.go
  • 运行:生成的可执行二进制文件./prof.go,生成对应的 cpu.prof、mem.prof、goroutine.prof
  • 查看:go tool pprof ./prof ./cpu.prof 进入一个交互式的控制台
File: prof
Type: cpu
Time: Nov 9, 2020 at 4:02pm (CST)
Duration: 200.45ms, Total samples = 20ms ( 9.98%)
Entering interactive mode (type "help" for commands, "o" for options)
(pprof) 

使用top命令查看 top CPU 的情况

(pprof) top
Showing nodes accounting for 2180ms, 99.09% of 2200ms total
Dropped 12 nodes (cum <= 11ms)
      flat  flat%   sum%        cum   cum%
     780ms 35.45% 35.45%     2150ms 97.73%  main.fillMatrix
     710ms 32.27% 67.73%     1100ms 50.00%  math/rand.(*Rand).Int31n
     270ms 12.27% 80.00%     1370ms 62.27%  math/rand.(*Rand).Intn
     220ms 10.00% 90.00%      220ms 10.00%  math/rand.(*rngSource).Uint64 (inline)
     110ms  5.00% 95.00%      330ms 15.00%  math/rand.(*rngSource).Int63
      60ms  2.73% 97.73%      390ms 17.73%  math/rand.(*Rand).Int63 (inline)
      30ms  1.36% 99.09%       30ms  1.36%  main.calculate
         0     0% 99.09%     2190ms 99.55%  main.main
         0     0% 99.09%      390ms 17.73%  math/rand.(*Rand).Int31 (inline)
         0     0% 99.09%     2190ms 99.55%  runtime.main
(pprof) 
  • flat 是对应函数本身使用的时间和所占的比例
  • cum 即cumulation,表示对应函数还调用了别的函数,总体加合在一起的执行时间和所占的比例

使用 list 命令查看指定函数详情

(pprof) list fillMatrix
Total: 2.20s
ROUTINE ======================== main.fillMatrix in /root/go_learn/src/ch31/tools/file/prof.go
     780ms      2.15s (flat, cum) 97.73% of Total
         .          .     15:
         .          .     16:func fillMatrix(m *[row][col]int) {
         .          .     17:   s := rand.New(rand.NewSource(time.Now().UnixNano()))
         .          .     18:
         .          .     19:   for i := 0; i < row; i++ {
      40ms       40ms     20:       for j := 0; j < col; j++ {
     740ms      2.11s     21:           m[i][j] = s.Intn(100000)
         .          .     22:       }
         .          .     23:   }
         .          .     24:}
         .          .     25:
         .          .     26:func calculate(m *[row][col]int) {
(pprof) 

可以看到所有的耗时基本是在 m[i][j] = s.Intn(100000) 这句;

也可以查看CPU耗时对应的图片

(pprof) svg
Generating report in profile001.svg

mem.prof 及 goroutine.prof 命令与cpu.prof 一样

使用 go-torch 生成火炬图

go-torch cpu.prof

通过HTTP方式输出 Profile

  • 简单,适合于持续性运行的应用
  • 在应用程序中导入import _ "net/http:/pprof,并启动 http server 即可
  • http://<host>:<port>/debug/pprof/
  • go tool pprof _http://<host>:<port>/debug/pprof/profile?seconds=10 (默认值为30秒)
  • go-torch -seconds 10 http://<host>:<port>/debug/pprof/profile

示例代码:
fb_server.go

package main

import (
    "fmt"
    "log"
    "net/http"
    _ "net/http/pprof"
)

// GetFibonacciserie function
func GetFibonacciserie(n int) []int {
    fidList := []int{1, 1}
    for i := 2; i < n; i++ {
        fidList = append(fidList, fidList[i-2]+fidList[i-1])
    }
    return fidList
}

func index(w http.ResponseWriter, r *http.Request) {
    w.Write([]byte("Welcome!"))
}

func createFBS(w http.ResponseWriter, r *http.Request) {
    var fbs []int
    for i := 0; i < 1000000; i++ {
        fbs = GetFibonacciserie(50)
    }
    w.Write([]byte(fmt.Sprintf("%v", fbs)))
}

func main() {
    http.HandleFunc("/", index)
    http.HandleFunc("/fb", createFBS)
    log.Fatal(http.ListenAndServe(":8081", nil))
}
  • 在浏览器查看结果:http://127.0.0.1:8081/fb
  • 在浏览器debug: http://127.0.0.1:8081/debug/pprof/
  • 在命令行:go tool pprof http://127.0.0.1:8081/debug/pprof/profile 可以看到跟文件是一样的进入一个交互的控制台
暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇