OpenClaw 테스트 힙 누수
이 스킬은 테스트 메모리 조사에 사용됩니다. 힙 스냅샷을 사용할 수 있을 때 RSS만으로 추측하지 마십시오. 리테이너(retainers)나 도미네이터(dominators)가 호출 스택을 뒷받침할 때까지 스냅샷 이름 델타를 트라이에이지(triage) 증거로 간주하고 증명으로 간주하지 마십시오.
먼저 ../openclaw-test-performance/SKILL.md를 읽고 현재 test-performance 명령과 증명 라우팅을 확인하십시오.
런타임 수정 (예: 게이트웨이와 같은 장기 실행 서비스의 클로저 누수)의 경우 아래 런타임 수정 검증을 참조하세요. 이는 단위 테스트 프로파일링 워크플로우 대신 전용 테스트 도구(harnes)를 사용합니다.
워크플로우
-
먼저 실패하는 형태를 재현하십시오.
-
실제 엔트리포인트와 워커 예산을 일치시키십시오. 구성별 최대 RSS와 상위 파일 타이밍을 확인하는 기본적인 unit-fast의 경우 다음으로 시작하십시오:
pnpm test:perf:groups \ --config test/vitest/vitest.unit-fast.config.ts \ --allow-failures \ --output .artifacts/test-perf/unit-fast-memory.json -
의심되는 파일의 경우, 해당 파일을 하나의 워커로 다시 실행하고 wall/RSS 증거를 수집하십시오:
/usr/bin/time -l pnpm test <file> --maxWorkers=1 --reporter=verbose. -
현재
pnpm test실행은scripts/test-projects.mts에 의해 계획됩니다. 보고서가 구성 또는 워커 예산별로 특정된 경우, 출력된 Vitest 구성 또는 샤드를 기록하고 해당 형태를 유지하십시오.
-
-
가능한 가장 강력한 힙 증거를 수집하십시오.
pnpm test:perf:profile:runner -- --output-dir .artifacts/test-perf/vitest-runner-profile -- <file>을 실행하여 단위 러너의 CPU 프로필과 샘플링 힙 프로필을 얻으십시오. DevTools에서 힙 프로필을 열고 가장 큰 할당 패밀리를 검사하십시오.- 샘플링
.heapprofile출력은.heapsnapshot이 아닙니다. 이를 스냅샷 델타 헬퍼에 전달하지 마십시오. - 전용 테스트 도구 또는 다른 알려진 생성자가 반복되는
.heapsnapshot파일을 생성하는 경우, 동일한 PID의 스냅샷을.agents/skills/openclaw-test-heap-leaks/scripts/heapsnapshot-delta.mjs와 비교하십시오. - 스냅샷 또는 힙 프로필을 사용할 수 없는 경우, RSS 증가는 유용한 트라이에이지 증거이지만 누수 분류는 잠정적으로 유지하십시오.
-
수정을 선택하기 전에 성장을 분류하십시오.
- 성장이 Vite/Vitest 변환 소스 문자열,
Module,system / Context, 바이트코드, 디스크립터 배열 또는 속성 맵에 의해 지배되는 경우, 장기 실행 워커에서 보존된 모듈 그래프 성장일 가능성이 높습니다. - 성장이 앱 객체, 캐시, 버퍼, 서버 핸들, 타이머, 모의 상태, SQLite 상태 또는 유사한 런타임 객체에 의해 지배되는 경우, 정리 또는 수명 주기 누수일 가능성이 높습니다.
- 이름이 모호한 경우, 확실한 레이블을 피하고 DevTools에서 주요 델타에 대한 리테이너/도미네이터를 검사하십시오.
- 성장이 Vite/Vitest 변환 소스 문자열,
-
올바른 계층을 수정하십시오.
- 공유 워커에서 보존된 변환 모듈 성장 가능성이 있는 경우:
- 소유하는 Vitest 구성과
scripts/test-projects.test-support.mjs의 프로세스 청킹을 검사하십시오. 동일한 형태의 증거가 공유 워커 보존이 원인임을 보여줄 때만 프로세스 수명 또는 프로젝트 소유권을 수정하십시오. test/vitest/vitest.unit-fast-isolated.config.ts는 감사된 상태 저장 테스트를 위한 것으로, 새로운 모듈 그래프가 필요합니다. 일반적인 메모리 핫스팟 목록으로 사용하지 마십시오.
- 소유하는 Vitest 구성과
- 실제 누수의 경우:
- 영향을 받은 테스트 또는 런타임 정리 경로를 패치하십시오.
- 누락된
afterEach/afterAll, 모듈 재설정 간격, 보존된 전역 상태, 해제되지 않은 DB 핸들 또는 파일을 넘어 지속되는 리스너/타이머를 찾으십시오.
- 공유 워커에서 보존된 변환 모듈 성장 가능성이 있는 경우:
-
가장 직접적인 증거로 확인하십시오.
- 동일한 그룹화된 또는 범위 지정 명령을 다시 실행하고 최대 RSS 추세 또는 OOM이 감소했는지 확인하십시오.
- 전용 생성자가 힙 프로필 또는 스냅샷을 생성하는 경우, 동일한 생성자를 반복하고 동등한 아티팩트를 비교하십시오.
- 라우팅 또는 구성 변경의 경우, 예상되는 Vitest 구성 또는 샤드가 시작되고 영향을 받는 테스트가 완료되는지 확인하십시오.
휴리스틱
- 모든 것을 누수라고 부르지 마십시오. 격리되지 않은 공유 Vitest 프로젝트에서의 성장은 애플리케이션 객체 누수보다는 워커 수명 문제일 수 있습니다.
scripts/test-projects.mts,scripts/test-group-report.mts,scripts/run-vitest-profile.mts는 현재 실행, 그룹화된 RSS 및 프로필 엔트리포인트입니다.[test] starting ...줄은 재현할 Vitest 구성 또는 샤드를 식별합니다..artifacts/vitest-shard-timings.json은 스케줄링을 위한 구성/샤드 기간을 저장합니다. 파일 수준 메모리 핫스팟 또는 동작 매니페스트가 아닙니다.- 동일한 워커 PID에서 여러 간격에 걸쳐 동일한 보존된 객체 패밀리가 증가하는 경우, 직관보다 스냅샷을 신뢰한 다음 모호한 호출을 리테이너 증거로 확인하십시오.
스냅샷 비교
- 직접 비교:
node .agents/skills/openclaw-test-heap-leaks/scripts/heapsnapshot-delta.mjs before.heapsnapshot after.heapsnapshot
- 하나의 레인(lane) 내에서 PID별로 가장 빠른/가장 늦은 스냅샷을 자동 선택:
node .agents/skills/openclaw-test-heap-leaks/scripts/heapsnapshot-delta.mjs --lane-dir <snapshot-directory>
- 유용한 플래그:
--top 40--min-kb 32--pid 16133
상위 양수 델타를 먼저 읽으십시오. 모듈 변환 아티팩트의 큰 양수 성장은 공유 프로세스 수명 또는 프로젝트 소유권을 가리키고, 런타임 객체의 큰 양수 성장은 실제 누수를 시사합니다. 이름만으로 결정되지 않는 경우, DevTools에서 동일한 스냅샷 쌍을 열고 최상위 행의 리테이너/도미네이터를 검사한 후 근본 원인을 선언하십시오.
런타임 수정 검증 (테스트 메모리 아님)
위의 워크플로우는 Vitest 워커 메모리 성장 진단을 위한 것입니다. 런타임/클로저 수정이 캡처된 상태를 실제로 해제하는지 검증하려면 전용 테스트 도구를 사용하십시오:
pnpm leak:embedded-run—scripts/embedded-run-abort-leak.ts를 실행합니다. 함수 형태의 범위에서 N번의 중단된 실행을 루프하여runEmbeddedAttempt를 모방하고, 힙 스냅샷을 작성하며,FinalizationRegistry를 사용하여 추적된 인스턴스 카운트와 RSS 델타를 기반으로 보존 성장에 대한 PASS/FAIL 판정을 보고합니다.
모드:
closure-extracted(기본값) — 프로덕션 수정 형태 (모듈 범위의 헬퍼).closure-inline— 수정 전 형태 (러너 범위 내의 클로저). 민감도 검사로 사용: 통과하면 하니스가 손상된 것이지 버그를 수정한 것이 아닙니다.synthetic-leak— 모듈 수준 버킷을 통해 의도적으로 유지합니다. 실제 수정에 대한 PASS를 신뢰하기 전에 하니스가 누수를 감지할 수 있는지 확인하는 데 사용합니다.
스냅샷은 .tmp/embedded-run-abort-leak/에 저장됩니다. 위와 동일한 스크립트로 비교:
node .agents/skills/openclaw-test-heap-leaks/scripts/heapsnapshot-delta.mjs \
.tmp/embedded-run-abort-leak/baseline-*.heapsnapshot \
.tmp/embedded-run-abort-leak/batch-N-*.heapsnapshot --top 30
다른 런타임 누수를 수정할 때는 이 하니스를 개조(retrofit)하는 대신 새로운 하니스를 추가하십시오. 픽스처 함수는 누수가 있는 함수의 어휘 범위를 모방해야 하며 일반적인 중단 루프가 되어서는 안 됩니다.
출력 기대 사항
이 스킬을 사용할 때 다음을 보고하십시오:
- 정확한 재현 명령.
- 재현된 Vitest 구성 또는 대상, 스냅샷을 사용할 수 있는 경우 비교된 PID.
- 힙 프로필 또는 스냅샷 델타에서 지배적인 보존된 객체 패밀리(사용 가능한 경우).
- 문제가 실제 누수인지 공유 워커 보존 모듈 성장인지, 그리고 리테이너/도미네이터가 이를 확인했는지 여부.
- 구체적인 수정 또는 영향 완화 패치.
- 확인한 내용과 스냅샷 오버헤드로 인해 확인하지 못한 내용.