백엔드
Go embed: 최소 변경으로 불필요한 메모리 사용 줄이기
두줄요약
GeoIP DB를 embed.FS.ReadFile로 읽으며 발생한 전체 DB heap 복사 원인을 분석했습니다.직접 []byte embed 방식으로 배포 구조를 유지하면서 보유 heap을 줄였습니다.
문제 상황
- Pyroscope inuse_space에서 GeoIP DB 로딩 경로인
embed.FS.ReadFile의 높은 보유 heap 비중 - 요청별 누적이 아닌 프로세스 초기화 시 공통으로 발생하는 DB 메모리 비용
원인 분석
- 바이너리에 포함된 GeoLite2 City DB를
ReadFile이 새로운[]byte로 전체 복사 geoip2.FromBytes가 복사본을 계속 참조하여 DB 크기만큼의 heap 유지
해결 방법
- 별도 파일을
mmap으로 여는 방식과[]byte직접 embed 방식 비교 //go:embed대상 변수를[]byte로 선언하고geoip2.FromBytes에 직접 전달- 공유 바이트 슬라이스 수정 금지 계약 명시와 기존 reader 반환·종료 흐름 유지
트레이드오프
- mmap의 heap 복사 제거 효과와 별도 MMDB 파일·경로·배포 규칙 운영 비용
- 직접 embed의 단일 바이너리 배포 유지와 공유 바이트 불변성 관리 필요
- 측정 결과를 근거로 운영 부담이 작은 직접 embed 방식 선택
