T162 — STR 핸들 90% 조기경고 근본 규명·수리 (부분 완료)
개요
63개 서비스 로그가 동일 지점(432,000/480,000 = 90%)에서 [STR] 조기경고 발생.
표본 = /Users/ef/crowny-butler/libs/의미어라우터서버.한선(다운, 최다 162회).
근본 원인 규명
- crownyc.c str_new()의 STR_ID_MAX=480000, 90% 경고 로직(2506~2513행) 확인.
- 표본 서비스는 46,074줄 의미어라우터_모델.psv를 부트 시 1회 벌크 로드(모델로드()).
줄마다 버퍼읽기() 필드추출(핸들 3~4개) + 복합키 문자열연결(F=1회, LF=3~4회 concat)
→ 추정 30만~40만 핸들이
요청 트래픽 없이 부트 단계에서만 소비.
→ 실측: 재기동 직후(요청 0건)에도 로그에 "로드: N cubes" 직후 즉시 90% 경고 재현.
- 즉 가설(부트 공통 경로의 대량 문자열 소비) 확인. 다만 모델로드()는 이미
T143(2026-07-31)에서 버퍼 오프셋 스캔 방식으로 1차 수리된 상태였음에도 재현 →
str_new()의 str_gc()가 46k줄 단일 while 루프 안에서 임시 문자열(개별 필드값·
중간 concat 결과)을 충분히 회수하지 못함이 잔여 근본 원인으로 좁혀짐(VM GC 마크 스코프
의심, 완전 확정은 미완).
수리 내용 (이번 세션)
- 의미어라우터_코어.한선 공백제거() — per-char 문자열연결(out=out+c, 글자수만큼
핸들 소비하는 O(n) 안티패턴)을 공백런 스킵 + 부분() 구간절단 방식으로 교체
(핸들 소비 O(n)→O(구간수)). 동일 안티패턴이 프로젝트 전역 26개 파일에서 확인됨
(grep 'out = out + c' 등) — 잔여 파일은 자식 티켓으로 이관.
- /tmp 계측 빌드(crownyc_dbg, cc -O2 -lm -framework Security -framework CoreFoundation)로
격리 포트(19793)에서 검증 → 500 요청에도 여전히 90% 경고 재현, RSS 1.2GB 성장 확인
→ 부트 단계 원인이 우세함을 뒷받침.
- hanseonc_high로 프로덕션 toau 재컴파일 → /Users/ef/crowny-butler/libs/의미어라우터서버.toau
교체(백업: /tmp/의미어라우터서버.toau.bak_*) → launchctl bootout/bootstrap →
9793 응답 확인(TCP 리스닝 + 실제 라우팅 응답 정상). 단, 완전 해소는 아니며
간헐적 크래시-재기동 루프 지속(KeepAlive로 자동 복구, 기존 다운 상태 대비 순개선).
잔여 이슈
- str_gc() 대용량 단일루프 내 마크 스코프 정밀 조사(계측 빌드로 gc_runs/gc_freed 로깅 추가 필요).
- 46k줄 모델 로드를 N줄마다 명시적 str_gc() 강제호출로 청크화(부트 핸들 피크 완화).
- 동일 out=out+c 안티패턴 나머지 25개 파일 일괄 수리.
- 63개 서비스 전수 재현/수리 확산(표본 1건만 처리).
관련 파일
- /Users/ef/crowny-butler/libs/의미어라우터_코어.한선
- /Users/ef/crowny-butler/libs/의미어라우터서버.한선
- /Users/ef/crowny-butler/libs/의미어라우터_모델.psv (46,074줄)
- /Users/ef/CrownyOS/crownyc/crownyc.c (str_new/str_gc, 2328~2520행)
- ~/Library/LaunchAgents/org.crowny.의미어라우터.plist