Este é um script Python para converter a saída de muitos criadores de perfil em um gráfico de pontos.
Pode:
Se você deseja um visualizador interativo para os gráficos gerados por gprof2dot , verifique xdot.py.
Atualmente, o gprof2dot atende às minhas necessidades e tenho pouco ou nenhum tempo para sua manutenção. Portanto, temo que seja improvável que quaisquer recursos solicitados sejam implementados e que eu possa estar processando lentamente relatórios de problemas ou solicitações pull.
Este é o resultado dos dados de exemplo no artigo Linux Gazette com as configurações padrão:
Na execução do Debian/Ubuntu:
apt-get install python3 graphviz
Execute no RedHat/Fedora
yum install python3 graphviz
PyPI
pip install gprof2dot
Script independente
Repositório Git
Usage:
gprof2dot.py [options] [file] ...
Options:
-h, --help show this help message and exit
-o FILE, --output=FILE
output filename [stdout]
-n PERCENTAGE, --node-thres=PERCENTAGE
eliminate nodes below this threshold [default: 0.5]
-e PERCENTAGE, --edge-thres=PERCENTAGE
eliminate edges below this threshold [default: 0.1]
-f FORMAT, --format=FORMAT
profile format: axe, callgrind, collapse, dtrace,
hprof, json, oprofile, perf, prof, pstats, sleepy,
sysprof or xperf [default: prof]
--total=TOTALMETHOD preferred method of calculating total time: callratios
or callstacks (currently affects only perf format)
[default: callratios]
-c THEME, --colormap=THEME
color map: bw, color, gray, pink or print [default:
color]
-s, --strip strip function parameters, template parameters, and
const modifiers from demangled C++ function names
--color-nodes-by-selftime
color nodes by self time, rather than by total time
(sum of self and descendants)
-w, --wrap wrap function names
--show-samples show function samples
--node-label=MEASURE measurements to on show the node (can be specified
multiple times): self-time, self-time-percentage,
total-time or total-time-percentage [default: total-
time-percentage, self-time-percentage]
--list-functions=LIST_FUNCTIONS
list functions available for selection in -z or -l,
requires selector argument ( use '+' to select all).
Recall that the selector argument is used with
Unix/Bash globbing/pattern matching, and that entries
are formatted '::'. When
argument starts with '%', a dump of all available
information is performed for selected entries, after
removal of leading '%'.
-z ROOT, --root=ROOT prune call graph to show only descendants of specified
root function
-l LEAF, --leaf=LEAF prune call graph to show only ancestors of specified
leaf function
--depth=DEPTH prune call graph to show only descendants or ancestors
until specified depth
--skew=THEME_SKEW skew the colorization curve. Values < 1.0 give more
variety to lower percentages. Values > 1.0 give less
variety to lower percentages
-p FILTER_PATHS, --path=FILTER_PATHS
Filter all modules not in a specified path
--compare Compare two graphs with almost identical structure. With this
option two files should be provided.gprof2dot.py
[options] --compare [file1] [file2] ...
--compare-tolerance=TOLERANCE
Tolerance threshold for node difference
(default=0.001%).If the difference is below this value
the nodes are considered identical.
--compare-only-slower
Display comparison only for function which are slower
in second graph.
--compare-only-faster
Display comparison only for function which are faster
in second graph.
--compare-color-by-difference
Color nodes based on the value of the difference.
Nodes with the largest differences represent the hot
spots.
perf record -g -- /path/to/your/executable
perf script | c++filt | gprof2dot.py -f perf | dot -Tpng -o output.png
opcontrol --callgraph=16
opcontrol --start
/path/to/your/executable arg1 arg2
opcontrol --stop
opcontrol --dump
opreport -cgf | gprof2dot.py -f oprofile | dot -Tpng -o output.png
Se você não está familiarizado com o xperf, leia primeiro este excelente artigo. Então faça:
Inicie o xperf como
xperf -on Latency -stackwalk profile
Execute seu aplicativo.
Salve os dados. ` xperf -d saída.etl
Inicie o visualizador:
xperf output.etl
No menu Trace , selecione Carregar símbolos . Configure caminhos de símbolos, se necessário.
Selecione uma área de interesse no gráfico de amostragem de CPU , clique com o botão direito e selecione Tabela de resumo .
No menu Colunas , certifique-se de que a coluna Pilha esteja habilitada e visível.
Clique com o botão direito em uma linha, escolha Export Full Table e salve em output.csv .
Em seguida, invoque gprof2dot como
gprof2dot.py -f xperf output.csv | dot -Tpng -o output.png
Colete dados de perfil como (também pode ser feito na GUI):
amplxe-cl -collect hotspots -result-dir output -- your-app
Visualize os dados do perfil como:
amplxe-cl -report gprof-cc -result-dir output -format text -report-output output.txt
gprof2dot.py -f axe output.txt | dot -Tpng -o output.png
Veja também a postagem do blog de Kirill Rogozhin.
/path/to/your/executable arg1 arg2
gprof path/to/your/executable | gprof2dot.py | dot -Tpng -o output.png
python -m profile -o output.pstats path/to/your/script arg1 arg2
gprof2dot.py -f pstats output.pstats | dot -Tpng -o output.png
python -m cProfile -o output.pstats path/to/your/script arg1 arg2
gprof2dot.py -f pstats output.pstats | dot -Tpng -o output.png
java -agentlib:hprof=cpu=samples ...
gprof2dot.py -f hprof java.hprof.txt | dot -Tpng -o output.png
Veja a postagem do blog de Russell Power para obter detalhes.
dtrace -x ustackframes=100 -n 'profile-97 /pid == 12345/ { @[ustack()] = count(); } tick-60s { exit(0); }' -o out.user_stacks
gprof2dot.py -f dtrace out.user_stacks | dot -Tpng -o output.png
# Notice: sometimes, the dtrace outputs format may be latin-1, and gprof2dot will fail to parse it.
# To solve this problem, you should use iconv to convert to UTF-8 explicitly.
# TODO: add an encoding flag to tell gprof2dot how to decode the profile file.
iconv -f ISO-8859-1 -t UTF-8 out.user_stacks | gprof2dot.py -f dtrace
A ferramenta FlameGraph de Brendan Gregg toma como entrada um arquivo de texto contendo uma linha por amostra. Este formato pode ser gerado a partir de várias outras entradas usando os scripts stackcollapse
no repositório FlameGraph. Também pode ser gerado por ferramentas como py-spy.
Exemplo de uso:
Desempenho
perf record -g -- /path/to/your/executable
perf script | FlameGraph/stackcollapse-perf.pl > out.collapse
gprof2dot.py -f collapse out.collapse | dot -Tpng -o output.png
Pi-espião
py-spy record -p -f raw -o out.collapse
gprof2dot.py -f collapse out.collapse | dot -Tpng -o output.png
Esta imagem ilustra um exemplo de uso das opções --compare
e --compare-color-by-difference
.
A seta apontando para a direita indica o nó onde a função foi executada mais rapidamente no perfil fornecido como o segundo (segundo perfil), enquanto a seta apontando para a esquerda indica o nó onde a função foi mais rápida no perfil fornecido como o primeiro (primeiro perfil) .
+-----------------------------+
| function name
| total time % -/+ total_diff
| ( self time % ) -/+ self_diff /
| total calls1 / total calls2 /
+-----------------------------+
Onde
total time %
e self time %
vêm do primeiro perfildiff
é calculado como o valor absoluto do time in the first profile - time in the second profile
.Nota A opção de comparação foi testada para perfis pstats, ax e callgrind.
Um nó no gráfico de saída representa uma função e possui o seguinte layout:
+------------------------------+
| function name |
| total time % ( self time % ) |
| total calls |
+------------------------------+
onde:
Uma aresta representa as chamadas entre duas funções e possui o seguinte layout:
total time %
calls
parent --------------------> children
Onde:
Observe que em ciclos recursivos, o % de tempo total no nó é o mesmo para todas as funções do ciclo, e não há % de tempo total nas arestas dentro do ciclo, pois tal valor não faria sentido.
A cor dos nós e arestas varia de acordo com o valor % do tempo total . No mapa de cores padrão semelhante à temperatura , as funções onde é gasto a maior parte do tempo (pontos quentes) são marcadas como vermelho saturado e as funções onde é gasto pouco tempo são marcadas como azul escuro. Observe que as funções onde o tempo é insignificante ou nenhum tempo gasto não aparecem no gráfico por padrão.
A flag --list-functions
permite listar as entradas de função encontradas na entrada gprof
. O objetivo é ser uma ferramenta de preparação para utilizações com os sinalizadores --leaf
( -l
) ou --root
( -z
).
prof2dot.py -f pstats /tmp/myLog.profile --list-functions "test_segments:*:*"
test_segments:5:,
test_segments:206:TestSegments,
test_segments:46:
O argumento do seletor é usado com correspondência de globbing/padrão Unix/Bash, da mesma maneira que executado pelos sinalizadores -l
e -z
.
As entradas são formatadas como '
Quando o argumento do seletor começa com '%', um dump de todas as informações disponíveis é executado para as entradas selecionadas, após a remoção do '%' inicial do seletor. Se o seletor for "+" ou "*", a lista completa de funções será impressa.
Por padrão, gprof2dot.py
gera um gráfico de chamada parcial , excluindo nós e arestas com pouco ou nenhum impacto no tempo total de computação. Se você deseja o gráfico de chamadas completo, defina um limite zero para nós e arestas por meio das opções -n
/ --node-thres
e -e
/ --edge-thres
, como:
gprof2dot.py -n0 -e0
Os rótulos dos nós podem ficar muito amplos ao criar o perfil do código C++, devido à inclusão de escopo, argumentos de função e argumentos de modelo em nomes de funções C++ desmantelados.
Se você não precisar de informações de argumentos de função e modelo, passe a opção -s
/ --strip
para retirá-los.
Se quiser manter todas essas informações, ou se os rótulos ainda estiverem muito largos, então você pode passar o -w
/ --wrap
, para embrulhar os rótulos. Observe que, como dot
não envolve as etiquetas automaticamente, as margens da etiqueta não ficarão perfeitamente alinhadas.
Provavelmente, o tempo total de execução é muito curto e, portanto, não há precisão suficiente no perfil para determinar onde o tempo está sendo gasto.
Você ainda pode forçar a exibição de todo o gráfico definindo um limite zero para nós e arestas por meio das opções -n
/ --node-thres
e -e
/ --edge-thres
, como:
gprof2dot.py -n0 -e0
Mas para obter resultados significativos, você precisará encontrar uma maneira de executar o programa por um período de tempo mais longo (resultados agregados de múltiplas execuções).
Provavelmente você tem um tempo de execução muito curto, fazendo com que os erros de arredondamento sejam grandes.
Veja a pergunta acima para saber como aumentar o tempo de execução.
As opções essenciais para produzir resultados adequados são:
-g
: produz informações de depuração-fno-omit-frame-pointer
: use o ponteiro de quadro (o uso do ponteiro de quadro está desabilitado por padrão em algumas arquiteturas como x86_64 e para alguns níveis de otimização; é impossível percorrer a pilha de chamadas sem ele) Se estiver usando o gprof, você também precisará da opção -pg
, mas hoje em dia você pode obter resultados muito melhores com outras ferramentas de criação de perfil, a maioria das quais não requer instrumentação de código especial durante a compilação.
Você deseja que o código cujo perfil está sendo criado seja o mais próximo possível do código que você irá liberar. Portanto, você deve incluir todas as opções usadas em seu código de lançamento, normalmente:
-O2
: otimizações que não envolvem uma compensação entre velocidade espacial-DNDEBUG
: desativa o código de depuração na biblioteca padrão (como a macro assert)No entanto, muitas das otimizações realizadas pelo gcc interferem na precisão/granularidade dos resultados do perfil. Você deve passar estas opções para desabilitar essas otimizações específicas:
-fno-inline-functions
: não incorpore funções em seus pais (caso contrário, o tempo gasto nessas funções será atribuído ao chamador)-fno-inline-functions-called-once
: semelhante ao acima-fno-optimize-sibling-calls
: não otimiza chamadas recursivas de irmãos e finais (caso contrário, as chamadas finais podem ser atribuídas à função pai)Se a granularidade ainda for muito baixa, você poderá passar estas opções para obter uma granularidade mais fina:
-fno-default-inline
: não torne as funções de membro inline por padrão apenas porque elas são definidas dentro do escopo da classe-fno-inline
: não preste atenção à palavra-chave inline. Observe, entretanto, que com essas últimas opções os tempos das funções chamadas muitas vezes serão distorcidos devido à sobrecarga da chamada de função. Isso é particularmente verdadeiro para código C++ típico, que espera que essas otimizações sejam feitas para um desempenho decente.Veja a lista completa de opções de otimização do gcc para obter mais informações.
Consulte o wiki para recursos externos, incluindo ferramentas complementares/alternativas.