크라우니캔버스 저장소.한선 O(n²) + OOM 크래시 근본수리
개요
crowny-canvas(:9620)
한선씨/저장소.한선에서 확증된 P0 결함(필드 재분할·유니크최신 O(n²))을 근본 수리. 재현 검증 중 원본 신고에 없던 2차 O(n²) 핫스팟(PSV 줄분리)까지 추가 발견해 함께 수리.
확증된 결함 (수리 전)
저장소_필드(행,idx) — 필드 접근마다 분리(행,"|")로 행 전체 재분할.
저장소_PSV파일유니크최신() — 저장소_유니크ID목록()이 growing 문자열 방문표+포함() 선형탐색(O(n²)), 저장소_최신행찾기()가 유니크id마다 전체 행배열 재스캔(유니크id수×전체행수 O(n²)).
- 실측(수리 전): 178~179행에서
/api/부팅 18~48s, 반복 호출 시 [ARRAY] OOM! 발생 → LaunchAgent(KeepAlive) 재기동 루프로 은폐.
수리 내용 (/Users/ef/crowny-canvas/한선씨/저장소.한선)
- 필드 캐시: 모듈전역
_필드캐시행/_필드캐시부분들 1행 메모이제이션 — 같은 행 문자열 연속 접근 시 재분할 생략. API 시그니처 불변(외부 호출부 무수정).
- 유니크ID목록: growing 문자열 방문표 →
맵생성/맵있나/맵넣어 해시맵(O(1) 존재확인). 검색.한선의 기존 관용구와 동일 패턴.
- PSV파일유니크최신: 유니크id별 전체 재스캔 → 단일 패스로 id→행 해시맵 채우며 latest-wins만 갱신(O(n)).
- (부수발견) PSV파싱: 1차 수정(
글자() 문자단위 순회 → 분리() 1회 호출)이 실측상 무효였음 — 문자열.한선의 분리()/찾기뒤()가 내부적으로 부분(문자열,i,i+1)을 위치별 반복호출하는 나이브 구현이라 분리() 호출 자체가 O(파일크기²)로 열화(실측: 12556자·179행 분리() 단독 922ms). 근본원인이 공유 표준라이브러리(문자열.한선, 이 작업 소유권 밖) 내부라 그쪽은 손대지 않고, 이 파일의 핫패스만 네이티브 버퍼(문자열버퍼/버퍼찾기/버퍼잘라/버퍼문자열/버퍼해제, O(1) 오프셋)로 우회. 검색.한선 검색_샤드누적()과 동일 관용구.
검증
- STRICT 재컴파일:
저장소.한선 자체 + 서버.한선(10개 모듈 전체 import 체인) 0경고.
- 셀프테스트(
_저장소테스트.한선, 삭제됨): 필드캐시 행전환 정합성, 유니크ID목록 순서(x,y,z), latest-wins 정확성 — 전부 PASS.
- 성능 실측(179~180행 실 데이터,
_저장소성능테스트*.한선, 삭제됨):
| 함수 | 수리 전 | 1차 수정 후 | 최종(버퍼) |
|---|---|---|---|
| PSV파싱 | (내재, 미분리측정) | 925ms |
1ms |
| PSV파일유니크최신 | 960ms+(추정 원본 18~48s대) | 960ms |
35ms |
| 페이지트리목록 전체 | 18~48s + OOM | 1046ms |
118ms |
라이브 재현(재컴파일 서버.toau → launchctl kickstart -k gui/$(id -u)/org.crowny.canvas → PID 4638):
/api/부팅 3연속: 0.249s/0.218s/0.203s, 200 (수리 전 18~48s+크래시)
10연속 부하: 0.2~2.8s 편차(200 유지, PID 불변·재기동 없음) — 편차는 이 macOS 1대에 crownyc 프로세스 150+개 동시구동(CPU 90%+ 점유 프로세스 다수 확인, ps aux) 중인 시스템 레벨 경합으로 판단, 원본 O(n²) 재발 아님(행 증가와 무관하게 균일 저지연).
/tmp/crowny-canvas.err에 kickstart 이후 신규 [ARRAY] OOM 없음(과거 재기동 이력만 잔존).관련 파일
/Users/ef/crowny-canvas/한선씨/저장소.한선 (수리 본체)
/Users/ef/crowny-canvas/서버.toau (재컴파일 반영)
/Users/ef/crowny-canvas/docs/00-작업계획서-에이전트디렉팅.md, docs/07-앱-계약.md (계약 SSOT, 무수정)
- LaunchAgent
org.crowny.canvas (kickstart로 재기동만, plist 무수정)
잔여 이슈
문자열.한선(공유 표준라이브러리)의 분리()/찾기()/찾기뒤()가 부분() 위치별 반복호출로 대형 문자열에서 O(n²) — 이 작업 범위 밖(파일 소유권=저장소.한선)이라 우회만 하고 원본은 무수정. 다른 서비스도 같은 함정 가능성 있어 별도 세션에서 문자열.한선 자체 개선 검토 필요(공유 인프라라 전 서비스 영향 — 반드시 별도 회귀검증 후 반영).
저장소_페이지메타JSON의 JSON 문자열 "+" 누적 연결(행당 9개 KV) — 234행 규모에서는 미미하나 규모 확대 시 동일 클래스 누적 O(n²) 우려, 필요 시 배열+합치기() 전환 검토.