Go 程序的性能优化及 pprof 的使用

程序的性能优化无非就是对程序占用资源的优化。对于服务器而言,最重要的两项资源莫过于 CPU 和内存。性能优化,就是在对于不影响程序数据处理能力的情况下,我们通常要求程序的 CPU 的内存占用尽量低。反过来说,也就是当程序 CPU 和内存占用不变的情况下,尽量地提高程序的数据处理能力或者说是吞吐量。

Go 的原生工具链中提供了非常多丰富的工具供开发者使用,其中包括 pprof

对于 pprof 的使用要分成下面两部分来说。

Web 程序使用 pprof

先写一个简单的 Web 服务程序。程序在 9876 端口上接收请求。

package main

import (
"bytes"
"io/ioutil"
"log"
"math/rand"
"net/http" _ "net/http/pprof"
) func main() {
http.HandleFunc("/test", handler)
log.Fatal(http.ListenAndServe(":9876", nil))
} func handler(w http.ResponseWriter, r *http.Request) {
err := r.ParseForm()
if nil != err {
w.Write([]byte(err.Error()))
return
}
doSomeThingOne(10000)
buff := genSomeBytes()
b, err := ioutil.ReadAll(buff)
if nil != err {
w.Write([]byte(err.Error()))
return
}
w.Write(b)
} func doSomeThingOne(times int) {
for i := 0; i < times; i++ {
for j := 0; j < times; j++ { }
}
} func genSomeBytes() *bytes.Buffer {
var buff bytes.Buffer
for i := 1; i < 20000; i++ {
buff.Write([]byte{'0' + byte(rand.Intn(10))})
}
return &buff
}

可以看到我们只是简单地引入了 net/http/pprof ,并未显示地使用。

启动程序。

我们用 wrk 来简单地模拟请求。

wrk -c 400 -t 8 -d 3m http://localhost:9876/test

这时我们打开 http://localhost:9876/debug/pprof,会显示如下页面:

用户可以点击相应的链接浏览内容。不过这不是我们重点讲述的,而且这些内容看起来并不直观。

我们打开链接 http://localhost:9876/debug/pprof/profile 稍后片刻,可以下载到文件 profile

使用 Go 自带的 pprof 工具打开。go tool pprof test profile。(proof 后跟的 test 为程序编译的可执行文件)

输入 top 命令得到:

可以看到 cpu 占用前 10 的函数,我们可以对此分析进行优化。

只是这样可能还不是很直观。

我们输入命令 web(需要事先安装 graphviz,macOS 下可以 brew install graphviz),会在浏览器中打开界面如下:

可以看到 main.doSomeThingOne 占用了 92.46% 的 CPU 时间,需要对其进行优化。

Web 形式的 CPU 时间图对于优化已经完全够用,这边再介绍一下火焰图的生成。macOS 推荐使用 go-torch 工具。使用方法和 go tool pprof 相似。

go-torch test profile 会生成 torch.svg 文件。可以用浏览器打开,如图。

刚才只是讲了 CPU 的占用分析文件的生成查看,其实内存快照的生成相似。http://localhost:9876/debug/pprof/heap,会下载得到 heap.gz 文件。

我们同样可以使用 go tool pprof test heap.gz,然后输入 topweb 命令查看相关内容。

通用程序使用 pprof

我们写的 Go 程序并非都是 Web 程序,这时候再使用上面的方法就不行了。

我们仍然可以使用 pprof 工具,但引入的位置为 runtime/pprof

这里贴出两个函数,作为示例:

// 生成 CPU 报告
func cpuProfile() {
f, err := os.OpenFile("cpu.prof", os.O_RDWR|os.O_CREATE, 0644)
if err != nil {
log.Fatal(err)
}
defer f.Close() log.Println("CPU Profile started")
pprof.StartCPUProfile(f)
defer pprof.StopCPUProfile() time.Sleep(60 * time.Second)
fmt.Println("CPU Profile stopped")
} // 生成堆内存报告
func heapProfile() {
f, err := os.OpenFile("heap.prof", os.O_RDWR|os.O_CREATE, 0644)
if err != nil {
log.Fatal(err)
}
defer f.Close() time.Sleep(30 * time.Second) pprof.WriteHeapProfile(f)
fmt.Println("Heap Profile generated")
}

两个函数分别会生成 cpu.profheap.prof 文件。仍然可以使用 go tool pprof 工具进行分析,在此就不赘述。

Trace 报告

直接贴代码:

// 生成追踪报告
func traceProfile() {
f, err := os.OpenFile("trace.out", os.O_RDWR|os.O_CREATE, 0644)
if err != nil {
log.Fatal(err)
}
defer f.Close() log.Println("Trace started")
trace.Start(f)
defer trace.Stop() time.Sleep(60 * time.Second)
fmt.Println("Trace stopped")
}

使用工具 go tool trace 进行分析,会得到非常详细的追踪报告,供更深入的程序分析优化。由于报告内容比较复杂,且使用方法类似,就不继续了。读者可自行尝试。

贴张网上的图给大家大概看一下:

参考:https://github.com/caibirdme/hand-to-hand-optimize-go

Go 程序的性能优化及 pprof 的使用的更多相关文章

  1. 使用pprof及Go 程序的性能优化

    使用Golang 程序的性能优化及 Pprof 程序的性能优化无非就是对程序占用资源的优化.对于服务器而言,最重要的两项资源莫过于 CPU 和内存.性能优化,就是在对于不影响程序数据处理能力的情况下, ...

  2. 小程序Canvas性能优化实战

    以下内容转载自totoro的文章<小程序Canvas性能优化实战!> 作者:totoro 链接:https://blog.totoroxiao.com/canvas-perf-mini/ ...

  3. [daily][optimize] 一个小python程序的性能优化 (python类型转换函数引申的性能优化)

    前天,20161012,到望京面试.第四个职位,终于进了二面.好么,结果人力安排完了面试时间竟然没有通知我,也没有收到短信邀请.如果没有短信邀请门口的保安大哥是不让我进去大厦的.然后,我在11号接到了 ...

  4. 微信小程序之性能优化

    如果做前端仅仅停留在编码和实现业务功能上面,可能进步速度会有些慢,但是如果经历了对页面的性能优化之后而且有所成绩的话那就不同了,因为你对他背后的机制进行了研究,才能做好性能优化. 做微信小程序也是一样 ...

  5. Python 和 C/C++ 拓展程序如何性能优化?看这一篇文就够

    作者:王璐璐 | 旷视 MegEngine 架构师 一. 背景 在 MegEngine imperative runtime 的早期开发中,我们面临着一些的性能优化问题.除了一些已知需要重构的地方(早 ...

  6. Windows 程序启动性能优化(先载入EXE,后载入DLL,只取有限的代码载入内存,将CPU的IP指向程序的入口点)

    一.重定位链接时重定位:目标文件一般由多个节组成,编译器在编译每个目标文件时一般都是从0地址开始生成代码.当多个代码节合成一个代码段时,需要根据其在最终代码段中的位置做出调整.同时,链接器需要对已经解 ...

  7. JVM性能优化系列-(4) 编写高效Java程序

    4. 编写高效Java程序 4.1 面向对象 构造器参数太多怎么办? 正常情况下,如果构造器参数过多,可能会考虑重写多个不同参数的构造函数,如下面的例子所示: public class FoodNor ...

  8. 【腾讯Bugly干货分享】Android性能优化典范——第6季

    本文来自于腾讯bugly开发者社区,非经作者同意,请勿转载,原文地址:http://dev.qq.com/topic/580d91208d80e49771f0a07c 导语 这里是Android性能优 ...

  9. Android性能优化典范(二)

    Google前几天刚发布了Android性能优化典范第2季的课程,一共20个短视频,包括的内容大致有:电量优化,网络优化,Wear上如何做优化,使用对象池来提高效率,LRU Cache,Bitmap的 ...

随机推荐

  1. MySQL慢查询日志

    实验环境: OS X EI Captian + MySQL 5.7 一.配置MySQL自动记录慢查询日志 查看变量,也就是配置信息 show (global) variables like '%slo ...

  2. SDP

    SDP语法 一个SDP描述含有会话级信息和媒体级信息.会话级信息应用于整个会话.例如:它能成为会话始发者或者会话的名字.媒体级信息作用于特殊的媒体流.例如:它能作为一个编码器给音频流编码或者是给视频流 ...

  3. 一只猿:使用flask来做一个小应用

    上周 @萍姐 问我如何抓取天猫上面店铺的评分,看了下挺简单的,于是花了点时间写了个Python脚本,加上web.py做成一个web服务,使用起来还不错,今天来看的时候发现当时为了方便直接用web.py ...

  4. Vulkan Tutorial 26 view and sampler

    操作系统:Windows8.1 显卡:Nivida GTX965M 开发工具:Visual Studio 2017 在本章节我们将为图形管线创建另外两个资源来对图像进行采样.第一个资源我们之前已经接触 ...

  5. java编译出错信息汇总(更新)

    1. java.lang.ClassNotFoundException: com.mysql.jdbc.Driver 原因:缺包mysql-connector-java-5.1.7-bin.jar 2 ...

  6. javascript面向对象个人理解

    1. javascript面向对象特性:抽象性,封装性,继承性: 2. js中的对象:键值对的集合:比如说{key:value} 3.抽象性:用一个对象描述一个数据,需要抽取这个对象的核心数据:两个必 ...

  7. mac下,mysql5.7.18连接出错,错误信息为:Access denied for user 'root'@'localhost' (using password: YES)

    mac下,mysql5.7.18连接出错,错误信息为:Access denied for user 'root'@'localhost' (using password: YES)()里面的为shel ...

  8. hdu_1564: Play a game

    题目链接 看n的奇偶性,题解参见kuangbin的博客 http://www.cnblogs.com/kuangbin/archive/2013/07/22/3204654.html #include ...

  9. (转)AJax跨域:No 'Access-Control-Allow-Origin' header is present on the requested resource

    在本地用ajax跨域访问请求时报错: No 'Access-Control-Allow-Origin' header is present on the requested resource. Ori ...

  10. 6步就能搞出个react网站哈,玩一把!

    1.安装mk-tools命令行工具   $ npm i -g mk-tools   2.创建空website   $ mk website myDemo $ cd myDemo    3.clone应 ...