Rendimiento de Pruebas en OpenClaw
Usa evidencia primero. El objetivo es mejorar la velocidad real de pnpm test, las suites de plugins y el inspector de plugins, así como reducir el RSS, manteniendo la cobertura intacta, no ajustar el runner a base de suposiciones.
Flujo de Trabajo
- Lee los archivos
AGENTS.mdlocales relevantes antes de editar:src/agents/AGENTS.mdpara agentes/cuellos de botella de importación.src/channels/AGENTS.mdysrc/plugins/AGENTS.mdpara pereza de plugins/canales.src/gateway/AGENTS.mdpara pruebas del ciclo de vida del servidor.test/helpers/AGENTS.mdysrc/channels/plugins/contracts/test-helpers/AGENTS.mdpara helpers de contratos compartidos.src/infra/outbound/AGENTS.mdpara pruebas de salida/media/acción.
- Establece una línea base antes de cambiar código:
- Prefiere
pnpm test:perf:groups --full-suite --allow-failures --output <archivo>para clasificación de suites completas. - Para la amplitud de plugins empaquetados, ejecuta el comando relevante más pequeño (
pnpm test:extensions:batch <plugin[,plugin...]>o comando del inspector de plugins) antes de saltar al barrido completo de extensiones. - Para un punto caliente específico, usa:
/usr/bin/time -l pnpm test <archivo-o-archivos> --maxWorkers=1 --reporter=verbose - Si hay sospecha de importaciones pesadas, añade:
OPENCLAW_VITEST_IMPORT_DURATIONS=1 OPENCLAW_VITEST_PRINT_IMPORT_BREAKDOWN=1.
- Prefiere
- Separa el ruido del runner del costo real del archivo:
- Compara la duración de Vitest, el tiempo del cuerpo de la prueba, el desglose de importaciones, el tiempo de pared y el RSS máximo.
- Vuelve a ejecutar archivos individuales cuando los números de grupos/suites completas parezcan desactualizados o ruidosos.
- Si una ejecución agrupada de suite completa reporta una falla de carril pero el JSON dice que las pruebas pasaron, captúralo como ruido del arnés y verifica el archivo sospechoso directamente.
- Elige el próximo ataque según el retorno y el riesgo:
- Alto retorno: un archivo/prueba domina segundos o RSS y tiene una raíz clara.
- Alto apalancamiento: un plugin o barril del SDK hace que cada ejecución del inspector de plugins o lote de extensiones cargue un runtime amplio.
- Menor riesgo: descriptores estáticos, análisis de destino, enrutamiento, omisión de autenticación, sugerencias de configuración, fixtures de registro o ciclo de vida del servidor de pruebas.
- Mayor riesgo: comportamiento real de memoria/tiempo de ejecución, proveedores en vivo, contratos de protocolo o refactorizaciones amplias de producción.
- Arregla la causa raíz, no el síntoma:
- Mueve metadatos estáticos/análisis a helpers estrechos o artefactos ligeros reutilizados por el runtime completo y las rutas rápidas.
- Prefiere inyección de dependencias, búsqueda solo de plugins cargados, fixtures explícitos y helpers puros en lugar de mocks amplios.
- Reutiliza servidores/clientes a nivel de suite cuando un handshake nuevo sea irrelevante.
- Mantén los planificadores/bucles en segundo plano desactivados a menos que la prueba demuestre planificación.
- En rutas de plugins, mueve metadatos estáticos a artefactos de manifiesto/ligeros y mantén las cargas de runtime de plugins detrás de límites de ejecución explícitos.
- Preserva la forma de la cobertura:
- No elimines una prueba de integración lenta a menos que la composición exacta de producción se extraiga en un helper con nombre y se pruebe.
- Mantén un humo de integración barato cuando el cableado entre componentes sea importante.
- Indica explícitamente qué cobertura incidental se eliminó, si la hubo.
- Vuelve a comparar el mismo comando después del cambio y calcula los segundos y el porcentaje de mejora.
- Actualiza el informe en ejecución cuando se solicite o cuando este hilo esté rastreando uno. Incluye comandos antes/después, artefactos, notas de cobertura, verificación y el próximo orden de ataque.
- Prepara las rutas previstas, confirma con Git estándar y empuja cuando el usuario lo haya solicitado. Prepara solo los archivos modificados para este ataque.
Flujo de Trabajo para Suites de Plugins
Usa esta sección cuando el trabajo de rendimiento involucre plugins empaquetados, inspector de plugins, barriles del SDK, pruebas de límites de paquetes o suites de extensiones.
- Primero mapea la forma de la suite:
- pruebas fuente:
pnpm test extensions/<id>opnpm test:extensions:batch <id> - límites de paquetes:
pnpm run test:extensions:package-boundary:canaryypnpm run test:extensions:package-boundary:compile - todas las pruebas fuente empaquetadas:
pnpm test:extensions - memoria de importación de plugins:
pnpm test:extensions:memory -- --json .artifacts/test-perf/extensions-memory.json - trabajo de inspector/reporte de plugins: mantén las primitivas de reporte en
plugin-inspector; mantén los wrappers ligeros y captura el RSS máximo cuando el comando lo admita.
- pruebas fuente:
- Empieza estrecho, luego amplía:
- un plugin cambiado: ejecuta las pruebas de ese plugin y el segmento del inspector de plugins.
- barril público del SDK cambiado: añade plugins representativos de proveedor, canal, memoria y características.
- espejo del cargador/runtime cambiado: añade verificaciones de límites de paquetes y prueba de compilación/empaquetado según sea necesario.
- comportamiento desconocido de plugin compartido: ejecuta grupos
test:extensions:batchantes depnpm test:extensions.
- Trata las fallas del inspector de plugins como señales de producto:
- El JSON debe analizarse.
- Las advertencias/errores deben clasificarse, no ocultarse.
- La captura del runtime debe ser silenciosa y tolerante a la configuración.
- La salida del comando debe incluir tiempo de pared, código de salida y RSS máximo cuando esté disponible.
- Sigue
$openclaw-testingpara la selección del host. Los benchmarks de fuentes confiables pueden ejecutarse localmente con condiciones de máquina/carga comparables. Usa$crabboxcuando el empaquetado limpio, el comportamiento de Linux/plataforma, el aislamiento o una solicitud remota explícita sean parte de la prueba; reutiliza y limpia solo el lease propio. - Si el rendimiento del plugin es sensible al artefacto del paquete, cambia a
release-openclaw-plugin-testingy Aceptación de Paquetes en lugar de confiar solo en la temporización de la fuente.
Recopilación de Métricas
Recopila al menos una métrica estable antes y después. Prefiere la misma máquina y el mismo comando. Para comparaciones en Testbox, usa el mismo ID tbx_... cuando sea posible.
| Métrica | Uso | Fuente preferida |
|---|---|---|
| tiempo de pared | costo de suite visible para el usuario | /usr/bin/time -l, duración del wrapper de prueba, tiempo de ejecución de Testbox |
| duración de Vitest | costo del cuerpo de prueba/importación | Salida de Vitest por archivo/fragmento |
| duración de import | cargas amplias de barril/runtime | OPENCLAW_VITEST_IMPORT_DURATIONS=1 |
| RSS máximo | presión de memoria y riesgo de OOM | /usr/bin/time -l, pnpm test:extensions:memory, resúmenes de memoria del wrapper |
| CPU/usuario/sistema | división entre límite de CPU y espera | /usr/bin/time -l localmente, temporización de trabajos de Testbox cuando la CPU local es ruidosa |
| evidencia de heap | fuga real vs gráfico de módulos retenido | flujo de trabajo openclaw-test-heap-leaks |
Comando local específico con CPU/RSS:
timeout 240 /usr/bin/time -l pnpm test <archivo> --maxWorkers=1 --reporter=verbose
Perfil de memoria de importación de plugins:
pnpm build
pnpm test:extensions:memory -- --top 20 --json .artifacts/test-perf/extensions-memory.json
Memoria de importación de plugin específico:
pnpm test:extensions:memory -- --extension discord --extension telegram --skip-combined
Escalada de Heap/RSS:
pnpm test:perf:groups \
--config test/vitest/vitest.unit-fast.config.ts \
--allow-failures \
--output .artifacts/test-perf/unit-fast-memory.json
pnpm test:perf:profile:runner -- \
--output-dir .artifacts/test-perf/vitest-runner-profile -- <archivo>
Usa openclaw-test-heap-leaks cuando el RSS siga creciendo entre intervalos, los workers fallen por OOM, o el comando sospechoso tenga retención de objetos de aplicación. No llames fuga al crecimiento de RSS hasta que las instantáneas o los retenedores lo respalden.
Causas Raíz Comunes
- Runtime completo de canal/plugin empaquetado cargado para datos estáticos.
- Respaldo de
getChannelPlugin()usado cuando un fixture ya cargado o un analizador puro sería suficiente. - Barriles anchos de
api.ts,runtime-api.ts,test-api.tso plugin-sdk arrastrados a pruebas calientes. - Alias raíz del SDK o barriles de paquetes que jalan subrutas enfocadas de vuelta a un gráfico de plugin amplio.
- Inspector de plugins cargando código de runtime solo para renderizar metadatos, informes o puntuaciones de políticas de CI.
- Captura de plugins empaquetados reutilizando estado real de configuración/casa en lugar de estado sintético, redactado y aislado.
- Mocks parciales usando
importActual()alrededor de módulos amplios. vi.resetModules()más importaciones frescas en bucles por prueba.- Registro de plugins de prueba sembrado en
beforeAllmientras el estado del runtime se restablece enafterEach. - Inicio de gateway/servidor/cliente por prueba cuando bastaría con restablecer el estado.
- Selección de modelo/auth por defecto en tiempo de ejecución pagada por instantáneas o fixtures inactivos.
- Descubrimiento de media/acción propiedad del plugin activado antes de verificar si los argumentos contienen campos propiedad del plugin.
- Ejecuciones paralelas de Vitest compartiendo
node_modules/.experimental-vitest-cachesin valores distintos deOPENCLAW_VITEST_FS_MODULE_CACHE_PATH.
Comandos de Benchmark
Archivo específico:
timeout 240 /usr/bin/time -l pnpm test <archivo> --maxWorkers=1 --reporter=verbose
Archivo específico con desglose de importación:
timeout 240 /usr/bin/time -l env \
OPENCLAW_VITEST_IMPORT_DURATIONS=1 \
OPENCLAW_VITEST_PRINT_IMPORT_BREAKDOWN=1 \
pnpm test <archivo> --maxWorkers=1 --reporter=verbose
Suite agrupada:
pnpm test:perf:groups --full-suite --allow-failures \
--output .artifacts/test-perf/<nombre>.json
Lote de extensiones:
pnpm test:extensions:batch <plugin[,plugin...]> -- --reporter=verbose
Todas las pruebas de extensiones:
pnpm test:extensions
Verificaciones de límites de paquetes de plugins:
pnpm run test:extensions:package-boundary:canary
pnpm run test:extensions:package-boundary:compile
Reutilizar un informe JSON existente de Vitest:
pnpm test:perf:groups --report <vitest-json> \
--output .artifacts/test-perf/<nombre>.json
Verificación
- Siempre ejecuta la superficie de prueba específica que prueba el cambio.
- Cambios en fuente: pruebas locales enfocadas + verificación específica de tipo/lint/formato antes de empujar;
pnpm check:changedopcional. CI de PR = prueba amplia. Testbox solo para brechas de CI/local, concesión inmediata; reutilización de Testbox calentado cuando se seleccione. - Para cambios solo de prueba, ejecuta
pnpm test:changedo las pruebas exactas editadas. - Ejecuta
pnpm buildcuando toques carga perezosa, artefactos empaquetados, límites de paquetes, importaciones dinámicas, salida de compilación o superficies públicas. - Para cambios en SDK/barril/runtime de plugins, compara commits exactos con
pnpm plugin-sdk:api:diff -- --base <sha-base> --head <sha-cabeza>cuando la superficie de la API pública pueda desviarse. Para prueba local de PR, usa la base de fusión de la rama como<sha-base>y el commit de cabeza exacto probado como<sha-cabeza>. - Para correcciones de rendimiento en suites de plugins, verifica al menos un lote de plugin representativo más la puerta cambiada; usa Aceptación de Paquetes si el error solo existe en un artefacto empaquetado.
- Si faltan dependencias o están desactualizadas, ejecuta
pnpm instally reintenta el comando exacto que falló una vez. - Usa el formato de informe:
| Métrica | Antes | Después | Ganancia |
| ----------------- | -----: | ------: | -----------------: |
| Tiempo de pared | `Xs` | `Ys` | `-Zs` (`P%`) |
| RSS máximo | `XMB` | `YMB` | `-ZMB` (`P%`) |
| CPU usuario/sistema | `X/Ys`| `A/Bs`| explicar |
Transición
Mantén el resumen final conciso:
- Causa raíz.
- Alcance de la suite/plugin.
- Archivos modificados.
- Tiempo de pared, Vitest/importación, CPU y RSS antes/después, cuando estén disponibles.
- Clasificación de fuga si hubo memoria involucrada: fuga real, gráfico de módulos retenido o no concluyente.
- Cobertura conservada.
- Comandos de verificación.
- ID de Testbox o URL del flujo de trabajo para pruebas remotas.
- Hash del commit y estado del push.