T123 — crownyc VM "맵 유니크 사일런트캡" 진범 규명 + FREADALL 수리
개요
T62-T63-T64에서 관찰된 "R>3000에서 유니크 키 ~860 캡" 현상을 마이크로벤치로
재현·격리 조사한 결과,
해시맵(맵생성/맵넣어/맵꺼내) 자체는 결백하고 진범은
읽기()(FREADALL, opcode 249)의 고정 스택버퍼 65536바이트 절단으로 밝혀짐.
조사 과정
- 크로니OS crownyc.c의 맵 구조(MAP_SLOTS=729, 체인 grow) 코드 검토.
- 격리 마이크로벤치로 순수 맵만 테스트: 정수키 5000개, 문자열키 20000개
모두 100% 정확 보존 (
hits=5000,
hits=20000) — 맵 자체는 정상.
- 실제
_PSV파일유니크최신()(미션장부.한선) 로직을 합성 PSV 데이터로 재현:
- R=300 (파일 13KB, 65536바이트 미만): OLD/NEW 모두 정확(100 unique)
- R=1500/3000/5000 (파일 104KB~358KB, 65536바이트 초과): OLD 바이너리 모두
동일하게 320 unique로 캡 (기대값과 무관하게 파일 바이트 절단점에서 멈춤)
- 파일 크기와 무관하게 캡값이 거의 고정 → "행 수 비례 캡"이 아니라
"바이트 절단 캡"임을 강하게 시사
읽기() 소스 확인: case 249: FREADALL이 char rbuf[STR_MAX_LEN](65536B)
고정 버퍼로 fread하고 나머지를 그냥 버림 — 파일이 65536바이트 넘으면
뒷부분(행 후반부)이 조용히 사라짐. 결과:
분리(내용,"\n")가 앞부분 줄만
반환 → 유니크 ID 집계가 실제 데이터양과 무관하게 낮은 고정값에서 멈춤.
수리 내용
/Users/ef/CrownyOS/crownyc/crownyc.c opcode 249(FREADALL):
- 경로 문자열 케이스:
fseek/ftell로 실제 파일 크기를 구해 malloc으로
동적 버퍼를 잡고 전체를 읽음. 안전상한 64MB 초과 시에만 앞부분만 읽되
이번엔 stderr 경고를 남김(무음 손실 제거).
- 스트림 핸들 케이스: 65536바이트 청크로
realloc 성장하며 EOF까지 누적,
64MB 상한까지.
★절대 규칙 준수 — 라이브 바이너리 무접촉
/Users/ef/CrownyOS/crownyc/crownyc 은 전혀 재빌드/교체하지 않음
(mtime 7/12 그대로, md5 79b3ce666fda338beb3c5ef2448f0463 불변 확인).
- 수리분은
/tmp/crownyc-fix 로만 별도 빌드(`cc -O2 -o /tmp/crownyc-fix
crownyc.c -lm -framework Security -framework CoreFoundation`)해 검증.
검증 결과
| 조건 | OLD(라이브) | NEW(/tmp/crownyc-fix) |
|---|
| R=300(13KB, 65536B 미만) | 100 unique(정확) | 100 unique(정확, 동일) |
| R=1500/3000/5000(65536B 초과) | 320으로 캡(버그 재현) | FREADALL 자체는 전체(358340/358340바이트) 읽기 성공 확인(디버그 프린트 rn=358340) |
| 읽기() 단독 검증 | 46353자만 읽힘(절단) | 전체 258340자(UTF-8 문자수, 한글 포함 바이트≠문자수는 정상) 읽힘 |
잔여 이슈(별도 티켓, 이번 수정과 무관):
_PSV파일유니크최신()이 R=1500~5000
스케일에서
분리()+
맵넣어() 체인이 O(n×R)~O(n²)에 가까워 90~300초 내
완주하지 못함(T63/T64에서 이미 지적된 MAP_SLOTS=729 체인 그로스 성능 이슈).
이는
정확성(cap) 문제가 아니라 성능 문제이며, 이번 FREADALL 수리와는
독립적 — 별도 성능 개선 티켓(버킷 배열 O(1) 재설계) 필요.
다음 단계 제안 (라이브 교체 절차)
/tmp/crownyc-fix를 crowny-deacon-scale-test 등 격리 환경에서 R=300~1500
스케일로 추가 회귀(이번 세션에서 R=300 완료·일치 확인).
- 맵 체인 O(n²) 성능 티켓(T64 후속)을 먼저 또는 병행 해결해 대규모(R≥3000)
E2E 회귀도 시간 내 완주 가능하게 만든다.
- 위 검증 통과 후 오너 승인 하에:
- `cd /Users/ef/CrownyOS/crownyc && cc -O2 -o crownyc crownyc.c -lm
-framework Security -framework CoreFoundation` 로 정본 재빌드
- 재빌드 직후 전 한선씨 서비스(29+ 서비스 공유 바이너리) 스모크 재기동 확인
필수 — 실패 시 즉시 이전 바이너리로 롤백
관련 파일
/Users/ef/CrownyOS/crownyc/crownyc.c (opcode 249 FREADALL, 수정)
/Users/ef/CrownyOS/crownyc/crownyc.한선 (동반 문서, 신규)
/tmp/crownyc-fix (검증용 별도 빌드 — 라이브 아님)
- 재현/검증 스크립트:
/tmp/mapfix/*.한선, /tmp/mapfix/repro*/
- 선행 문서:
2026-07-30-T62-T63-T64-crownyc-VM-프로파일링.md
잔여 이슈
- 맵 체인 O(n²) 성능 재설계(버킷 배열) — 별도 티켓 필요
- R=1500~5000 스케일 E2E(
_PSV파일유니크최신 실사용 경로) 완주 확인은 성능
이슈 해결 후 재시도 필요