Engenharia de Desempenho .NET
Use este skill ao investigar, explicar, corrigir, fazer benchmark ou validar o desempenho de uma aplicação .NET, incluindo ASP.NET Core, serviços, aplicações de console, Avalonia, WPF, WinUI, MAUI, Skia, WebGPU, motores de jogo/gráficos, NativeAOT e cargas de trabalho de interoperabilidade nativa.
Este repositório define um skill. SKILL.md é o ponto de entrada de política e roteamento; procedimentos operacionais detalhados residem em uma árvore de referência hierárquica. Carregue apenas os índices e capítulos necessários para a investigação atual e expanda quando as evidências cruzarem um limite de propriedade.
Regras não negociáveis
- Perfile e faça benchmark de uma build otimizada, normalmente
Release, na forma de implantação real. - Registre o commit e estado sujo, SDK/runtime, SO, arquitetura, hardware, modo de energia, carga de trabalho, versões das ferramentas, substituições de ambiente e comandos exatos.
- Estabeleça uma reprodução determinística antes de alterar código.
- Separe inicialização a frio, primeiro uso, estado estável aquecido, sobrecarga, drenagem e desligamento.
- Aqueça compilação em camadas, shaders, pipelines, caches e pools, a menos que o comportamento a frio seja o assunto.
- Colete evidências em todos os limites de propriedade relevantes: runtime gerenciado, biblioteca nativa, kernel, escalonador, sistema de arquivos/rede, dependência, driver, GPU, compositor e display.
- Não infira retenção gerenciada apenas pelo RSS.
- Não infira saturação de GPU apenas por alto tempo de quadro, uso da API GPU ou utilização.
- Não afirme uma correção com base em uma média, um trace, uma captura de quadro, um microbenchmark ou a execução de benchmark mais rápida.
- Preserve artefatos brutos e relate símbolos ausentes, eventos descartados, overhead do profiler, variação ambiental e incerteza.
- Proteja segredos e dados pessoais em dumps, traces, logs, spans SQL, capturas de pacotes e corpora de entrada de benchmark.
- Trate exemplos de comandos como sensíveis à versão. Consulte a ajuda da ferramenta instalada primeiro; ela substitui exemplos quando a sintaxe difere. Use
references/command-reference.mdpara regras de seleção verificadas e formulários canônicos.1
Saída de investigação necessária
Relate:
- Sintoma — impacto observável e alvo violado.
- Reprodução — carga de trabalho e ambiente determinísticos.
- Coleta — ferramentas, comandos, duração e caminhos de artefatos exatos.
- Evidência — contadores, traces, capturas, dumps, distribuições de benchmark e medições.
- Propriedade — CPU gerenciada, runtime, CPU nativa, kernel, escalonador, I/O, dependência, memória, driver, GPU, compositor ou display.
- Causa dominante — maior custo suportado, espera ou recurso de crescimento mais rápido.
- Correção — menor alteração de código ou configuração de alto impacto.
- Validação — execuções equivalentes antes/depois com métricas de propagação e cauda.
- Riscos residuais — gargalos não resolvidos e limites de medição.
Nunca afirme uma melhoria sem evidências antes/depois de uma carga de trabalho equivalente.
Roteador de referência
Sempre comece com references/index.md, references/core/index.md e o verificado references/command-reference.md.
Carregue índices de domínio adicionais por pergunta:
- CPU gerenciada, alocação, GC, JIT, exceções, ThreadPool, locks, pilhas assíncronas, dumps:
references/runtime/index.md - Propriedade de memória gerenciada/nativa/VM/mapeada/GPU e análise de vazamento:
references/memory/index.md - Contenção, latência assíncrona, filas, contrapressão, I/O de arquivo/rede/banco de dados, latência do dispatcher de UI:
references/latency/index.md - Inicialização a frio, primeiro quadro/requisição, loader, JIT, ReadyToRun, trimming, arquivo único, NativeAOT:
references/startup/index.md - BenchmarkDotNet, benchmarks de micro/componente/macro/carga/soak, benchmarks assíncronos/de concorrência, comparações JIT/AOT, desmontagem, contadores de hardware, estatísticas, portões de CI:
references/benchmarking/index.md - Produção, containers, portas de diagnóstico,
dotnet-monitor, coleta disparada, Kubernetes, segurança de artefatos:references/production/index.md - UI/renderização/GPU/WebGPU/Metal/D3D/Vulkan/OpenGL/shader/sincronização/apresentação:
references/gpu/index.md
Carregue toda referência de plataforma relevante através de references/platforms/index.md. Uma investigação em único host geralmente precisa de um documento de plataforma; comparações multiplataforma e cenários remotos/cliente-servidor podem exigir vários.
Não carregue todos os documentos por padrão. Selecione o conjunto mínimo que responde à hipótese atual, mas não pare em um limite de propriedade meramente porque outro guia é necessário.
Sequência de triagem rápida
- Compile e execute a configuração equivalente à de produção.
- Defina fases de carga de trabalho, métricas de sucesso e uma regra de parada.
- Registre contadores
System.Runtimemais CPU do processo e memória total. - Capture evidência de CPU/runtime gerenciado com
dotnet-tracequando a propriedade gerenciada for plausível. - Capture pilhas repetidas quando progresso, starvation ou bloqueio for suspeito.
- Se o custo total não for explicado, colete o trace nativo de CPU/escalonador/I/O/memória da plataforma.
- Para memória, compare bytes vivos gerenciados, comprometimento do GC, privado/RSS/PSS, alocações nativas, mapeamentos, alocações gráficas e residência na GPU.
- Para renderização, correlacione marcadores de aplicação, submissão de CPU, timestamps de GPU, captura nativa de GPU, apresentação, compositor e temporização de display.
- Para solicitações de benchmark, escolha a metodologia de micro, componente, macro, carga ou soak antes de selecionar BenchmarkDotNet ou outro harness.
- Para incidentes apenas de produção, use coleta limitada ou disparada e registre restrições cgroup/host.
- Implemente apenas após as evidências suportarem a causa dominante.
- Repita a carga de trabalho idêntica e publique mediana, propagação, valores de cauda e artefatos brutos.
Testes de propriedade
- CPU alta do processo com pilhas gerenciadas quentes: trabalho da aplicação/JIT/runtime.
- CPU alta do processo abaixo de P/Invoke: biblioteca nativa, alocador, API gráfica ou CPU do driver.
- CPU baixa com pilhas bloqueadas repetidas: sincronização, I/O, escalonador, enfileiramento ou dependência externa.
- Fila do ThreadPool crescente com CPU baixa e pilhas bloqueadas: starvation ou sync-over-async.
- Bytes vivos gerenciados estáveis com privado/RSS crescente: heap nativo, mapeamentos, heaps de código, fragmentação, recursos gráficos ou caches do SO.
- Grafo gerenciado vivo crescente após pontos equivalentes de coleta completa: retenção gerenciada ou cache intencionalmente ilimitado.
- Quadro longo de CPU com timestamps curtos de GPU: aplicação/thread de renderização/CPU do driver é o gargalo.
- Submissão curta de CPU com timestamps longos de GPU: execução de GPU é o gargalo.
- CPU e GPU terminam cedo, mas a apresentação está atrasada: swapchain, compositor, vsync, starvation de drawable ou pacing de display.
- Lacunas ociosas de GPU entre submissões dependentes: starvation de CPU, sincronização excessiva, serialização ou buffer insuficiente.
- Latência alta com tempo baixo em CPU: espera fora da CPU, enfileiramento, dependência, limitação de taxa ou atraso do escalonador.
- A inicialização melhora, mas a primeira ação piora: o trabalho foi adiado em vez de removido.
- O benchmark melhora, mas a métrica do produto não: o experimento omitiu o caminho crítico, usou a distribuição de entrada errada ou otimizou uma operação não dominante.
Procedimento operacional do agente
- Inspecione compilação, implantação, diagnósticos, projetos de benchmark, corpora de entrada, CI e convenções de artefatos do repositório.
- Crie
artifacts/performance/<issue-ou-timestamp>/ou o equivalente do repositório. - Adicione um driver de carga de trabalho determinístico e marcadores estáveis quando ausentes.
- Armazene comandos, metadados de ambiente, versões de analisadores/ferramentas e links oficiais de referência ao lado dos artefatos.
- Analise custos inclusivos primeiro, depois custos exclusivos, chamados, esperas, enfileiramento, sincronização e propriedade.
- Modifique código apenas após a causa dominante ser suportada.
- Adicione um benchmark, orçamento de regressão, marcador de telemetria, receita de trace ou invariante de tempo de vida que previna recorrência.
- Mantenha grandes artefatos de trace, captura, dump e benchmark fora do Git, a menos que a política do repositório os armazene explicitamente.
- Valide caminhos de falha, cancelamento, sobrecarga, limpeza, perda de dispositivo e desligamento — não apenas o caminho feliz.
Conclusões inválidas a rejeitar
- “A CPU está alta, portanto o método X é lento” sem pilhas.
- “O RSS cresceu, portanto o heap gerenciado vaza.”
- “O heap do GC está estável, portanto não há vazamento.”
- “A latência/tempo de quadro médio está dentro do orçamento, portanto as caudas estão saudáveis.”
- “A utilização da GPU está alta, portanto o shader X é o gargalo.”
- “A thread de renderização está ocupada, portanto a GPU está ocupada.”
- “Uma captura de quadro representa o comportamento de estado estacionário.”
- “Menos chamadas de draw sempre significa renderização mais rápida.”
- “Mais threads do ThreadPool corrigem starvation.”
- “Código assíncrono não pode bloquear.”
- “NativeAOT é automaticamente mais rápido.”
- “Uma melhoria de microbenchmark prova melhoria da aplicação.”
- “Um delta estatisticamente detectável é automaticamente significativo para o produto.”
- “Uma execução de benchmark prova o resultado.”
Notas de rodapé da documentação
Footnotes
-
references/command-reference.md, que vincula à documentação oficial atual para as ferramentas de diagnóstico .NET, BenchmarkDotNet, Xcode Instruments, Windows Performance Toolkit, Linuxperf/BCC, PresentMon, RenderDoc e profilers de GPU de fornecedores. ↩