Este é o nono dia da minha participação na Atividade de Criação de Notas Companheiras do "Quinto Acampamento de Treinamento Juvenil"
prefácio
O conteúdo principal deste artigo é o ajuste de desempenho do Go, ferramenta de análise de desempenho - introdução do pprof, processo de amostragem do pprof e análise de princípios.
Introdução
Em projetos reais, todos sabemos que a otimização é muito importante. Com o desenvolvimento iterativo no trabalho, a otimização do código deve ser realizada moderadamente e não excessivamente. A seguir estão os princípios de otimização para referência.
Princípios de otimização e ajuste de desempenho:
- Confie em dados, não em suposições
- Para localizar os maiores gargalos em vez de galhos
- Não otimize prematuramente
- não otimize demais
ferramenta de análise de desempenho
Queremos saber onde e quanto o aplicativo consome.Existe CPU
alguma Memory
ferramenta para detectá-lo?
pprof
É uma ferramenta que pprof
pode ser usada para visualizar e analisar dados de análise de desempenho. A seguir apresentaremos o pprof e uma introdução simples ao seu uso.
pprof
É uma poderosa ferramenta de análise de desempenho que pode capturar dados de status de execução multidimensionais. Go
Ele integra ferramentas de amostragem no nível da linguagem e pode obter informações de execução como , , e profile
assim por diante durante a execução do programa . Isso envolverá pacotes como , e get Os dados vêm em duas formas: formal e gerado por documento.cpu
heap
block
traces
runtime/pprof
net/http/pprof
profile
web
profile
combate pprof
construção do projeto
Para criar um projeto de pprof
prática, o github
projeto de código aberto anterior é usado aqui. Este projeto incorporou alguns códigos de bomba com antecedência, resultando em problemas de desempenho observáveis. A execução deste projeto ocupará o 1CPU
núcleo e o excesso de 1GB
memória.
Endereço do projeto de código aberto: github.com/wolfogre/go…
Depois de clonar o projeto, insira-o no terminal go run main.go
para executar o projeto.
visualização do indicador
打开浏览器,输入地址 http://localhost:6060/debug/pprof 即可,如图。
从页面中可以查到,内存、block、协程、堆等分配的情况以及锁的操作等。
CPU
首先看一下CPU的运行情况,打开电脑自带的活动管理器,可以看到此项目在我的电脑上占了48%
的CPU。
pprof在每运行一段时间后,就会把运行信息输出到文件中,我们可以通过命令来获取文件。
在终端中输入命令,获取文件:
go tool pprof "http://localhost:6060/debug/pprof/profile?seconds=10"
复制代码
topN
命令:top
用于查看占用资源最多的函数
参数说明:
flat
: 当前函数本身的执行耗时flat%
:flat
占CPU
总时间的比例sum%
: 上面每一行的flat%
总和cum
: 当前函数本身加上其周期函数的总耗时cum%
:cum
占CPU
总时间的比例
从图中可以看到,Flat
列有的是0
,有的不是0
,那么Flat
在什么情况下等于Cum
?什么情况下等于0
呢?
根据上述参数说明,可以知道:
- Flat == Cum,说明函数中没有调用其他函数
- Flat == 0,说明函数中只有其他函数的调用
通过top
命令,得出Eat
函数是最消耗CPU
的,下面介绍如何定位到代码的具体行。
list
命令:list
可以根据指定的正则表达式查找代码行
输入命令list Eat
,从输出结果里可以看到对应的文件为tiger.go
,而且具体的代码行为24
行的for
循环。
web
有时候根据命令行查看结果不是很直观,pprof还提供了可视化的查看方式。
命令: web
将调用关系生成可视化文件,可以输出可视化调用量以及每个节点的资源占用数据。
找到代码进行更改,将循环次数改小一些,再次启动项目,查看资源占用情况,可以发现CPU已经没有那么高了。
Heap
经过代码的改造,可以发现CPU的问题已经解决了,但是内存使用还是很高。
这次直接以可视化的方法查看,输入以下命令,打开堆内存的占用情况:
go tool pprof -http=:8080 "http://localhost:6060/debug/pprof/heap"
复制代码
打开之后,会出现一下界面:
从上图我们一眼就可以看出,Mouse
这个对象的Steal
方法占用的内存最多。
打开View
->Source
视图,还可以看到具体的代码文件以及对应的行数。
找到对应的代码,将代码进行注释,然后看下资源占用情况。
注释掉mouse.go
文件的第50
行。
重新运行项目,查看资源占用已经很低了。
采样说明,SAMPLE
菜单中有几个选项,对应说明如下:
- alloc_objects: 程序累计申请的对象数
- alloc_space: 程序累计申请的内存大小
- inuse_objects: 程序当前持有的对象数
- inuse_space: 程序当前占用的内存大小
协程
goroutine
泄露也会导致内存泄露
以可视化的方法查看,输入以下命令,打开堆内存的占用情况:
go tool pprof -http=:8080 "http://localhost:6060/debug/pprof/goroutine"
复制代码
火焰图说明:
- 由上到下标识调用顺序
- 每一块代表一个函数,越长代表占用CPU时间更长
- 火焰图是动态的,支持点击块进行分析
切换到Source视图,查看代码具体位置。
可以看出wolf.go
文件里的第34
行,协程里进行了睡眠30s
,修改此处代码即可修复该问题。
mutex
通过pprof
查看锁相关问题,比如加锁时间长等。
执行命令:
go tool pprof -http=:8080 "http://localhost:6060/debug/pprof/mutex"
复制代码
输出界面如下:
切换到代码视图:
可以发现,wolf.go文件里在释放锁前,进行了睡眠操作,对此处代码进行修改即可修复问题。
block
检查代码中是否存在阻塞,执行命令:
go tool pprof -http=:8080 "http://localhost:6060/debug/pprof/block"
复制代码
输出界面如下:
切换到Source
视图,可以看到cat.go
文件里存在阻塞行为:
同样的,通过top
命令也可以看到存在问题的文件。
pprof原理
下面介绍一下pprof的采样过程以及实现原理。
CPU
采样对象:函数调用和他们占用的时间
采样率:100次/秒,固定值
采样时间:从手动启动到手动结束
采样详细流程如下:
流程说明:
- 操作系统:每10ms向进程发送一次
SIGPROF
信号 - 进程:每次接收到
SIGPROF
信号会记录调用堆栈 - 写缓冲:每100ms读取已经记录的调用栈并写入输出流
堆内存
堆内存采样过程如下:
- 采样程序通过内存分配器在堆上分配和释放内存,记录分配/释放的大小和数量
- 采样率:每分配512KB记录一次,可在运行开头修改,1为每次分配均记录
- 采样时间:从程序运行开始到采样时
- 采样指标:alloc_space, alloc_objects, inuse_space, inuse_objects
- 计算方式:inuse = alloc - free
协程&线程创建
协程和线程创建在实现上非常的相似,都是会在STW之后,遍历所有goroutine/所有线程的列表并输出堆栈,最后Start The World继续运行。这个采样是立刻触发的全量记录,可以通过比较两个时间点的差值来得到某一时间段的指标。
协程(Goroutine)
记录所有用户发起且在运行中的goroutine(即入口非runtime开头的)runtime.main的调用栈信息
线程创建(ThreadCreate)
记录程序创建的所有系统线程的信息
协程和线程创建的采样流程如下:
Block&Mutex
阻塞和锁竞争这两个指标在流程和原理也非常相似,这两个采样记录的都是对应操作发生的调用栈、次数和耗时,不过这两个指标的采样率含义并不相同。
A taxa de amostragem da operação de bloqueio é um "limiar", e a operação de bloqueio que consome mais do que o tempo limite será gravada, e 1 significa que todas as operações serão gravadas.
A taxa de amostragem da competição de bloqueio é uma "proporção". Durante o tempo de execução, apenas uma proporção fixa de operações de bloqueio será registrada por meio de números aleatórios e 1 significa que cada operação será gravada.
Operações de amostragem para operações de bloqueio:
- O número e o tempo gasto nas operações de bloqueio de amostragem
- Taxa de amostragem: Somente quando o tempo de bloqueio exceder o limite, ele será registrado e 1 é registrado para cada bloqueio
Operações de amostragem para competição de bloqueio:
- Amostragem do número de vezes e tempo gasto na competição por fechaduras
- Taxa de amostragem: grava apenas uma proporção fixa de operações de bloqueio, 1 para cada bloqueio é registrado
O processo de amostragem de bloqueio e competição de bloqueio é o seguinte:
Resumir
O conteúdo principal deste artigo é a ferramenta de ajuste e análise de desempenho Go - pprof
, que pprof
fornece métodos de solução de problemas, como linha de comando e visualização. Este artigo verifica os problemas de desempenho existentes no código por meio da operação real do pprof
código CPU
. Problemas em vários aspectos, como como memória, pilha, co-rotina block
, bloqueio, etc.
Embora o exemplo seja relativamente simples, ele nos permite aprender rapidamente como usar pprof
a ferramenta e estabelece uma boa base para solução de problemas e otimização de desempenho no futuro.