---
name: perf
description: 프레임 예산 — 목표 FPS 와 측정 표본으로 p95 초과·히치·발열 저하·GC 할당을 판정하고, 에디터 측정은 증거로 받지 않는다. 트리거 "성능 최적화", "프레임 예산", "끊김", "스터터", "히치", "발열", "오브젝트 풀".
---
# perf
nereus:common 규칙을 따른다. 담당 에이전트: gameplay-engineer.
**엔진과 무관하다** — 프로파일러 사용법은 엔진 스킬·공식 문서가 갖고, 여기서는 측정을 판정한다.
드로우 콜·GPU 메모리는 `nereus-3d:renderbudget` 이 갖는다. 여기는 프레임 시간만 본다.
출처: awesome-gamedev-agent-skills `disciplines/performance-optimization` (Apache-2.0). 방법론을 판정으로 다시 썼다.
## 철칙 — 재기 전에 고치지 않는다
측정 없이 고친 성능은 대개 엉뚱한 곳을 고친다. 순서는 항상 같다:
**목표를 정한다 → 재현 가능한 최악 장면을 잡는다 → 잰다 → 병목 하나를 고친다 → 같은 장면·기기에서 다시 잰다.**
## 1. 잰다
릴리스(또는 development) 빌드를 **대상 최저 사양 기기**에서 돌려 프레임 시간(ms) 표본을 모은다.
CPU 프레임과 GPU 프레임 시간을 따로 얻을 수 있으면 같이 넣는다.
## 2. 판정한다
```bash
echo '{"targetFps":60,"build":"release","device":"target","samplesMs":[...],"cpuMs":5,"gpuMs":14,"gcBytesPerFrame":0}' \
| node plugins/nereus-game/lib/frame-budget.mjs
```
JS 에서는 `checkFrames(input)`. 예산은 프로파일이 아니라 **입력이 준다** — 같은 게임도 플랫폼마다 목표가 다르다.
| 위반 | 기준 | 대응 |
|---|---|---|
| `over-budget` | p95 > 1000/목표FPS | 병목 쪽(`bound`)의 가장 큰 비용 하나를 고친다 |
| `hitch-rate` | 예산 2배 넘는 프레임이 1% 초과 | 평균이 아니라 스파이크를 찾는다 — 로딩·생성·GC·경로탐색을 프레임에 나눠 깐다 |
| `thermal-drop` | 뒤 1/4 평균이 앞 1/4 의 1.2배 넘고 예산도 넘음 | 프레임 상한을 걸고 여유를 둔다. 60 고정보다 30 고정이 나은 구간이 있다 |
| `gc-per-frame` | 정상 상태 프레임당 할당 > 0 | 매 프레임 생성·해제를 풀링으로, 버퍼를 재사용한다 |
`bound` 가 `gpu` 면 CPU 코드를 다듬어도 소용없고, `cpu` 면 드로우 콜을 줄여도 소용없다. 반대쪽을 고치지 않는다.
## 3. 증거로 받는 것
`pass` 는 **위반이 없고** `evidence` 가 true 일 때만 true 다. `evidence` 는 `build` 가 `release`·`development` 이고
`device` 가 `target` 일 때만 true 다. 에디터·디버그 빌드나 개발 머신의 숫자는 거짓말을 한다 —
위반이 0 이어도 완료 근거로 쓰지 않는다. 에디터에서만 쟀으면 그렇다고 적는다.
보고는 수치로 한다: 전후 p95·히치 비율, 찾은 병목, 고친 것. "빨라졌을 것"은 보고가 아니다.
## 하지 말 것
- 재지 않은 코드를 최적화하지 않는다.
- 알고리즘(덜 하기·캐시·공간 분할·주기 낮추기)보다 핫 라인 미세 조정을 먼저 하지 않는다.
- 재미가 검증되기 전의 프로토타입을 성능 때문에 비틀지 않는다.