Golang 性能测试 (2) 性能分析

栏目: IT技术 · 发布时间: 4年前

内容简介:本文介绍 golang 如何做性能分析。对服务做了基准性能测试后,如果服务出现问题,可以通过性能分析工具,查出消耗资源的瓶颈,并做针对性的性能优化。Golang 语言也为我们提供了方便的性能分析工具pprof,方便我们做必要的服务优化。pprof 可以做cpu分析,统计所有调用方法执行的时间片(通过采样); 可以查看内存分配,找到是否有内存泄漏,哪里泄露了(调用栈);还可以查看Block、事件调用,互斥锁等。可谓麻雀虽小,五脏俱全。Golang 提供了两种分析的工具,一种是web工具,直接引入即可;另一种是

本文介绍 golang 如何做性能分析。

对服务做了基准性能测试后,如果服务出现问题,可以通过性能分析工具,查出消耗资源的瓶颈,并做针对性的性能优化。

Golang 语言也为我们提供了方便的性能分析工具pprof,方便我们做必要的服务优化。pprof 可以做cpu分析,统计所有调用方法执行的时间片(通过采样); 可以查看内存分配,找到是否有内存泄漏,哪里泄露了(调用栈);还可以查看Block、事件调用,互斥锁等。可谓麻雀虽小,五脏俱全。Golang 提供了两种分析的工具,一种是web工具,直接引入即可;另一种是命令行交互工具,需要抓取prof 数据,再做详细分析。

WEB 工具

golang 性能分析 工具 主要有几种,最常用的是使用web 界面的工具。我们举个简单的例子,将一个map数据做编码,编码100w次,例子如下:

package main

import "encoding/json"
import _ "net/http/pprof"
import "net/http"

func main() {
  mapData := 
  mapData := map[string]string{
    "abcdefg1":  "aaaaaaaaaaaaaaaaaaaa",
    "abcdefg2":  "aaaaaaaaaaaaaaaaaaaa",
    "abcdefg3":  "aaaaaaaaaaaaaaaaaaaa",
    "abcdefg4":  "aaaaaaaaaaaaaaaaaaaa",
    "abcdefg5":  "aaaaaaaaaaaaaaaaaaaa",
    "abcdefg6":  "aaaaaaaaaaaaaaaaaaaa",
    "abcdefg7":  "aaaaaaaaaaaaaaaaaaaa",
    "abcdefg8":  "aaaaaaaaaaaaaaaaaaaa",
    "abcdefg9":  "aaaaaaaaaaaaaaaaaaaa",
    "abcdefg10": "aaaaaaaaaaaaaaaaaaaa",
  }

  go func() {
    for i := 0; i < 100000000; i++ {
      _, _ = json.Marshal(data)
    }
  }()
  http.ListenAndServe("0.0.0.0:8080", nil)
}

引入 "net/http/pprof" 包,将自动在默认的http中添加相关 pprof 的处理方法(当然也可以自己添加了)。

我们通过访问 /debug/pprof/ 就可以打开对应的web 界面。

  • allocs 过去所有内存分配的采样。
  • block 查看阻塞同步的堆栈
  • cmdline 当前进程的命令行
  • goroutine 所有协程的调用栈
  • heap 当前活动对象的内存分配
  • mutex 竞态互斥锁的调用栈
  • profile 获取一个30s(可以通过seconds 参数指定)的cpu 采样prof 文件 (可以用 go tool pprof 分析)
  • threadcreate 导致创建了新系统线程的调用栈
  • trace 抓一个当前执行的trace包,可以捕获各种事件(可以用go tool trace 做可视化分析)

Golang 性能测试 (2) 性能分析

命令行交互

命令行工具,需要先抓取一段采样数据,采样数据可以通过web 的 profile 链接直接下载,也可以不启动web服务,直接采样。直接采样的好处是,可以直接采样我们需要优化的代码段的数据,而web采样的数据不一定会抓到我们执行的代码段(毕竟是通过采样实现的)。下面我们写一个直接采样的例子:

package main

import "encoding/json"
import "runtime/pprof"
import "os"
import "log"

func main() {
  cpuprofile := "json_map.prof"
  mapData := map[string]string{
      "abcdefg1":  "aaaaaaaaaaaaaaaaaaaa",
      "abcdefg2":  "aaaaaaaaaaaaaaaaaaaa",
      "abcdefg3":  "aaaaaaaaaaaaaaaaaaaa",
      "abcdefg4":  "aaaaaaaaaaaaaaaaaaaa",
      "abcdefg5":  "aaaaaaaaaaaaaaaaaaaa",
      "abcdefg6":  "aaaaaaaaaaaaaaaaaaaa",
      "abcdefg7":  "aaaaaaaaaaaaaaaaaaaa",
      "abcdefg8":  "aaaaaaaaaaaaaaaaaaaa",
      "abcdefg9":  "aaaaaaaaaaaaaaaaaaaa",
      "abcdefg10": "aaaaaaaaaaaaaaaaaaaa",
  }

  if cpuprofile != "" {
      f, err := os.Create(cpuprofile)
      if err != nil {
          log.Fatal(err)
      }

      pprof.StartCPUProfile(f)
      defer pprof.StopCPUProfile()
  }

  for i := 0; i < 1000000; i++ {
      _, _ = json.Marshal(mapData)
  }
}

然后我们通过如下命令进入交互模式:

[root@localhost pprof]# go tool pprof json_map.prof
File: json_map_1
Type: cpu
Time: Apr 11, 2020 at 6:49pm (CST)
Duration: 7.38s, Total samples = 7.12s (96.46%)
Entering interactive mode (type "help" for commands, "o" for options)
(pprof)

交互模式,也提供了丰富的命令查看prof文件中的数据,例如如下使用top10 查看代码执行cpu占比top10 的方法。

(pprof) top10
Showing nodes accounting for 3470ms, 48.74% of 7120ms total
Dropped 78 nodes (cum <= 35.60ms)
Showing top 10 nodes out of 87
      flat  flat%   sum%        cum   cum%
     570ms  8.01%  8.01%     1100ms 15.45%  encoding/json.(*encodeState).string
     550ms  7.72% 15.73%     1850ms 25.98%  runtime.mallocgc
     460ms  6.46% 22.19%      460ms  6.46%  runtime.memmove
     410ms  5.76% 27.95%      540ms  7.58%  runtime.mapaccess2
     320ms  4.49% 32.44%      350ms  4.92%  runtime.heapBitsSetType
     290ms  4.07% 36.52%      970ms 13.62%  runtime.typedmemmove
     230ms  3.23% 39.75%      230ms  3.23%  runtime.nextFreeFast
     220ms  3.09% 42.84%      220ms  3.09%  runtime.memclrNoHeapPointers
     210ms  2.95% 45.79%      210ms  2.95%  cmpbody
     210ms  2.95% 48.74%     6720ms 94.38%  encoding/json.mapEncoder.encode

还有其他功能,例如绘制调用图,内存分配图等,可以通过help查看:

Golang 性能测试 (2) 性能分析

除此之外, go tool profile 还有另外的打开模式。例如,通过web服务查看prof 文件。

执行如下命令,通过web服务查看prof文件:

[root@localhost pprof]# go tool pprof -http=:8080 json_map.prof

可以查看进程调用图,看到各调用函数的执行事件。

Golang 性能测试 (2) 性能分析

可以查看火焰图,具体分析哪些方法有优化空间。

Golang 性能测试 (2) 性能分析

  • 还可以查看Peek (调用者与被调用者匹配关系)

Golang 性能测试 (2) 性能分析

  • 可以从源码角度查看执行时间占比。

Golang 性能测试 (2) 性能分析

  • 也可以通过反汇编的代码角度查看执行时间占比。

Golang 性能测试 (2) 性能分析

除此之外,还可以命令行方式直接抓取web工具中的profile 数据做分析。(实际看来和自己抓取没什么区别,只是方便了而已)

其他

golang 目前提供的性能分析工具已经比较齐全了。本文只是对目前已经使用的功能做简单总结,其他功能还待我们一起去探索。

本文使用的 go 版本为1.13

Golang 性能测试 (2) 性能分析

下一篇将对 go tool 的另一神器 go tool trace 做简单总结。

欢迎关注我们的微信公众号,每天学习Go知识

Golang 性能测试 (2) 性能分析

以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

游戏引擎架构

游戏引擎架构

[美] Jason Gregory (杰森.格雷戈瑞) / 叶劲峰 / 电子工业出版社 / 2014-1 / 128.00元

《游戏引擎架构》同时涵盖游戏引擎软件开发的理论及实践,并对多方面的题目进行探讨。本书讨论到的概念及技巧实际应用于现实中的游戏工作室,如艺电及顽皮狗。虽然书中采用的例子通常依据一些专门的技术,但是讨论范围远超于某个引擎或API。文中的参考及引用也非常有用,可让读者继续深入游戏开发过程的任何特定方向。 《游戏引擎架构》为一个大学程度的游戏编程课程而编写,但也适合软件工程师、业余爱好者、自学游戏程......一起来看看 《游戏引擎架构》 这本书的介绍吧!

在线进制转换器
在线进制转换器

各进制数互转换器

XML、JSON 在线转换
XML、JSON 在线转换

在线XML、JSON转换工具

XML 在线格式化
XML 在线格式化

在线 XML 格式化压缩工具