Golang性能调优入门
如何利用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性能调优入门的更多相关文章
- golang 性能调优分析工具 pprof(下)
golang 性能调优分析工具 pprof(上)篇, 这是下篇. 四.net/http/pprof 4.1 代码例子 1 go version go1.13.9 把上面的程序例子稍微改动下,命名为 d ...
- golang 性能调优分析工具 pprof (上)
一.golang 程序性能调优 在 golang 程序中,有哪些内容需要调试优化? 一般常规内容: cpu:程序对cpu的使用情况 - 使用时长,占比等 内存:程序对cpu的使用情况 - 使用时长,占 ...
- JVM性能调优入门
1. 背景 虽然大多数应用程序使用JVM的默认设置就能很好地工作,仍然有不少应用程序需要对JVM进行额外的配置才能达到其期望的性能要求. 现在JVM为了满足各种应用的需要,为程序运行提供了大量的JVM ...
- 【GoLang】golang垃圾回收 & 性能调优
golang垃圾回收 & 性能调优 参考资料: 如何监控 golang 程序的垃圾回收_Go语言_第七城市 golang的垃圾回收(GC)机制 - 两只羊的博客 - 博客频道 - CSDN.N ...
- Golang 的 协程调度机制 与 GOMAXPROCS 性能调优
作者:林冠宏 / 指尖下的幽灵 掘金:https://juejin.im/user/587f0dfe128fe100570ce2d8 博客:http://www.cnblogs.com/linguan ...
- 关于iOS性能调优
性能调优一直都是作为高阶iOS开发者的一个入门门槛,下面我搜集了日常查阅资料中见到的各种高质量调优博文,仅供参考 UIKit性能调优实战讲解 iOS 高效添加圆角效果实战讲解
- Spark Streaming性能调优详解
Spark Streaming性能调优详解 Spark 2015-04-28 7:43:05 7896℃ 0评论 分享到微博 下载为PDF 2014 Spark亚太峰会会议资料下载.< ...
- Go性能调优
文章引用自 Go性能调优 在计算机性能调试领域里,profiling 是指对应用程序的画像,画像就是应用程序使用 CPU 和内存的情况. Go语言是一个对性能特别看重的语言,因此语言中自带了 pr ...
- Spark性能调优-高级篇
前言 继基础篇讲解了每个Spark开发人员都必须熟知的开发调优与资源调优之后,本文作为<Spark性能优化指南>的高级篇,将深入分析数据倾斜调优与shuffle调优,以解决更加棘手的性能问 ...
随机推荐
- 什么是系统平均负载(Load average)
一.什么是系统平均负载(Load average)? 在Linux系统中,uptime.w.top等命令都会有系统平均负载load average的输出,那么什么是系统平均负载呢? Load Aver ...
- asp.net实现将网页内容输出到word并下载到本地
个人觉得要实现这个功能如果没有类库提供的几个关键函数,还是比较繁琐的.所以首先介绍几个将要在代码中使用的关键函数和参数,然后再说函数实现.注意问题等. 关键函数: 1.函数原型:Response.Ap ...
- Asp.Net Mvc5新特性
One ASP.NET:统一平台 BootStrap:免费Css响应式页面 路由标记属性:简单,控制器,操作,前缀,参数,URL ASP.NET WEB API 2:路由标记属性,Oauth2.0,O ...
- app打包,发布(同步发生冲突)
1:打包步骤: 1:桌面建立一个文件夹,名字叫keystore 2:点击build下面的 ,如下: 3:会出现如下界面: 4:下一步: 5:如果有keystore,请点击 choose exi ...
- Android异步请求
class MyTask_SendMessage extends AsyncTask<String, Void, String> { @Override protected void on ...
- Windows下使用ODBC API访问数据库之关键
本文采用SQL2005 + VS2008环境,以ODBC API方式成功连接数据库. 1.SQL安装和环境配置 这部分网上随便搜一下都有很多资料,而且很容易就可以配置成功. 注意的关键点: SA账号配 ...
- [OC笔记] static 关键字
在变量声明前加上static关键字,可以使局部变量保留多次方法调用所得到的值.当多个方法对一个静态变量进行操作时,多个方法共享同一个静态变量的值.
- bootstrap小结
bootstrap总结 bootstrap总结 base css 我分为了几大类 1,列表 .unstyled(无样式列表),.dl-horizontal(dl列表水平排列) 2,代码 code(行级 ...
- 基于nginx的rtmp的服务器(nginx-rtmp-module)
一,首先下载安装nginx需要依赖的库文件: 1.1,选定源码目录 选定目录 /usr/local/RTMP cd /usr/local/RTMP 1.2,安装PCRE库 cd /usr/local/ ...
- jQuery选择器的学习
jQuery的核心在于它的选择器,通过观看视频和阅读,发现jQuery选择器大体上的分类可分为这么几种(不同人方式不同,这里选择一个自认为比较好的): 1.基础选择器(对应api文档中的基本选择器和层 ...