golang 如何排查和定位GC问题

    最近在作文本处理的时候遇到一个很奇怪的现象。串行执行脚本可能只须要几秒钟,可是若是想给每行开个协程并发处理的话,执行时间却从几十秒到几十分钟不等,关键是执行的过程当中cpu的占用并不高。通过一系列的分析以后确认是gc致使的。因此想讲一下排查gc问题的一些小技巧,以后也会给出一些case:浏览器

    一。如何查看程序运行过程当中的GC信息呢?

    设置gctrace的变量值为1便可,这个既能够设置成环境变量,也能够选择按以下方式执行:bash

GODEBUG=gctrace=1  go run main.go
//GODEBUG=gctrace=1 ./main

GODEBUG=gctrace=1 表明只针对这个进程开启gc追踪功能。程序输出以下:并发

       

    对于上面每一行每一列的具体含义:函数

gc 1 @0.038s 1%: 0.55+0.12+0.081 ms clock, 2.2+0/0.42/1.1+0.32 ms cpu, 4->4->0 MB, 5 MB goal, 4 P。

1 表示第一次执行

@0.038s 表示程序执行的总时间

1% 垃圾回收时间占用总的运行时间百分比

0.018+1.3+0.076 ms clock 垃圾回收的时间,分别为STW(stop-the-world)清扫的时间, 并发标记和扫描的时间,STW标记的时间

0.054+0.35/1.0/3.0+0.23 ms cpu 垃圾回收占用cpu时间

4->4->3 MB 堆的大小,gc后堆的大小,存活堆的大小

5 MB goal 总体堆的大小

4 P 使用的处理器数量

    打开了GCTRACE以后对于gc执行的时间点、执行次数以及耗时可能已经有了初步的了解,可是对什么地方耗用大量内存并形成大量延迟可能并不清除。工具

二。如何定位gc问题所在?

    这一点主要使用pprof来实现。开启pprof也特别简单,用net/http/pprof包能够快速实现。只须要在以前的代码中加下面三行就能够:spa

import (
    "net/http"
    _ "net/http/pprof"
)
go func() {
            log.Println(http.ListenAndServe("localhost:8081", nil))
}()

    在程序启动以后,只须要在命令行或者浏览器输入如下命令便可:命令行

go tool pprof  http://127.0.0.1:8081/debug/pprof/heap       //查看堆的使用,即内存使用状况
go tool pprof  http://127.0.0.1:8081/debug/pprof/profile    //查看cpu耗时,会详细列出每一个函数的耗时
go tool pprof  http://127.0.0.1:8081/debug/pprof/goroutine  //当前在运行的goroutine状况以及总数

    能够看下profile的输出信息, flat表明单个函数的运行时间,而cum则是累加的时间,也会包括这个函数下面的子函数的累加时间,因此main.main确定是100%:debug

        

    若是想看具体的图示的话,可使用png命令将结果存成图片看,好比:code

        

    能够看下生成图片的样子, 有具体的箭头以及每一个函数占用的时间或者内存:协程

     

 

基本目前笔者用到的工具就这两个了,感受有收获的读者能够本身实验一下。接下来,我会不按期的分享一些遇到的GC问题的case,欢迎一块儿交流哈。

相关文章
相关标签/搜索