파이썬 서버가 빈 메모리를 돌려주게 하는 glibc 설정 세 가지
MALLOC_ARENA_MAX로 arena 수를 줄이고, mmap·trim 기준을 고정하고, 큰 데이터를 내린 뒤와 주기적으로 malloc_trim을 부른다.
파이썬 객체는 다 풀렸는데 서버의 RSS가 줄지 않는다. glibc 할당자가 빈 힙을 OS에 돌려주지 않고 들고 있는 것이다. 코드를 크게 고치지 않고 배포 설정만으로 상당 부분 줄일 수 있다.
1. arena 수 줄이기. glibc는 스레드가 많으면 arena(할당 구역)를 여러 개 만든다. 스레드 풀이나 sync_to_async를 쓰는 서버는 빈 공간이 여러 arena에 흩어져 돌려주기 어렵다. MALLOC_ARENA_MAX=2로 줄인다.
2. mmap·trim 기준 고정. glibc는 큰 블록을 free하고 나면 mmap 기준을 스스로 올린다. 그 뒤로는 큰 할당도 힙에 남아 돌려주기 어렵다. 기준을 고정해 큰 할당은 계속 mmap으로 가게 한다.
3. 주기적 trim. 큰 데이터를 내린 뒤와 일정 주기(예: 5분)로 malloc_trim(0)을 부른다. 비용이 있으니 간격을 두되, 간격 안에 불렸다면 건너뛰지 말고 간격이 끝날 때로 미룬다.
services:
api:
environment:
MALLOC_ARENA_MAX: "2"
GLIBC_TUNABLES: "glibc.malloc.mmap_threshold=131072:glibc.malloc.trim_threshold=131072"
import ctypes
libc = ctypes.CDLL("libc.so.6")
libc.malloc_trim(0) # 큰 데이터를 내린 뒤, 그리고 주기적으로
세 가지 모두 glibc 기반 이미지(debian, slim)에만 해당한다. musl을 쓰는 alpine 이미지에는 이 설정이 없다.