V8의 기능을 활용하여 Node.js 위에서 실행되는 애플리케이션의 프로파일을 얻을 수 있다.

 

구조

[DevTools / node inspect CLI]
                 │  (WebSocket, JSON-RPC)
                ▼
 ┌───────────────┐
  │ node::inspector::Agent                    │  ← 디버거 서버 (포트 9229)
  │   └─ NodeInspectorClient             │  ← V8 브리지
  │        └─ v8_inspector API              │  ← V8 디버거 엔진
 └───────────────┘
                │
               ▼
    [JS 코드 실행부]

동작

타겟 애플리케이션을 --inspect 옵션으로 실행하거나 실행 중 USR1 신호를 보내면

inspect agent 가 실행되어 9229 포트로 디버거 서버를 띄운다.

 

테스트 방법

  1. 타겟 애플리케이션 실행: node를 --inspect 옵션으로 실행하거나 실행 중 USR1 신호를 보냄
    • kill -USR1 {pid}
  2. inspector 프로세스 실행: pid 나 host:port 를 명시하여 타겟에 attach
    • node inspect [--pid {process id} | 192.168.0.10:9229 ]
  3. inspector 프로세스에서 profile, profileEnd 커맨드를 순차 실행 후 profiles 로 결과 파일 확인 및 저장
    • profiles[{인덱스}].save('{경로}') 

 

결과 파일 읽기

  • 전체 구조
{
  "nodes": [ ... ],      // 함수 호출 트리 (각 노드: 함수 하나)
  "samples": [ ... ],    // 특정 시점에 실행 중이던 node.id
  "startTime": 1093425539501,
  "endTime": 1093450780167
}
  • nodes 구조 (예시)
{
  "id": 34,
  "callFrame": {
    "functionName": "(익명함수)",
    "scriptId": "95",
    "url": "file:///Users/jihyechoi/Documents/testcode/my-server.js",
    "lineNumber": 13,
    "columnNumber": 33
  },
  "hitCount": 697,
  "children": [35, 38],
  "positionTicks": [
    {"line": 27, "ticks": 2},
    {"line": 26, "ticks": 695}
  ]
}
  • functionName 종류
(idle) 이벤트 루프가 놀고 있을 때 (대기 시간)
(program) 초기 런타임 세팅
(garbage collector) GC 중 사용된 CPU
processTicksAndRejections 이벤트 루프의 마이크로태스크 처리
parserOnHeadersComplete HTTP 요청 파싱 완료 콜백
onconnection / Socket TCP 연결 수락 및 스트림 설정
emit Node.js EventEmitter
end, _send, _writeRaw 응답을 네트워크로 전송 중
Readable.read, Writable.write 스트림 I/O 동작
  • samples: 샘플링 타이머가 매번 실행 중인 함수의 id를 기록한 것. 많이 등장한 id 의 함수가 CPU를 많이 점유했다는 뜻이다

+ Recent posts