Pular para o conteúdo principal

Budgets de Performance

O AppCore mantém um benchmark reproduzível entre subsistemas para que correções de concorrência e persistência sejam medidas com as mesmas cargas V1.

appcore-dev cert bottlenecks

O comando em perfil release grava builds/certification/bottlenecks.json. O relatório registra commit exato, estado dirty, toolchain, sistema, arquitetura, p50/p95/p99, throughput, tempo total e pico de memória residente. Ele também conta bytes solicitados ao heap Rust, operações de alocação/desalocação, pico vivo e retenção por subsistema. O CI Linux e Windows executa o mesmo gate e publica o artefato JSON.

RSS continua obrigatório porque os contadores Rust excluem metadata do allocator, bibliotecas nativas, memory mappings, buffers do kernel e memória de devices. Saturação dos contadores falha fechada. Cada workload fixo é limitado a 64 MiB de delta de heap vivo e 4 MiB de crescimento retido; o processo completo mantém os tetos maiores de catástrofe de RSS e heap. A primeira calibração release no Apple M1 observou pico vivo de 29.476.637 bytes e 139.611 bytes de crescimento retido no heap Rust.

Peer RPC relata intervalos de alocação separados para V1, stream V2, codecs V2 e erros tipados. Base64 JSON com scratch fixo e decode emprestado reduziram os bytes solicitados em 8,75% no workload completo, 7,20% no stream V2 e 21,36% nos codecs em runs pareados no Apple M1. Pico e heap retido não mudaram; operações de alocação subiram 5,44% e o p99 do stream 1,69%, portanto o relatório preserva esse tradeoff em vez de confundir churn com memória residente. Mover ownership dos chunks identity pelo encoder, frame e assembler reduziu os bytes solicitados no stream de 64 MiB de 1.072.617.252 para 938.399.524 (-12,51%) e as alocações em 7,39%, com +0,22% no p99 e -0,21% no RSS pico do processo. Esse checkpoint de ownership falhava acima de 960 MiB cumulativos. A atribuição por fase mostrou então 662.732.479 bytes solicitados no encode. Uma sonda de incompressibilidade fixa em stack reduziu o total do stream de 938.404.175 para 342.886.735 (-63,57%) e as alocações em 47,83%. Dois runs da sonda completa melhoraram o p99 entre 15,38% e 16,14%, mantendo gzip nas fixtures compressíveis. O gate agora é 384 MiB.

SQLite relata intervalos separados de alocação para startup, append, leitura pontual, construção das fixtures, enqueue da outbox, backup e integrity check. O enqueue de 512 records pequenos tem gates de 2 MiB solicitados no heap Rust e 250 ms p99. O scratch proporcional do BLOB incremental reduziu bytes solicitados no workload completo de 578.081.344 para 8.251.670 (-98,57%) e o delta de heap vivo de 1.083.528 para 233.600 bytes (-78,44%); o enqueue solicitou 255.676 bytes, não reteve crescimento e mediu 141.791 ns p99.

Cargas fixas​

  • startup manifest-first e dispatch concorrente de commands e queries;
  • enqueue, leitura e ACK da outbox perto de 1, 10 e 64 MiB, mais comparação de materialização entre snapshot completo e página limitada sobre 256 mensagens;
  • contenção do routing state do Gateway com 1, 100 e 1.000 tenants, mais uma prova de independência de lock entre tenants;
  • 32 trocas HTTP/1.1 sequenciais por uma única conexão keep-alive aceita;
  • encode, decode, integridade e replay JSON/base64 e binário/nativo do Peer RPC entre 1 KiB e 4 MiB, mais 4.096 round trips de rejeição V2 tipada;
  • startup do scheduler e lotes limitados de 64 tasks vencidas.

As fixtures não contêm segredo estático. Cada execução obtém material secreto temporário da fonte aleatória do sistema operacional.

Uso dos budgets​

Os limites portáveis impedem regressões em runners CI compartilhados. Eles não são promessa de performance em produção. Cada correção deve preservar V1, mostrar antes/depois, adicionar uma invariante de comportamento e apertar o budget afetado quando o resultado estiver estável.

A baseline inicial registrou concorrência máxima 1 nos handlers de commands e queries. AC-001 remove a execução de command handler do mutex compartilhado do host. O gate agora exige sobreposição de pelo menos quatro entre oito workers; testes determinísticos exigem que os oito entrem juntos, preservam execução única para uma chave idempotente igual e verificam a drenagem no shutdown. AC-002 também remove a execução de query endpoint do mutex do host e aplica o mesmo gate de quatro entre oito. Seu teste determinístico congela o registro e exige sobreposição das oito chamadas de endpoint.

AC-003 substitui o mapa global público de tenants do Gateway por um diretório limitado com 32 shards e um lock por tenant. O gate mantém o write lock de um tenant enquanto exige que o lock de outro continue disponível. Como manter o mapa antigo restauraria a serialização ou duplicaria estado mutável, a correção continua bloqueada no RC até restaurar a compatibilidade 1.x e o campo antigo foi removido.

AC-004 remove o mutex global de metadata de requests pendentes. Um único mapa privado e limitado por tenant guarda channel de resposta, geração do worker, deadline e limite da resposta na mesma entrada. Testes determinísticos exigem cleanup após resposta, resposta inválida, timeout, cancelamento, shutdown, substituição e desconexão do worker; geração stale deve preservar a entrada atual.

AC-005 adiciona um cliente HTTP reutilizável com admissão por origem, conexões ociosas e retenção de origens limitadas. Os deadlines de conexão/admissão, leitura e escrita são independentes. Somente respostas totalmente delimitadas e interpretadas voltam ao pool; qualquer falha ou resposta não reutilizável descarta o socket. O gate exige as 32 trocas pela mesma conexão aceita. O adapter V1 livre send continua one-shot com Connection: close.

AC-007 substitui reload/rewrite integral da outbox pelo journal append-only V2 explícito no 1.0.2-rc. As cargas de 1/10/64 MiB agora incluem um pequeno enqueue incremental de tail limitado a 100 ms p99, enquanto ACK fica limitado a 500 ms p99. A compactação atômica muda a geração; testes exigem recovery do frame final incompleto e falha fechada para corrupção completa, frames duplicados/reordenados e versões incompatíveis.

AC-011 adiciona índices diretos por tenant, Core ID e (cluster_id, core_id). O gate executa 16.384 lookups entre o máximo de 1.024 workers registrados e exige no máximo 1 ms p99, pelo menos 10.000 lookups/s e zero inconsistências. Testes de reconnect, disconnect e prune de heartbeat exigem que geração stale nunca remova a entrada atual.

AC-018 substitui uma thread por execução do scheduler por pool fixo e fila limitada. O gate de 64 tasks exige que concorrência de callbacks e nomes distintos de threads worker permaneçam dentro de max_concurrent_tasks, além de observar ao menos um evento limitado de saturação da fila. Trabalho excedente é adiado sem consumir tentativas de retry.

AC-020 adiciona o contrato de telemetria Gateway do 1.0.2-rc. O gate mantém 128 séries de capability, agrega oito nomes adicionais em uma série fixa de overflow, executa 4.096 rotas instrumentadas sem worker disponível e constrói 256 snapshots. Ele exige zero rotas inflight residuais, cardinalidade e overflow exatos, rota p99 no máximo de 1 ms e snapshot p99 no máximo de 5 ms. A execução limpa macOS/aarch64 no commit de implementação 31c4fbe mediu 1.792 ns p99 para rota e 5.792 ns p99 para snapshot. A exportação é uma fronteira pull explícita do deployment e nunca é chamada pelo roteamento.

AC-021 valida a matriz completa de erros tipados, decode V1 exato e 4.096 round trips de encode/decode/validação de rejeição V2. O gate exige p99 de no máximo 1 ms e pelo menos 1.000 operações/s. A execução limpa macOS/aarch64 em d11befe mediu p99 de 750 ns e 1.405.708 operações/s, com pico RSS total de 298.672 KiB. Artefatos CI Linux e Windows continuam sendo a autoridade de plataforma.

AC-012 substitui a seleção aleatória por processo pelas policies estáveis FirstAvailable, RoundRobin, LeastInflight, HealthWeighted e Affinity stateless. O gate registra 64 workers, exige exatamente quatro seleções round-robin por worker, verifica invariantes de health, capacity e affinity, e executa 16.384 seleções por policy medida. Cada policy é limitada a 1 ms p99 e deve superar 10.000 seleções/s. A execução final limpa macOS/aarch64 em 7caddc1 mediu 17.125 ns p99 para round-robin, 18.542 ns para least-inflight e 38.083 ns para affinity.

AC-013 adiciona 4.096 lookups no registry compartilhado e três rounds completos de recovery com 1, 100 e 1.000 tenants, depois 64 requests com sucesso em cada rota fenced local real e rota federada V2 autenticada. Lookup é limitado a 5 ms p99 e deve superar 500/s; recovery é limitado a 5 s; rota local a 50 ms p99 e 100/s; federação a 250 ms p99 e 20/s. A execução limpa macOS/aarch64 em 7197416 mediu no máximo 667 ns p99 de lookup, 2,25 ms p99 de recovery, 0,35 ms p99 de rota local e 0,91 ms p99 de rota federada. Testes Redis, proxy externo e perda de owner continuam como evidências separadas; artefatos Linux e Windows ainda são necessários.

AC-014 adiciona uma representação binária opt-in explícita para os DTOs Peer RPC V2 existentes, preservando as fixtures JSON/base64 exatas e todas as rotas V1. O gate exige que bytes de body binário fiquem em até 80% do JSON, que o p99 do codec binário não ultrapasse o JSON e que o buffer limitado fique em até 90% do JSON. A execução limpa macOS/aarch64 em 6f3bc38 mediu 25% menos bytes de body, 93% menos p99 de codec e buffer 14% menor entre 64 KiB e 4 MiB; o pico RSS total foi 306.448 KiB. Suporte binário ausente falha sem retry JSON. Artefatos Linux e Windows ainda são necessários.

AC-015 adiciona páginas de outbox limitadas por quantidade/bytes, stats sem payload, readiness durável de retry e receipts parciais exatos. O follower e a CLI do Runtime não materializam mais a fila completa. A execução limpa macOS/aarch64 em c904e83 materializou 460.684 bytes para uma página de sete mensagens contra 30.021.820 bytes no snapshot completo de 256 mensagens, uma redução de 98,46%. O p99 da página foi 71.458 ns contra 1.404.417 ns; o p99 de stats foi 54.542 ns e o pico RSS total foi 244.752 KiB. O wire peer V1 permanece inalterado; artefatos Linux e Windows ainda são necessários.

Veja o benchmark em AC-022 pública e a correção de commands em AC-001 pública. A correção de queries está em AC-002 pública. A correção do Gateway está em AC-003 pública. O ownership de requests pendentes está em AC-004 pública. O reuso de conexões HTTP está em AC-005 pública. A correção do journal da outbox está em AC-007 pública. O índice direto de workers está em AC-011 pública. O pool fixo do scheduler está em AC-018 pública. A telemetria limitada do Gateway está em AC-020 pública. A seleção limitada de workers está em AC-012 pública. A HA do Gateway está na AC-013 pública. O framing binário do Peer RPC está na AC-014 pública. A paginação limitada da outbox está na AC-015 pública. Os artefatos de plataforma restantes do erro wire tipado estão na AC-021 pública.