如何利用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. Samba通过ad域进行认证并限制空间大小《转载》

    本文实现了samba服务被访问的时候通过windows域服务器进行用户名和密码验证;认证通过的用户可以自动分配500M的共享空间;在用户通过windows域登陆系统的时候可以自动把这块空间映射成一块硬 ...

  2. <微信应用开发系列>定时刷新AccessToken

    微信内嵌H5站一直很火,很多公司也想借助微信的用户群和社交群来做点事情,所以对于各位代码君来说也算是一个研究方向吧. access_token是公众号的全局唯一票据,公众号调用各接口时都需使用acce ...

  3. DEV GridControl 根据单元格值改变背景色

    GridControl 根据单元格值改变背景色(需要用到CustomDrawCell事件) 方法1: private void gdvClient_CustomDrawCell(object send ...

  4. EF数据建模(一)

    大中型软件开发过程中常会使用ORM技术,ORM全称是“对象-关系映射Object-Relation-Mappping”.是将数据库中的数据对象的形式表现出来,并将通过面向对象的方式将这些对象组织起来, ...

  5. dug

    http://blog.csdn.net/ysy441088327/article/details/8992393 http://www.cnblogs.com/Leo_wl/p/4423922.ht ...

  6. 新建一个vs2010的MFC工程

    1.在新建mfc工程时Visual C++下的MFC MFC ActiveX Control用来生成MFC ActiveX控件程序 MFC Application用来生成MFC应用程序. MFC DL ...

  7. C# 操作 Excel

    1.NOIP (功能齐全,评价较高) http://www.codeproject.com/Tips/813187/Csharp-Read-and-write-Excel-xls-and-xlsx-f ...

  8. Arbitrage HDU

    Arbitrage                                              Time Limit: 2000/1000 MS (Java/Others)    Mem ...

  9. C# txt文件读写

    //读取文件内容 (1).使用FileStream类进行文件的读取,并将它转换成char数组,然后输出. ]; ]; public void Read() { try { FileStream fil ...

  10. file_get_contents 获取不了网页内容

    服务器在做验签的过程中,经常需要向渠道服务器获取某个用户的信息.一般有两种方法,curl和file_get_contents. 一般情况下,像这样用,不会有问题. public function Oa ...