Flame graph, pausas e contenção
Onde o tempo foi — por ação da linguagem, não por quadro do Python. Mais as pausas do coletor e a contenção que nenhum perfil de CPU mostra.
Um benchmark diz que está lento; um perfil diz onde. P.comecar_perfil sombreia o mesmo gancho que o `dataforge profile` usa, e conta o tempo próprio de cada ação — o total menos o que as chamadas internas gastaram.
dataforge profile src/main.df # o resumo, por acaoE de dentro da linguagem, com o gráfico:
// perfil := P.perfilar(minha_acao)
// IO.write("perfil.svg", P.chama_svg(perfil["perfil"]))
// IO.write("perfil.folded", P.chama_texto(perfil["perfil"]))| Saída | Para que serve |
|---|---|
P.chama_svg(perfil) | o gráfico, sem nada de fora: sem CDN, sem script e sem fonte remota — a mesma regra da Vitrine, porque perfil costuma ser aberto em rede fechada |
P.chama_texto(perfil) | o formato dobrado (a;b;c 1234), que o flamegraph.pl e os visualizadores de navegador consomem |
O formato dobrado foi escolhido por isso: um formato próprio obrigaria a escrever o visualizador junto.
Pausas do coletor#
A pausa do coletor é o que transforma um P50 bom num P99 ruim, e ela não aparece em medida nenhuma que olhe só o tempo total. gc.callbacks entrega o começo e o fim de cada coleta — é a medida na fonte.
adopt Arcane.Perfil as P
action trabalho():
total := 0
cycle i from 1 to 50:
total += i
yield total
r := P.gc_pausas(trabalho)
assert r["resultado"] is 1275
assert "p95" in r and "por_geracao" in r
assert r["total_ms"] smaller 50Contenção de trava#
Contenção não aparece num perfil de CPU: a thread bloqueada não gasta CPU nenhuma. Ela aparece como latência que ninguém explica — e a única forma de vê-la é medir na própria trava.
adopt Arcane.Perfil as P
trava := P.trava()
P.com_trava(trava, lambda => 1 + 1)
P.com_trava(trava, lambda => 2 + 2)
e := P.estatisticas_da_trava(trava)
assert e["aquisicoes"] is 2
assert e["esperas"] is 0 // sem disputa, ninguem esperouA distinção é feita por uma tentativa sem bloqueio antes da aquisição real: sem ela, toda aquisição contaria como espera, e a métrica diria que há contenção em programa de uma thread só.