<!-- task=m-large-payload-followup-optimization/04_ws_fixed_latency plan=0 tag=PERF -->

# Code Review Reference - PERF

> **[IMPLEMENTING AGENT — READ FIRST] Filling in this file is the mandatory final step of implementation.**
> The task is NOT complete until every implementation-owned section below is filled in.
> Complete the `구현 체크리스트`; the final checklist item is mandatory before saving.
> Fill implementation-owned sections, then stop with active files in place and report ready for review.
> If implementation is blocked by a user-only decision, user-owned external environment prerequisite, or scope conflict, fill `사용자 리뷰 요청` with evidence and stop with active files in place; code-review decides whether to write `USER_REVIEW.md`.
> Do not ask the user directly, present choices in chat, or call `request_user_input` during implementation.
> Finalization is review-agent-only.

## 개요

date=2026-06-14
task=m-large-payload-followup-optimization/04_ws_fixed_latency, plan=0, tag=PERF

## Roadmap Targets

- Milestone: `agent-roadmap/milestones/large-payload-followup-optimization.md`
- Task ids:
  - `ws-fixed-latency-path`: WS 계열 fixed latency가 지속되면 common/worker/gateway 경로 분석
- Completion mode: check-on-pass

## 이 파일을 읽는 리뷰 에이전트에게

> **[REVIEW AGENT ONLY]** 아래 종결 절차는 코드리뷰 에이전트 전용이다. 구현 에이전트는 이 섹션을 실행하지 않는다.

각 항목의 구현을 실제 소스 파일과 대조하고, `검증 결과` 섹션의 출력이 코드와 일치하는지 확인하세요.

## 구현 항목별 완료 여부

| 항목 | 완료 여부 |
|------|---------|
| [PERF-1] low-latency 설정 및 phase 계측 | [x] |
| [PERF-2] fixed latency row 수집 | [x] |

## 구현 체크리스트

- [x] [PERF-1] TypeScript/Kotlin WS/TCP socket 경로의 low-latency 설정과 phase 계측을 추가해 gateway off/on과 transport latency를 분리한다.
- [x] [PERF-2] fixed latency 재현 stress를 실행하고 개선 여부와 남은 병목 후보를 review stub에 수치로 기록한다.
- [x] TypeScript gateway/WS roundtrip 및 Kotlin WS quick stress를 실행해 correctness와 stability hard gate가 유지되는지 확인한다.
- [x] CODE_REVIEW-*-G??.md의 구현 에이전트 소유 섹션을 실제 구현 내용과 검증 출력으로 채운다. 이 항목이 완료되기 전에는 구현이 완료된 것이 아니다.

## 코드리뷰 전용 체크리스트

> **[REVIEW AGENT ONLY]** 이 체크리스트는 코드리뷰 에이전트만 사용한다.

- [x] `코드리뷰 결과`에 `PASS`, `WARN`, `FAIL` 중 하나의 판정을 append한다.
- [x] active `CODE_REVIEW-*-G??.md`를 `code_review_cloud_G07_N.log`로 아카이브한다.
- [x] active `PLAN-*-G??.md`를 `plan_cloud_G07_M.log`로 아카이브한다.
- [x] `.gitignore`의 Agent-Ops 관리 block을 확인한다.
- [x] PASS이면 `complete.log`를 작성하고 active task 디렉터리를 archive로 이동한다.
- [x] PASS이고 task group이 `m-<milestone-slug>`이면 완료 이벤트 메타데이터를 보고하고 roadmap 수정은 하지 않는다.

## 계획 대비 변경 사항

- `typescript/src/tcp_client.ts`: TLS 경로 별도 분기 없이 `TcpClient` 생성자에서 `socket.setNoDelay(true)`를 한 번 호출하도록 했다. `net.Socket`과 `tls.TLSSocket` 모두 `setNoDelay`를 제공하므로 `connectTcp`/`connectTcpTls` 양쪽에 동일하게 적용된다.
- Kotlin no-delay는 plan의 `NoDelaySocketFactory` shape 그대로 구현했다. plan이 우려한 TLS 충돌은 발생하지 않는다. OkHttp는 `sslSocketFactory`로 만든 SSL socket을 `socketFactory`가 만든 plain socket 위에 layering하므로, plain socket에 `tcpNoDelay`를 켜면 ws/wss 모두 적용된다. 별도 TLS 분기를 추가하지 않았다.
- TypeScript phase 계측은 plan대로 stdout `ROW|` schema를 건드리지 않고 `emitRow`에서 stderr `DIAG fixed-latency ...` 한 줄을 추가하는 방식으로만 구현했다. 기존 `log()`(stderr) helper를 재사용했다.
- Kotlin `kotlin/crosstest/stress.kt`에도 동일한 stderr `DIAG fixed-latency ...` 진단을 `emitRow`에 추가했다. 이 파일은 sibling task `03_kotlin_tcp_parallel`의 변경이 이미 들어와 있어, 그쪽 변경을 건드리지 않고 `emitRow` 말미에만 추가했다.
- plan에는 명시되지 않았지만 `typescript/test/ws.test.ts`에 fake socket으로 `NodeWebSocket`이 `setNoDelay(true)`를 호출하는지 검증하는 단위 테스트를 추가했다(plan의 "필요 시" 조항 활용).

## 주요 설계 결정

- **근본 원인 가설: Nagle's algorithm + delayed-ACK.** `NodeWebSocket.writeFrame`는 header와 payload를 두 번의 `socket.write`로 보낸다(`node_ws_client.ts:388-389`). no-delay가 꺼진 상태에서 작은 두 번째 write가 delayed-ACK를 기다리며 막히는 전형적 패턴이 약 40ms 고정 지연과 일치한다. 따라서 socket no-delay를 명시하는 것을 1차 완화로 선택했다.
- **단일 지점 적용.** custom WS 경로(client `connectNodeWebSocket`, server `handleUpgrade`)는 모두 `NodeWebSocket`을 생성하므로 생성자에서 `socket.setNoDelay?.(true)`를 한 번 켜면 양쪽이 커버된다. 서버 `handleUpgrade`에는 `101 Switching Protocols` 핸드셰이크 응답 write도 즉시 flush되도록 raw socket 단계에서 `setNoDelay(true)`를 추가로 명시했다.
- **검증 결과 fixed latency 해소.** baseline(`20260613-202744-...stress-full.md`)에서 TypeScript gateway transport row는 gateway off/on 모두 p50 약 41ms였다. no-delay 적용 후 quick gateway run에서 ws gateway=off p50=1.604ms, gateway=on p50=1.545ms로 떨어졌고, WS roundtrip concurrency=1 p50도 0.645ms다. 약 40ms 고정 지연이 사라졌다.
- **남은 병목 후보.** gateway `worker_threads` mode는 여전히 p99=215.558ms tail을 보인다. 이는 no-delay와 무관한 worker_threads hop 자체의 tail이며 plan 배경에서 이미 별도 issue로 언급된 항목이다. Kotlin WS는 concurrency=1에서 p50=1.303ms로 깨끗하고, concurrency≥16에서의 p50 상승(44~59ms)은 per-request 고정 지연이 아니라 동시성 포화 특성이다. 두 항목 모두 이 plan의 범위 밖이며 후속 분석 후보로 남긴다.

## 사용자 리뷰 요청

_기본값은 `없음`이다. 구현 중 사용자 결정, 사용자 소유 외부 환경/secret/서비스 준비, 또는 계획 범위 변경 없이는 안전하게 진행할 수 없으면 아래 항목을 실제 내용으로 교체하고, 구현을 중단한 뒤 active 파일을 그대로 둔 채 리뷰를 요청한다. 구현 에이전트는 사용자에게 직접 질문하거나 선택지를 제시하거나 `request_user_input`을 호출하지 않는다. 후속 에이전트가 명령 재실행이나 산출물 수집으로 해소할 수 있는 검증 증거 공백만으로는 사용자 리뷰 요청을 작성하지 않는다._

- 상태: 없음
- 사유 유형: 없음
- 결정 필요: 없음
- 차단 근거: 없음
- 실행한 검증/명령: 없음
- 자동 후속 불가 이유: 없음
- 재개 조건: 없음

## 리뷰어를 위한 체크포인트

- no-delay 설정이 TLS/secure WS 경로를 깨지 않는지 확인한다.
- ROW schema가 performance parser와 호환되게 유지됐는지 확인한다.
- fixed latency가 남으면 남은 후보와 수치가 명확히 기록됐는지 확인한다.

## 검증 결과

_구현 에이전트가 각 중간 검증 및 최종 검증 명령 실행 후 출력을 여기에 붙여 넣는다._

### PERF-1 중간 검증
```text
$ cd typescript && npm test -- test/tcp.test.ts test/ws.test.ts
 ✓ test/tcp.test.ts (7 tests) 264ms
 ✓ test/ws.test.ts (12 tests) 1429ms
 Test Files  2 passed (2)
      Tests  19 passed (19)
# 신규 추가한 "NodeWebSocket enables TCP no-delay on its socket" 포함, ws.test.ts 11 -> 12 tests

$ cd kotlin && ./gradlew --offline test --tests com.tokilabs.proto_socket.WsTest
> Task :compileKotlin
> Task :test
BUILD SUCCESSFUL in 14s
11 actionable tasks: 4 executed, 7 up-to-date
# NoDelaySocketFactory 추가 후 컴파일/WsTest 통과
```

### PERF-2 중간 검증
```text
$ bash agent-ops/skills/project/run-proto-socket-test-matrix/scripts/run_stress.sh --quick --lang typescript,kotlin --transport ws --profile roundtrip
# TypeScript
DIAG fixed-latency profile=roundtrip transport=ws gateway=off p50=0.645 p99=1.863   # concurrency=1
DIAG fixed-latency profile=roundtrip transport=ws gateway=off p50=1.685 p99=3.986   # concurrency=16
DIAG fixed-latency profile=roundtrip transport=ws gateway=off p50=5.923 p99=6.178   # concurrency=64
DIAG fixed-latency profile=roundtrip transport=ws gateway=off p50=16.921 p99=25.548 # concurrency=256
DONE typescript: PASS (rows=4 skips=0 required_skips=0 violations=0)
# Kotlin
DIAG fixed-latency profile=roundtrip transport=ws p50=1.303 p99=27.231   # concurrency=1
DIAG fixed-latency profile=roundtrip transport=ws p50=44.270 p99=46.298  # concurrency=16
DIAG fixed-latency profile=roundtrip transport=ws p50=47.065 p99=47.564  # concurrency=64
DIAG fixed-latency profile=roundtrip transport=ws p50=59.129 p99=70.263  # concurrency=256
DONE kotlin: PASS (rows=4 skips=0 required_skips=0 violations=0)
전체 결과값: PASS

$ bash agent-ops/skills/project/run-proto-socket-test-matrix/scripts/run_stress.sh --quick --lang typescript --transport ws --profile gateway
DIAG fixed-latency profile=gateway transport=ws gateway=off p50=1.604 p99=4.027
DIAG fixed-latency profile=gateway transport=ws gateway=on p50=1.545 p99=2.673
DIAG fixed-latency profile=gateway transport=ws gateway=worker_threads p50=2.027 p99=215.558
DONE typescript: PASS (rows=6 skips=0 required_skips=0 violations=0)
전체 결과값: PASS
# baseline 약 41ms(off/on) -> off 1.604ms / on 1.545ms 로 고정 지연 해소.
# worker_threads p99 tail(215ms)은 no-delay와 무관한 별도 이슈로 잔존.
```

### 최종 검증
```text
$ cd typescript && npm run check
> tsc --noEmit
# exit 0

$ cd typescript && npm test -- test/tcp.test.ts test/ws.test.ts
 Test Files  2 passed (2)
      Tests  19 passed (19)

$ cd kotlin && ./gradlew --offline test --tests com.tokilabs.proto_socket.WsTest
BUILD SUCCESSFUL in 14s

$ bash .../run_stress.sh --quick --lang typescript,kotlin --transport ws --profile roundtrip
전체 결과값: PASS  (typescript rows=4, kotlin rows=4, violations=0)
결과 기록: agent-test/runs/20260614-103154-proto-socket-stress-quick.md

$ bash .../run_stress.sh --quick --lang typescript --transport ws --profile gateway
전체 결과값: PASS  (typescript rows=6, violations=0)
결과 기록: agent-test/runs/20260614-103211-proto-socket-stress-quick.md
```

---

> **[IMPLEMENTING AGENT — BEFORE SAVING] Have you filled in every implementation-owned section: completion table, implementation checklist, changes from plan, design decisions, and verification output?**

## 섹션 소유권

| Section | Owner | Note |
|---------|-------|------|
| Header comment, 개요, 리뷰 에이전트 지시 | Fixed at stub creation | 구현 에이전트는 수정하지 않는다. |
| Roadmap Targets | Fixed at stub creation from plan | PASS 시 code-review가 `complete.log`의 Roadmap Completion 근거로 복사한다. |
| 구현 항목별 완료 여부 | Implementing agent | 구현 에이전트가 `[ ]`를 `[x]`로 갱신한다. |
| 구현 체크리스트 | Implementing agent | final checkbox까지 반드시 채운다. |
| 코드리뷰 전용 체크리스트 | Review agent only | 구현 에이전트는 수정하거나 체크하지 않는다. |
| 계획 대비 변경 사항, 주요 설계 결정 | Implementing agent | 실제 구현 결과로 placeholder를 교체한다. |
| 사용자 리뷰 요청 | Implementing agent | 사용자 결정이 필요할 때만 `상태: 없음`을 교체한다. |
| 리뷰어를 위한 체크포인트 | Fixed at stub creation | 리뷰 초점이다. |
| 검증 결과 | Implementing agent | 실제 stdout/stderr를 붙인다. |

## 코드리뷰 결과

### 종합 판정

PASS

### 차원별 평가

| 차원 | 평가 | 근거 |
|------|------|------|
| correctness | Pass | TypeScript TCP/custom WS와 Kotlin OkHttp WS client에 no-delay가 적용됐고, 기존 WS/TCP request/response 동작이 유지된다. |
| completeness | Pass | 계획된 low-latency 설정, stderr diagnostic, stress row 수집, 남은 worker_threads tail 후보 기록이 완료됐다. |
| test coverage | Pass | TypeScript fake socket no-delay 테스트와 TCP/WS 회귀 테스트, Kotlin WS 테스트, quick stress row가 실행됐다. 리뷰 중 TypeScript/Kotlin 전체 smoke도 추가 확인했다. |
| API contract | Pass | stdout `ROW|`/summary schema는 유지되고 diagnostic은 stderr에만 추가됐다. 공개 protocol/schema 변경은 없다. |
| code quality | Pass | 변경은 transport 설정과 deterministic diagnostic에 국한되며 debug-only dead code나 불필요한 API 확장은 보이지 않는다. |
| plan deviation | Pass | TypeScript no-delay fake socket 테스트 추가는 계획의 "필요 시" 범위 안이며, Kotlin crosstest의 sibling 변경과 충돌하지 않게 `emitRow` 말미만 확장했다. |
| verification trust | Pass | 구현자가 기록한 stress 결과 파일의 row와 stderr diagnostic을 확인했고, 리뷰 중 핵심 검증 명령을 재실행해 모두 PASS를 확인했다. |

### 발견된 문제

없음

### 리뷰 중 재실행 검증

```text
$ cd typescript && npm run check
> tsc --noEmit
exit 0

$ cd typescript && npm test -- test/tcp.test.ts test/ws.test.ts
Test Files  2 passed (2)
Tests  19 passed (19)

$ cd kotlin && ./gradlew --offline test --tests com.tokilabs.proto_socket.WsTest
BUILD SUCCESSFUL in 2s

$ bash agent-ops/skills/project/run-proto-socket-test-matrix/scripts/run_stress.sh --quick --lang typescript,kotlin --transport ws --profile roundtrip
전체 결과값: PASS
결과 기록 파일: agent-test/runs/20260614-110207-proto-socket-stress-quick.md

$ bash agent-ops/skills/project/run-proto-socket-test-matrix/scripts/run_stress.sh --quick --lang typescript --transport ws --profile gateway
전체 결과값: PASS
결과 기록 파일: agent-test/runs/20260614-110215-proto-socket-stress-quick.md

$ cd typescript && npm test
Test Files  5 passed (5)
Tests  63 passed (63)

$ cd kotlin && ./gradlew test
BUILD SUCCESSFUL in 15s
```

### 다음 단계

PASS이므로 `complete.log`를 작성하고 task directory를 archive로 이동한다. Roadmap 업데이트는 code-review가 직접 수행하지 않고 런타임 완료 이벤트로 보고한다.
