如何利用golang自带的profile工具进行应用程序的性能调优,前一段时间我做的日志分析系统在线上遇到了一个问题,就是分任务的系统down机了,日志处理延迟了10几个小时,这个时候任务分发系统重启之后开始分发任务,但是一下子就承受了十几个并发任务,导致内存消耗过快,直接吃掉了16G的内存,这可急坏了我啊。所以赶紧开始做性能优化。

性能优化我主要从以下几个方面进行了测试和调优:

  • CPU Profiling
  • Mem Profiling
  • GC & HEAP

我采用了如下的profile工具代码:

package main

import (

"fmt"

"log"

"os"

"runtime"

"runtime/debug"

"runtime/pprof"

"strconv"

"sync/atomic"

"syscall"

"time"

)

var heapProfileCounter int32

var startTime = time.Now()

var pid int

func init() {

pid = os.Getpid()

}

func StartCPUProfile() {

f, err := os.Create("cpu-" + strconv.Itoa(pid) + ".pprof")

if err != nil {

log.Fatal(err)

}

pprof.StartCPUProfile(f)

}

func StopCPUProfile() {

pprof.StopCPUProfile()

}

func StartBlockProfile(rate int) {

runtime.SetBlockProfileRate(rate)

}

func StopBlockProfile() {

filename := "block-" + strconv.Itoa(pid) + ".pprof"

f, err := os.Create(filename)

if err != nil {

log.Fatal(err)

}

if err = pprof.Lookup("block").WriteTo(f, 0); err != nil {

log.Fatalf(" can't write %s: %s", filename, err)

}

f.Close()

}

func SetMemProfileRate(rate int) {

runtime.MemProfileRate = rate

}

func GC() {

runtime.GC()

}

func DumpHeap() {

filename := "heap-" + strconv.Itoa(pid) + "-" + strconv.Itoa(int(atomic.AddInt32(&heapProfileCounter, 1))) + ".pprof"

f, err := os.Create(filename)

if err != nil {

fmt.Fprintf(os.Stderr, "testing: %s", err)

return

}

if err = pprof.WriteHeapProfile(f); err != nil {

fmt.Fprintf(os.Stderr, "testing: can't write %s: %s", filename, err)

}

f.Close()

}

func showSystemStat(interval time.Duration, count int) {

usage1 := &syscall.Rusage{}

var lastUtime int64

var lastStime int64

counter := 0

for {

//http://man7.org/linux/man-pages/man3/vtimes.3.html

syscall.Getrusage(syscall.RUSAGE_SELF, usage1)

utime := usage1.Utime.Sec*1000000000 + usage1.Utime.Usec

stime := usage1.Stime.Sec*1000000000 + usage1.Stime.Usec

userCPUUtil := float64(utime-lastUtime) * 100 / float64(interval)

sysCPUUtil := float64(stime-lastStime) * 100 / float64(interval)

memUtil := usage1.Maxrss * 1024

lastUtime = utime

lastStime = stime

if counter > 0 {

fmt.Printf("cpu: %3.2f%% us  %3.2f%% sy, mem:%s \n", userCPUUtil, sysCPUUtil, toH(uint64(memUtil)))

}

counter += 1

if count >= 1 && count < counter {

return

}

time.Sleep(interval)

}

}

func ShowSystemStat(seconds int) {

go func() {

interval := time.Duration(seconds) * time.Second

showSystemStat(interval, 0)

}()

}

func PrintSystemStats() {

interval := time.Duration(1) * time.Second

showSystemStat(interval, 1)

}

func ShowGCStat() {

go func() {

var numGC int64

interval := time.Duration(100) * time.Millisecond

gcstats := &debug.GCStats{PauseQuantiles: make([]time.Duration, 100)}

memStats := &runtime.MemStats{}

for {

debug.ReadGCStats(gcstats)

if gcstats.NumGC > numGC {

runtime.ReadMemStats(memStats)

printGC(memStats, gcstats)

numGC = gcstats.NumGC

}

time.Sleep(interval)

}

}()

}

func PrintGCSummary() {

memStats := &runtime.MemStats{}

runtime.ReadMemStats(memStats)

gcstats := &debug.GCStats{PauseQuantiles: make([]time.Duration, 100)}

debug.ReadGCStats(gcstats)

printGC(memStats, gcstats)

}

func printGC(memStats *runtime.MemStats, gcstats *debug.GCStats) {

if gcstats.NumGC > 0 {

lastPause := gcstats.Pause[0]

elapsed := time.Now().Sub(startTime)

overhead := float64(gcstats.PauseTotal) / float64(elapsed) * 100

allocatedRate := float64(memStats.TotalAlloc) / elapsed.Seconds()

fmt.Printf("NumGC:%d Pause:%s Pause(Avg):%s Overhead:%3.2f%% Alloc:%s Sys:%s Alloc(Rate):%s/s Histogram:%s %s %s \n",

gcstats.NumGC,

toS(lastPause),

toS(avg(gcstats.Pause)),

overhead,

toH(memStats.Alloc),

toH(memStats.Sys),

toH(uint64(allocatedRate)),

toS(gcstats.PauseQuantiles[94]),

toS(gcstats.PauseQuantiles[98]),

toS(gcstats.PauseQuantiles[99]))

} else {

// while GC has disabled

elapsed := time.Now().Sub(startTime)

allocatedRate := float64(memStats.TotalAlloc) / elapsed.Seconds()

fmt.Printf("Alloc:%s Sys:%s Alloc(Rate):%s/s\n",

toH(memStats.Alloc),

toH(memStats.Sys),

toH(uint64(allocatedRate)))

}

}

func avg(items []time.Duration) time.Duration {

var sum time.Duration

for _, item := range items {

sum += item

}

return time.Duration(int64(sum) / int64(len(items)))

}

// human readable format

func toH(bytes uint64) string {

switch {

case bytes < 1024:

return fmt.Sprintf("�", bytes)

case bytes < 1024*1024:

return fmt.Sprintf("%.2fK", float64(bytes)/1024)

case bytes < 1024*1024*1024:

return fmt.Sprintf("%.2fM", float64(bytes)/1024/1024)

default:

return fmt.Sprintf("%.2fG", float64(bytes)/1024/1024/1024)

}

}

// short string format

func toS(d time.Duration) string {

u := uint64(d)

if u < uint64(time.Second) {

switch {

case u == 0:

return "0"

case u < uint64(time.Microsecond):

return fmt.Sprintf("%.2fns", float64(u))

case u < uint64(time.Millisecond):

return fmt.Sprintf("%.2fus", float64(u)/1000)

default:

return fmt.Sprintf("%.2fms", float64(u)/1000/1000)

}

} else {

switch {

case u < uint64(time.Minute):

return fmt.Sprintf("%.2fs", float64(u)/1000/1000/1000)

case u < uint64(time.Hour):

return fmt.Sprintf("%.2fm", float64(u)/1000/1000/1000/60)

default:

return fmt.Sprintf("%.2fh", float64(u)/1000/1000/1000/60/60)

}

}

}

Golang性能调优入门的更多相关文章

  1. golang 性能调优分析工具 pprof(下)

    golang 性能调优分析工具 pprof(上)篇, 这是下篇. 四.net/http/pprof 4.1 代码例子 1 go version go1.13.9 把上面的程序例子稍微改动下,命名为 d ...

  2. golang 性能调优分析工具 pprof (上)

    一.golang 程序性能调优 在 golang 程序中,有哪些内容需要调试优化? 一般常规内容: cpu:程序对cpu的使用情况 - 使用时长,占比等 内存:程序对cpu的使用情况 - 使用时长,占 ...

  3. JVM性能调优入门

    1. 背景 虽然大多数应用程序使用JVM的默认设置就能很好地工作,仍然有不少应用程序需要对JVM进行额外的配置才能达到其期望的性能要求. 现在JVM为了满足各种应用的需要,为程序运行提供了大量的JVM ...

  4. 【GoLang】golang垃圾回收 & 性能调优

    golang垃圾回收 & 性能调优 参考资料: 如何监控 golang 程序的垃圾回收_Go语言_第七城市 golang的垃圾回收(GC)机制 - 两只羊的博客 - 博客频道 - CSDN.N ...

  5. Golang 的 协程调度机制 与 GOMAXPROCS 性能调优

    作者:林冠宏 / 指尖下的幽灵 掘金:https://juejin.im/user/587f0dfe128fe100570ce2d8 博客:http://www.cnblogs.com/linguan ...

  6. 关于iOS性能调优

    性能调优一直都是作为高阶iOS开发者的一个入门门槛,下面我搜集了日常查阅资料中见到的各种高质量调优博文,仅供参考 UIKit性能调优实战讲解 iOS 高效添加圆角效果实战讲解

  7. Spark Streaming性能调优详解

    Spark Streaming性能调优详解 Spark  2015-04-28 7:43:05  7896℃  0评论 分享到微博   下载为PDF 2014 Spark亚太峰会会议资料下载.< ...

  8. Go性能调优

    文章引用自   Go性能调优 在计算机性能调试领域里,profiling 是指对应用程序的画像,画像就是应用程序使用 CPU 和内存的情况. Go语言是一个对性能特别看重的语言,因此语言中自带了 pr ...

  9. Spark性能调优-高级篇

    前言 继基础篇讲解了每个Spark开发人员都必须熟知的开发调优与资源调优之后,本文作为<Spark性能优化指南>的高级篇,将深入分析数据倾斜调优与shuffle调优,以解决更加棘手的性能问 ...

随机推荐

  1. js-浏览器DOM

    1.window尺寸 适配所有浏览器的尺寸方案 var w=window.innerWidth|| document.documentElement.clientWidth|| document.bo ...

  2. cell的各种使用和赋值 总结

    cell可以分为:自定义cell,系统的cell ,cell的自适应,.xib的cell //第一种cell:系统cell 在 UIViewController下创建UITableView //1.0 ...

  3. windows应用中调用DLL一步步试验

    试验环境: PC:win10 build 10143 IDE: vs2015 RC WinPhone: win10 build 10136 简单界面,点按钮,算加法 一.主程用C++ 1.新建visu ...

  4. 利用JS实现HTML TABLE的分页

    有时候table的列数太长,不利于使用者查询,所以利用JS做了一个table的分页,以下为相关代码 一.JS代码 <script type="text/javascript" ...

  5. Python学习笔记九-文件读写

    1,读取文件: f=open('目录','读写模式',encoding='gbk,error='egiong') 后三项可以不写但是默认是' r'读模式:open函数打开的文件对象会自动加上read( ...

  6. Python批量修改文本文件内容

    Python批量替换文件内容,支持嵌套文件夹 import os path="./" for root,dirs,files in os.walk(path): for name ...

  7. Android Support Library package简介

    转自http://my.oschina.net/chengliqun/blog/148451 N久未做android了,以前做的时候,2.2才刚出来,现在android都更新到了4.3了,而从前一段时 ...

  8. C语言多维数组的地址

    设有整型二维数组a[3][4]如下: 0   1   2   3 4   5   6   7 8   9  10  11  它的定义为:     int a[3][4]={{0,1,2,3},{4,5 ...

  9. UVa 232 Crossword Answers

     Crossword Answers  A crossword puzzle consists of a rectangular grid of black and white squares and ...

  10. 养成代码注释习惯,帮助你更好使用NetBeans导航器

    在使用NetBeans编写php代码时,为了在一个类中,或者在方法库文件中快速找到你想要找的函数或方法,通常我们会使用NetBeans的导航器. 我们看一个导航器的事例: 大家知道,在php中代码习惯 ...