← 목록
기타 2026-07-24 5KB 읽기 4분

크라우니캔버스 저장소.한선 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. 필드 캐시: 모듈전역 _필드캐시행/_필드캐시부분들 1행 메모이제이션 — 같은 행 문자열 연속 접근 시 재분할 생략. API 시그니처 불변(외부 호출부 무수정).
  2. 유니크ID목록: growing 문자열 방문표 → 맵생성/맵있나/맵넣어 해시맵(O(1) 존재확인). 검색.한선의 기존 관용구와 동일 패턴.
  3. PSV파일유니크최신: 유니크id별 전체 재스캔 → 단일 패스로 id→행 해시맵 채우며 latest-wins만 갱신(O(n)).
  4. (부수발견) 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 |
  • 라이브 재현(재컴파일 서버.toaulaunchctl 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²) 우려, 필요 시 배열+합치기() 전환 검토.