Rust로 구현된 초경량 메모리 할당기 smalloc, 성능은?
Rust로 구현된 smalloc은 glibc, libmalloc 등 기존 할당기를 대체하는 것을 목표로 함
351줄의 간결한 코드(Code)로 구현되어, 다른 할당기 대비 유지보수성(Maintainability)을 강조함
벤치마크(Benchmark) 결과, 기존 할당기 대비 우수한 성능을 보이며, 특히 멀티스레딩 환경에서 강점
2GiB 이상의 단일 할당 불가, 인스턴스(Instance) 중복 생성 불가 등 제한 사항(Limitations) 존재
smalloc의 핵심 설계: 가상 메모리 공간 활용
smalloc은 가상 메모리 주소 공간을 광범위하게 예약하여 메모리 할당을 효율적으로 처리한다. 가상 메모리 주소 공간(Virtual Memory Address Space)은 거의 무제한의 자원이므로, 이를 활용하여 메모리 할당 및 해제 연산의 복잡성을 줄인다. 특히, 포인터 자체에 정보를 인코딩하여 해제 시 추가적인 정보 검색을 최소화하는 방식을 사용한다. 이러한 설계는 코드의 간결성을 높이고, 일관된 성능을 보장하는 데 기여한다.
성능 비교: 기존 할당기와의 경쟁
벤치마크 결과에 따르면, smalloc은 jemalloc, snmalloc, mimalloc, rpmalloc 등 다른 메모리 할당기보다 우수한 성능을 보이는 경우가 있다. 특히, 멀티스레딩 환경에서 smalloc은 경쟁 할당기 대비 최대 97%의 성능 향상을 기록했다. 이러한 성능은 smalloc의 간결한 코드 구조와 효율적인 메모리 관리 방식에서 기인하며, 시스템 자원 활용도를 극대화한다.
구현 방식: 슬롯, 슬랩, 그리고 자유 리스트
smalloc은 메모리를 슬롯(Slot), 슬랩(Slab), 그리고 자유 리스트(Free List)로 구성하여 관리한다. 각 슬랩은 고정된 크기의 슬롯 배열을 포함하며, 각 슬롯은 특정 크기의 메모리 할당을 담당한다. 자유 리스트(Free List)는 사용 가능한 슬롯을 추적하며, malloc() 호출 시 자유 리스트에서 슬롯을 가져와 사용하고, free() 호출 시 슬롯을 다시 자유 리스트에 추가한다. 이러한 구조는 메모리 할당 및 해제 연산을 빠르고 효율적으로 수행할 수 있도록 돕는다.
제한 사항: 2GiB 할당 제약 및 인스턴스 제한
smalloc은 몇 가지 제한 사항을 가지고 있다. 첫째, 단일 malloc() 호출로 2GiB 이상의 메모리를 할당할 수 없다. 둘째, 단일 프로세스 내에서 여러 smalloc 인스턴스를 생성할 수 없다. 이러한 제한 사항은 smalloc의 설계상 발생하는 것으로, 대규모 메모리 할당이 필요한 경우나, 여러 메모리 할당기를 사용하는 복잡한 환경에서는 고려해야 할 사항이다. 하지만, 일관된 성능과 예측 가능한 오류 처리를 위해 이러한 트레이드오프(Trade-offs)를 선택했다.
멀티스레딩 환경에서의 안전성: flh 업데이트
smalloc은 멀티스레딩 환경에서 안전하게 동작하기 위해 flh(free-list-head) 업데이트에 원자적 비교-교환(Atomic Compare-and-Exchange) 연산을 사용한다. 이 기법은 여러 스레드가 동시에 자유 리스트를 수정하려는 경우, 데이터 경쟁(Data Race)을 방지하고, 일관성을 유지한다. 또한, ABA 문제를 해결하기 위해 flh에 카운터를 추가하여, 동시성 문제를 더욱 안전하게 처리한다.