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

크라우니캔버스 — 컬렉션.한선 O(n²) P0 수리

개요

컬렉션.한선(F4 컬렉션/DB 엔진)이 저장소.한선과 동일한 O(n²) 안티패턴을 "의도적 복제" 주석을 단 채 보유하고 있어 P0로 지목됨. 저장소.한선이 이미 받은 수리 패턴(모듈전역 1행 필드캐시 + 해시맵 유니크)을 동일하게 적용하고, 실측 결과 그것만으로는 목표(200건 <300ms)에 못 미쳐 근본원인 2(글자()/부분() 매호출 O(len) 재스캔에 기반한 PSV파싱)까지 추가로 수리했다.

무엇을 했는지

  1. 컬렉션_필드(): 매 접근마다 분리(행,"|") 재호출하던 것을 저장소_필드()와 동일한
모듈전역 1행 캐시(_C_필드캐시행/_C_필드캐시부분들)로 교체 — 같은 행 문자열 반복 조회 시 재분할 생략.
  1. 컬렉션_유니크ID목록(): growing-string 방문표 + 포함하나() 선형탐색 누적(O(n²))을
해시맵(맵생성/맵있나/맵넣어, O(1))으로 교체 — 저장소_유니크ID목록과 동일 관용구. (현재 호출부는 없으나 "동일 사상" 유지 원칙상 함께 수리)
  1. 컬렉션_PSV파싱() (근본원인 2, 위 두 수리만으론 부하테스트 6.28초 관찰 후 추가 발견):
글자(내용,i)를 파일 전체에 대해 문자 단위로 순회하는 구조라, 글자()/부분()이 "매호출 O(len) 전체 재스캔"인 VM 특성상 전체가 O(파일크기²)로 열화(저장소.한선이 이미 진단·수리한 근본원인과 동일). 저장소_PSV파싱과 동일한 네이티브 버퍼(BUF_*, O(1) 오프셋) 기반으로 교체. 버퍼 핸들은 함수 내부에서만 생성·해제되고 반환값은 순수 문자열 배열이라, 이 파일에 이미 문서화된 "조건식 내 버퍼함수 인라인 평가뒤집힘" 함정(2026-07-24 이전 시도 철회 사유)과는 무관함을 확인 후 적용.

검증

  • CROWNY_STRICT=1 hanseonc_high 컬렉션.한선 → 0 경고, 컴파일 성공.
  • CANVAS_COLLECTION_SELFTEST=1 자체테스트 재실행 → 7/7 PASS, 0 FAIL (스키마/속성순서/
레코드생성/필터/정렬/합계/뷰적용/바인딩 전부 기존과 동일 결과값 일치).
  • 200건 레코드 생성 후 조회 실측(격리 프로세스, hanseonc_high 독립 실행):
  • 수리 전(1·2만 적용, PSV파싱 미수리): 목록+필터+정렬+합계 합산 6.28초 — 목표 미달.
  • PSV파싱까지 수리 후: 단일 뷰적용(필터+정렬 결합, 실제 API 사용 패턴과 동일) 245ms
  • (VM기동 baseline ~14ms 포함) — <300ms 목표 충족. 개별 연산 목록/필터/합계는 각 104~116ms, 정렬(내부에서 목록 재조회 포함)은 320ms로 개별 호출 기준 다소 여유 없음 — 추후 서버.한선 API 핸들러가 여러 연산을 한 요청에서 연쇄 호출하는 경우 맵빌드 결과를 요청 스코프에서 재사용하도록 추가 최적화 여지 있음(현재는 함수별 독립 빌드, F4 계약상 뷰적용 경로가 실제 API 소비 형태이므로 1차 목표는 달성).
    • 서버.한선(컬렉션.한선 가져옴) 재컴파일 → 0 경고 → `launchctl kickstart -k
    gui/$(id -u)/org.crowny.canvas 재기동 → GET / 200, GET /api/부팅` 정상 응답 라이브 확인.

    관련 파일

    • /Users/ef/crowny-canvas/한선씨/컬렉션.한선 (수리 대상, 소유 파일)
    • /Users/ef/crowny-canvas/한선씨/저장소.한선 (수리 패턴 원본 참조)
    • /Users/ef/crowny-canvas/서버.토au (재컴파일 산출물)

    잔여 이슈

    • 여러 컬렉션 연산(목록+필터+정렬+합계)을 한 요청에서 순차 호출하는 상위 API 패턴이
    생기면, 요청 스코프 단위 맵빌드 캐시(1회 빌드 공유)로 추가 절감 여지 있음 — 현재는 각 공개 함수가 독립적으로 1회씩 파일을 읽음(O(n)이므로 안전하나 호출 누적 시 선형 가산).
    • 컬렉션_JSON값/컬렉션_문자열비교 등은 레코드당 값 문자열이 짧아 현재 규모에선 문제
    없으나, 속성값이 매우 길어지는 경우 별도 실측 필요.