Attention: Here be dragons

This is the latest (unstable) version of this documentation, which may document features not available in or compatible with released stable versions of Godot.

O Profiler

Você executa seu jogo a partir do Godot e joga um pouco. É divertido, está ficando completo em termos de recursos e você sente que está chegando perto do lançamento.

Mas então, você abre a árvore de habilidades (skill tree), e o jogo trava completamente devido a algo que enroscou no seu código. Assistir à árvore de habilidades rolar como se fosse um slide show é inaceitável. O que deu errado? É o posicionamento dos elementos da árvore de habilidades, a interface de usuário (UI) ou a renderização?

Você poderia tentar otimizar tudo e executar o jogo repetidamente, mas você pode ser mais inteligente do que isso e estreitar as possibilidades. Entre no profiler do Godot.

Uma visão geral do analisador

Você pode abrir o profiler abrindo o painel Debugger e clicando na aba Profiler.

../../../_images/profiler.png

O profiler do Godot não funciona automaticamente porque o perfilamento consome muito desempenho. Ele precisa medir continuamente tudo o que acontece no jogo e reportar de volta ao depurador, por isso fica desativado por padrão.

Para iniciar o perfilamento, execute o seu jogo e depois foque novamente no editor. Clique no botão Start no canto superior esquerdo da aba Profiler. Você também pode marcar a opção Autostart, que fará com que o profiler inicie automaticamente na próxima vez que o projeto for executado. Observe que o estado da caixa de seleção Autostart não é preservado entre as sessões do editor.

Nota

O profiler atualmente não suporta scripts em C#. Scripts em C# podem ser perfilados usando o JetBrains Rider e o JetBrains dotTrace com o plugin de suporte ao Godot.

Você pode limpar os dados clicando no botão Clear a qualquer momento. Use o menu suspenso Measure (Medir) para alterar o tipo de dados que você mede. O painel de medições e o gráfico serão atualizados de acordo.

Os dados medidos

A interface do profiler é dividida em duas. Há uma lista de funções à esquerda e o gráfico de desempenho à direita.

As medições principais são frame time (tempo de quadro), physics frame (quadro de física), idle time (tempo ocioso) e physics time (tempo de física).

  • O frame time é o tempo que o Godot leva para executar toda a lógica de uma imagem inteira, desde a física até a renderização.

  • Physics frame é o tempo que o Godot alocou entre as atualizações de física. Em um cenário ideal, o tempo de quadro é aquele que você escolheu: 16,66 milissegundos por padrão, o que corresponde a 60FPS. É um quadro de referência que você pode usar para todo o resto ao seu redor.

  • Idle time is the time Godot took to update logic other than physics, such as code that lives in _process() or timers and cameras set to update on Idle.

  • Physics time is the time Godot took to update physics tasks, like _physics_process() and built-in nodes set to update on Physics.

Nota

O Frame Time inclui o tempo de renderização. Suponha que você encontre um pico misterioso de lag no seu jogo, mas a sua física e os seus scripts estão todos rodando rápido. O atraso pode ser devido ao aparecimento de partículas ou efeitos visuais!

Por padrão, o Godot faz a contagem com base no Frame Time e no Physics Time. Isso lhe dá uma visão geral de quanto tempo cada quadro leva em relação ao FPS de física desejado e alocado. Você pode alternar as funções ativando e desativando as caixas de seleção à esquerda. Outros recursos aparecem conforme você desce na lista, como Physics 2D, Physics e Audio, antes de chegar às funções de Script, onde o seu código aparece.

Se você clicar no gráfico, você altera qual informação de quadro aparece à esquerda. No canto superior direito, há também um contador de quadros onde você pode ajustar manualmente o quadro que está visualizando de forma mais granular.

Escopo de medição e janelas de medição

Você pode alterar qual medição está visualizando usando o menu suspenso Measure. Por padrão, ele começa com o Frame Time e lista o tempo que leva para percorrer o quadro em milissegundos. O tempo médio (average time) é o tempo médio que uma determinada função levou quando chamada mais de uma vez. Por exemplo, uma função que levou 0,05 milissegundos para rodar cinco vezes deve fornecer uma média de 0,01 milissegundos.

Se a contagem precisa de milissegundos não for importante e você quiser ver as proporções de tempo em relação ao resto do quadro, use medições de porcentagem. O Frame % é relativo ao Frame Time, e o Physics % é relativo ao Physics Time.

A última opção é o escopo do tempo. Inclusive (Inclusivo) mede o tempo que uma função levou com quaisquer chamadas de função aninhadas (nested). Por exemplo:

../../../_images/split_curve.png

get_neighbors, find_nearest_neighbor, and move_subject all took a lot of time. You could be fooled into thinking that this is because all three of them are slow.

Mas quando alterado para Self (Próprio), o Godot mede o tempo gasto no corpo da função sem considerar as chamadas de função que ela mesma fez.

../../../_images/self_curve.png

You can see that get_neighbors and move_subject have lost a lot of their importance. In effect, that means that get_neighbors and move_subject have spent more time waiting for some other function call to finish than not, and find_nearest_neighbor is actually slow.

Depurando código lento com o profiler

Encontrar códigos lentos com o profiler resume-se em rodar o seu jogo e observar o gráfico de desempenho conforme ele desenha. Quando ocorre um pico inaceitável no tempo de quadro, você pode clicar no gráfico para pausar o seu jogo e estreitar o número do quadro (_Frame #_) até o início do pico. Pode ser necessário pular de um lado para o outro entre quadros e funções para encontrar a causa raiz.

Sob as funções de Script, ative as caixas de seleção de algumas funções para descobrir quais estão levando tempo. Estas são as funções que você precisa revisar e otimizar.

Medindo manualmente em microssegundos

If your function is complex, it could be challenging to figure out which part needs optimization. Is it your math or the way you access other pieces of data to do the math with? Is it the for loop? The if statements?

You can narrow down the measurement by manually counting ticks as the code runs with some temporary functions. The two functions are part of the Time class object. They are get_ticks_msec() and get_ticks_usec(). The first measures in milliseconds (1,000 per second), and the second measures in microseconds (1,000,000 per second).

Qualquer uma delas retorna a quantidade de tempo desde que a engine do jogo iniciou em seu respectivo intervalo de tempo.

Se você envolver um pedaço de código com uma contagem inicial e final de microssegundos, a diferença entre as duas é a quantidade de tempo que levou para rodar esse pedaço de código.

# Measuring the time it takes for worker_function() to run
var start = Time.get_ticks_usec()
worker_function()
var end = Time.get_ticks_usec()
var worker_time = (end-start)/1000000.0

# Measuring the time spent running a calculation over each element of an array
start = Time.get_ticks_usec()
for calc in calculations:
    result = pow(2, calc.power) * calc.product
end = Time.get_ticks_usec()
var loop_time = (end-start)/1000000.0

print("Worker time: %s\nLoop time: %s" % [worker_time, loop_time])

Conforme você se torna um programador mais experiente, essa técnica se torna menos necessária. Você começa a aprender quais partes de um programa em execução são lentas. Saber que laços (loops) e ramificações (branches) podem ser lentos vem da experiência, e você ganha experiência medindo e pesquisando.

Mas entre o profiler e as funções de ticks, você deve ter o suficiente para começar a encontrar quais partes do seu código precisam de otimização.