Skip to content

feat(ai-file): promote the MuPDF store drop to stg/prod

변재혁 requested to merge feature/DOP-AI_성능테스트 into develop

dev 부하테스트로 검증 완료 → 배포 프로파일 전체로 승격한다.

검증 결과 (dev, PDF 17~18MB · HWP · PPTX 혼합, /read 부하)

요청당 RSS 증가: 1차 튜닝 없음 2.3220 MB/req → ~989MB 에서 OOMKill 3차 +MALLOC_MMAP_THRESHOLD_ 0.1760 MB/req → 1015MB 플래토 → OOMKill B-2 +store 수정 0.0295 MB/req → ~280MB 대역 (1차 대비 79배)

B-2 정상 상태: RSS 275.6~287.8MB(53샘플, 폭 12.2MB), 창 내부 추세 -4.99MB(감소). cg_anon 최대 238MB = limit 1024MB 의 23.2%, 여유 786MB. cg_file 0.00MB.

수정이 실제로 도는 것은 B-1 에서 증명됐다: 회수 프로브의 after_trim_mb 와 after_store_shrink_mb 가 소수점까지 일치(231.76==231.76 등) → reclaimed_store_mb=0.00. 프로브가 도착했을 때 store 가 이미 비어 있다.

두 수정은 세트다

MALLOC_MMAP_THRESHOLD_=131072 (Deployment env) 가 없으면 store 를 비워도 메모리가 glibc free list 에 반납만 되고 OS 로 돌아가지 않는다(store_shrink 는 munmap 을 하지 않는다). 그 env 가 큰 블록(디코드 이미지)을 mmap 으로 보내놨기 때문에 free 시 곧바로 반환된다. stg/prod Deployment 에 MALLOC_MMAP_THRESHOLD_=131072 를 함께 넣어야 효과가 난다. (뒤 언더스코어 필수 — 빠지면 glibc 가 조용히 무시한다.)

부수 효과로 glibc 파편화도 줄었다: reclaimed_trim_mb 54.9 → 21.3MB. store 할당·해제 자체가 파편화를 만들고 있었다.

배치

모델 기본값은 False(롤백 바닥)로 두고 k8s 로 뜨는 프로파일(dev/stg/prod)에서 명시적으로 켠다 — agent_knowledge_pdf_page_concurrency 와 같은 패턴. local 은 부하가 없어 미적용. 되돌릴 때는 각 yml 의 false 또는 env AI_FILE_PDF_STORE_SHRINK_AFTER_RENDER=false.

추가 가드 테스트

pdf_page_window_size 를 올릴 때 AiFileRuntime 기동 검증식 (pdf_artifact_cache_max_bytes >= window * image_max_base64_size_bytes*3/4)을 어기면 파드가 기동 자체를 못 한다. 현재 값(64MB / 3.75MB)에서 상한은 17페이지다. 배포 프로파일 전체가 이 식을 만족하는지 확인하는 테스트를 추가해, 창 크기를 올릴 때 캐시 상한도 함께 올리도록 CI 에서 잡는다.

전체 스위트 473 passed.

Co-Authored-By: Claude Opus 5 (1M context) noreply@anthropic.com

Merge request reports