Otimização de Código
Melhore o desempenho e a confiabilidade visíveis ao usuário, mantendo o código compreensível e o custo operacional proporcional. Otimize a carga de trabalho que existe; não adicione complexidade para uma escala futura hipotética.
Fluxo de Trabalho
- Defina o objetivo e as salvaguardas. Identifique o endpoint, job, consulta, carga de trabalho e resultado desejado relevantes. Escolha apenas as métricas que importam: por exemplo, latência p95/p99, throughput, CPU, memória, taxa de alocação, contagem de consultas ao banco de dados, viagens de ida e volta de dependências, taxa de erro ou saturação. Preserve comportamento, consistência, segurança e contratos de erro existentes. Faça apenas uma pergunta focada quando um alvo ou carga de trabalho ausente impedir uma escolha sólida; caso contrário, infira o que puder a partir da solicitação e do código.
- Estabeleça uma linha de base. Use traces, perfis, planos de consulta, métricas, testes ou um benchmark representativo existentes. Mantenha entrada, ambiente e concorrência comparáveis antes e depois. Não reivindique aceleração por intuição ou um único timing ruidoso. Evite executar testes de carga ou análises de consulta caras contra produção sem autorização.
- Encontre o gargalo. Trace o caminho crítico de ponta a ponta e use perfilamento ou instrumentação para distinguir trabalho de CPU, bloqueio, tempo de banco de dados, esperas de rede, serialização, contenção de bloqueio e enfileiramento. Inspecione o padrão real de consulta/chamada e os dados representativos. Prefira evidências a limpeza ampla ou micro-otimização. Se o gargalo não for estabelecido, relate a incerteza e proponha a menor medição útil antes de fazer alterações invasivas.
- Escolha a menor alteração efetiva. Otimize um gargalo material de cada vez quando prático. Preserve saída, ordenação, comportamento de falha, semântica de transação e verificações de segurança. Não troque correção ou confiabilidade por um ganho de benchmark. Siga as convenções do repositório e evite refatorações não relacionadas.
- Verifique ambos os resultados. Execute testes de correção relevantes e compare a mesma carga de trabalho representativa antes e depois. Verifique se a métrica alvo melhorou e se as salvaguardas — especialmente latência final, erros, memória e saturação de dependências — não regrediram. Se uma comparação significativa não estiver disponível, diga e evite apresentar uma alteração não medida como uma otimização comprovada.
- Relate o resultado. Declare brevemente o gargalo e a evidência, a alteração feita ou recomendada, a validação e o impacto medido (ou por que não pôde ser medido), e qualquer compensação material. Para uma auditoria ou solicitação de plano, priorize os achados por evidência, impacto provável, esforço e risco, em vez de alterar código.
Otimização de banco de dados e acesso a dados
- Conte consultas e inspecione padrões de acesso ORM/banco de dados. Remova leituras ou gravações N+1 com um join, lote ou operação baseada em conjunto apropriado; verifique a contagem de consultas e preserve a ordenação dos resultados e o comportamento de registros ausentes.
- Busque apenas as colunas e linhas necessárias. Use paginação ou streaming para grandes conjuntos de resultados; empurre filtragem e agregação adequadas para o banco de dados em vez de carregar grandes conjuntos de dados na memória da aplicação.
- Use o plano de consulta e predicados reais para justificar índices. Verifique seletividade, necessidades de classificação/join, índices existentes e sobrecarga de gravação/armazenamento. Não adicione índices especulativos ou duplicados. Valide o plano e a latência em dados representativos; use análise de plano baseada em execução apenas em um ambiente seguro.
- Reduza viagens de ida e volta desnecessárias e mantenha transações e escopos de bloqueio não maiores do que o necessário. Não enfraqueça restrições, isolamento, validação ou consistência como atalho.
- Adicione cache apenas quando o reuso medido o justificar. Defina frescor, invalidação, escopo da chave e comportamento de falha; não introduza um cache como resposta padrão para uma consulta lenta.
Otimização de backend e chamadas de serviço
- Remova chamadas redundantes, agrupe solicitações compatíveis e paralelize apenas chamadas que são verdadeiramente independentes. Mantenha a concorrência limitada, preserve ordenação/dependências necessárias e considere a capacidade downstream.
- Reutilize clientes e pools de conexão. Defina prazos/timeouts que se encaixem no orçamento da requisição e propague cancelamento quando suportado.
- Repita apenas falhas transitórias quando a operação for segura para repetir. Limite as tentativas e o tempo total de repetição, use backoff com jitter e evite repetir em várias camadas de maneiras que amplifiquem a carga. Não adicione repetições, disjuntores ou filas sem um modo de falha demonstrado que eles abordem.
- Reduza payloads superdimensionados ou serialização repetida apenas quando forem materiais para o caminho medido. Mantenha a semântica de falha de serviço necessária intacta; torne a degradação gradual explícita para dependências opcionais.
Runtime, confiabilidade e manutenibilidade
- Prefira a correção de maior alavancagem apoiada por evidências: melhore a complexidade algorítmica, remova trabalho repetido, reduza alocação/cópia desnecessária ou aborde bloqueio e contenção antes de micro-otimizações de baixo nível.
- Mantenha o uso de recursos limitado sob concorrência: considere memória, filas, pools, fan-out, timeouts, cancelamento e backpressure. Garanta que falhas não criem tempestades de repetição, trabalho ilimitado ou vazamentos de recursos.
- Trate desempenho e confiabilidade como resultados sistêmicos. Um chamador mais rápido que sobrecarrega um banco de dados ou aumenta as taxas de erro não é uma otimização.
- Aplique YAGNI: não adicione uma dependência, abstração, cache, índice, camada assíncrona, opção de configuração ou mudança de arquitetura para um gargalo hipotético. Prefira uma alteração local clara; se a complexidade for necessária, explique o benefício medido e seu custo de manutenção.
- Não remova validação de entrada, autorização, observabilidade ou verificações de segurança para economizar tempo insignificante. Não substitua código legível por uma micro-otimização mais difícil de manter, a menos que o ganho medido seja material.
Notas de verificação
- Compare cargas de trabalho equivalentes com execuções repetíveis e amostras suficientes para distinguir sinal de ruído. Use distribuições (especialmente latência final) quando relevante, não apenas médias.
- Verifique o comportamento funcional e casos extremos afetados por lotes, cache, paralelismo, paginação, repetições ou concorrência. Adicione testes focados onde eles protegem um invariante significativo, como contagem de consultas, ordenação, comportamento de timeout ou fallback de serviço opcional.
- Re-perfile após a alteração: os gargalos se movem, e uma melhoria local pode deslocar o custo para outro serviço ou recurso.
- Se a otimização não produzir uma melhoria material ou sua complexidade superar o benefício, reverta-a ou recomende contra ela.