OpenClaw Performance
Desperdício é o trabalho que uma requisição não precisa. Grandes ganhos de velocidade vêm de eliminar desperdício, não de fazer o mesmo trabalho mais rápido. Um cache é o último recurso: ele esconde o desperdício até que sua chave, invalidação ou taxa de acerto quebre, e o desperdício retorne.
1. Medir
Escreva a regra de aceitação no PR antes da primeira execução: fluxo, workload, métrica, frio ou quente, amostras, e a mudança que conta como vitória ou regressão.
| Fluxo | Workload comprometido |
|---|---|
| Inicialização do CLI | pnpm test:startup:bench (:check contém o orçamento) |
| Inicialização / reinicialização do Gateway | scripts/bench-gateway-startup.ts, scripts/bench-gateway-restart.ts, scripts/perf/post-restart-burst-measure.ts |
| Turno de chat, quadros por turno | scripts/bench-channel-turn.mts, scripts/perf/transcript-broadcast-measure.ts |
| Carga fria da UI de Controle | scripts/bench-control-ui-cold-load.ts, pnpm ui:check-performance (:base compara) |
| Lista de sessões, forma multi-agente | scripts/perf/team-shape-fixture.ts, src/gateway/session-list-viewers.perf.test.ts |
| Concorrência, estado SQLite | scripts/bench-gateway-concurrency.ts, pnpm test:sqlite:perf |
- Conte primeiro: operações por ação (consultas SQL, RPCs e quadros, leituras de arquivo, cargas de catálogo ou registro, spawns, renderizações) antes do tempo de parede. As contagens permanecem estáveis em um host carregado. Uma contagem que deveria ser zero é o bug.
- Fluxo real: um Gateway isolado no head sob teste, transporte real, o caminho lento incluído. Um Gateway mockado, um build desatualizado ou um servidor de desenvolvimento mede outra coisa.
- Amostras: linha de base e candidato intercalados (ABAB), pelo menos 5 cada, frio e quente separados; mediana e p95 com dispersão, executados serialmente, carga do host registrada.
- Repetível: apenas scripts comprometidos contam; estenda um existente quando nenhum se encaixa.
- Perfil:
node --cpu-profpor thread, ou um trace de performance do navegador, no caminho quente.
Concluído quando o fluxo tem um workload comprometido, uma tabela de linha de base e uma regra escrita.
2. Encontrar desperdício
Pergunte para cada operação contada: esta requisição precisa disso? Desperdícios recorrentes do OpenClaw:
- Trabalho prematuro no caminho crítico: uma busca de registro importou o carregador de plugins (#133518, 47,07 s → 10,36 s); runtimes opcionais carregados na inicialização (#119374).
- Recomputação por linha ou por chamada: uma leitura síncrona por linha arquivada (#156665, 56.700 leituras → 0); padrões de log resolvidos por quadro (#150042, 539 → 17 ms por 10.000 quadros).
- Re-verificação de estado já admitido: verificações de esquema, admissão ou frescor em handles quentes (#166102, #172676; 14 PRs na cadeia de admissão SQLite).
- Re-escaneamento completo por delta transmitido: cada token reprocessava a resposta inteira (#158526, 5.342 → 1 ms CPU em 256 KiB).
- Re-lendo sua própria escrita: dois backups de banco de dados por busca (#161551, 772,8 → 7,7 ms); Doctor re-escaneava e fazia backup do que acabava de verificar (#174665, ~26 → 3,0 s).
- Construções repetidas de catálogo ou registro: uma reconstrução de catálogo por agente na inicialização (#116261, 24,9 → 5,0 s); reconstruções por falta ou TTL (#127178, #167008).
- Esperando por dados opcionais: a página de Uso esperava por planos de provedor e re-tentava leituras não relacionadas (#176358).
- Cópias defensivas e encapsulamento:
structuredClonepor turno (#172940, 1,685 MiB → 0); encapsulamento de limite por valor (#163818, 11.571 → 500 ns/evento). - Spawn ou fan-out por chamada: um processo filho por resolução (#155779, 100 → 0).
- Cascatas de renderização e cargas completas: uma renderização por atualização (#159400, 250 → 79); linhas completas reenviadas para um delta (#165404, 21,75 → 0,95 MB).
Concluído quando cada contagem dominante traça para o código que a emite, com um sim ou não em "necessário".
3. Corrigir nesta ordem
- Delete o desperdício. Deleções raramente voltam; uma deleção falhou removeu uma guarda, então mantenha toda verificação que protege um contrato e prove que o contrato ainda se mantém.
- Uma vez no proprietário: chamadores consomem o fato registrado do proprietário.
- Carregue o fato preparado pelo caminho quente.
- Agrupe trabalho independente, e prove que o agrupamento mantém quadros, caudas de latência e inicialização a frio estáveis: coalescência foi revertida três vezes (#162560, #173901, #175092).
- Cache, com uma razão escrita do porquê as etapas 1–4 não se aplicam. Siga a "Identidade do cache" raiz, invalide a partir das escritas do proprietário, limite o tamanho, e adicione um teste de contagem de trabalho intercalado. Três de quatro re-correções de cache foram falhas silenciosas: leitores se removendo mutuamente (#115369 → #174741), um orçamento que triturou (#149773 → #149879).
Uma movimentação de worker ou um adiamento realoca custo; conte trabalho da thread principal e total ambos.
Concluído quando o desperdício desapareceu das contagens, ou o PR diz qual etapa parou e por quê.
4. Publicar
- Re-execute o workload da etapa 1 na linha de base e no candidato sob a mesma regra.
- Toda métrica voltada ao usuário melhora ou permanece estável: latência, p95/p99, quadros, inicialização a frio, CPU, memória, contagens. Uma métrica pior precisa da aceitação explícita do proprietário no PR. Uma mudança de 20% em uma célula é uma parada, nunca "dentro da dispersão": cinco de seis PRs de performance revertidos mostraram sua regressão em seu próprio corpo.
- Reverta mudanças sem um ganho mensurável.
- A evidência vive no PR, não em novos testes: as contagens antes/depois são a evidência. Estenda o teste de contagem de trabalho existente de um fluxo apenas quando este desperdício já voltou antes; test-audit é dono do valor do teste.
- Evidência do PR: comando do workload, regra de aceitação, tabela antes/depois (contagens e tempos, mediana e p95, amostras), desperdício removido, e qualquer métrica que se moveu na direção errada.
Concluído quando a tabela atende a regra escrita na etapa 1.
Relacionados
Velocidade do conjunto de testes: openclaw-test-performance. Crescimento do heap de teste: openclaw-test-heap-leaks. Capacidade do CI: openclaw-ci-limits.