Como encontrar pontos de melhoria de performance

Nesse post vamos falar sobre a técnica de profiling, que consegue nos ajudar muito na hora de encontrar melhorias em relação a performance dos nossos programas, principalmente, consumo de memória e CPU.

Para realizar os testes, vamos recuperar o código que escrevemos no post “Qual a melhor forma de aumentar um array?

Apenas para relembrar, nesse post escrevemos 3 funções e 3 testes, um para cada função. Cada uma das funções mostrar uma forma diferente de expandir um array.

Tendo relembrado isso, vamos agora fazer o profiling de cada uma das funções e analisar o resultado.

Para coletar dados de cpu e memória, vamos adicionar as flags -memprofile e -cpuprofile no comando que executamos para fazer benchmark das funções.

Primeiro, vamos fazer o profiling da memória da função Append1 com o seguinte comando:

$ go test -bench=Append1 -cpu=8 -benchmem -benchtime=5s -count 5 -memprofile=mem.out

O output não mudou nada em relação a quando executamos somente o benchmark da função. No entanto um novo arquivo foi gerado, mem.out.

Para analizar esse arquivo, vamos executar o comando go tool pprof -http :8081 mem.out.

Ao executar esse comando, uma nova aba deve ter sido aberta no seu navegador com um diagrama parecido com o que está abaixo.

profiling Append1

Esse diagrama mostra as etapas da execução do programa, assim como onde foi gasto a maior quantidade de recurso. Como podemos ver, todas as etapas anteriores ao Append1 gastaram 0 de 13.26GB, ou seja, todo o consumo de memória ocorreu na função Append1, o que faz sentido.

Agora, para ficar mas fácil a comparação entre as 3 funções que escrevemos, vamos executar novamente o comando, mas sem definir qual função queremos.

$ go test -bench=. -cpu=8 -benchmem -benchtime=5s -count 5 -memprofile=mem.out

Após finalizar o benchmark, vamos executar novamente o go tool pprof -http :8081 mem.out.

profiling memória

Como podemos ver na imagem acima, lá no topo ele diz que foi consumido 54.14GB de memória. Mais abaixo, conseguimos ver quando cada uma das funções consumiu.

Para fazer o profiling de CPU, vamos executar o comando de benchmark novamente alterando a flag -memprofile para -cpuprofile.

$ go test -bench=. -cpu=8 -benchmem -benchtime=5s -count 5 -cpuprofile=cpu.out

Por ser muito grande o resultado desse diagrama, vou cortar a imagem apenas na parte que mais nos interessa.

profiling cpu

Nesse diagrama conseguimos ver cada etapa da execução interna do programa, inclusive etapas que nós não escrevemos diretamente, como o growslice e mallocgc.

Ao olhar para os tempos gastos em cada uma das funções, conseguimos ver que a função Append3 ainda é a melhor escolha, já que seu tempo total foi de 15.42s contra 18.18s e 19.46 das funções Append2 e Append1, respectivamente.

Como podemos ver, ao fazer profiling de uma aplicação, conseguimos facilmente identificar pontos onde está sendo gasto mais CPU ou memória. Com esses resultados nas mãos, conseguimos rever esses pontos para tentar melhorar a performance da aplicação.

Em um próximo post vou abordar como fazer profiling em APIs. Por isso, não deixe de se inscrever para receber todas nossas atualizações em sua caixa de email.

Deixem suas dúvidas nos comentários.

Até a próxima!


Subscreva

Fique por dentro de tudo o que acontece no mundo Go.

Deixe uma resposta