Linux 커널 6.18의 Swap Table: 수십 년 묵은 기술부채 청산하기
엔지니어들 사이에서 Swap은 일종의 ‘계륵’ 같은 존재입니다. 서버에서는 성능 예측 불가능성을 이유로 아예 꺼버리는 경우도 많고, 데스크탑에서는 “RAM이 64GB인데 굳이?”라는 반응이 대다수죠. 하지만 리눅스 커널 개발자들에게 Swap은 여전히 필수불가결한 메모리 관리의 최후 방어선입니다.
최근 릴리즈된 리눅스 커널 6.18에서 이 오래된 Swap 서브시스템에 꽤나 흥미로운 변화가 있었습니다. 바로 Swap Table 의 도입입니다. LWN의 기사와 Hacker News의 반응을 바탕으로, 이 변화가 왜 중요한지, 그리고 현업 엔지니어들에게 어떤 의미가 있는지 깊게 파고들어 보겠습니다.
1. 레거시의 고통: XArray와 간접 참조의 늪
사실 그동안 리눅스의 Swap 구현은 꽤나 복잡했습니다. 커널 6.17까지의 Swap 서브시스템을 한 문장으로 요약하자면 “파일 시스템을 흉내 낸 거대한 우회로” 였습니다.
Swap은 본질적으로 익명 메모리(Anonymous Memory)를 디스크로 내리는 작업입니다. 하지만 커널은 이를 관리하기 위해 파일 시스템의 캐시 관리 구조인 address_space와 XArray를 재사용했습니다. 이게 왜 문제였을까요?
- 복잡한 조회 경로: 특정 페이지가 Swap 파일의 어디에 있는지 알기 위해
swapper_spaces라는 배열을 뒤지고, 다시address_space를 거쳐,XArray트리를 타야 했습니다. - 불필요한 추상화: Swap은 파일 시스템처럼 복잡한 메타데이터가 필요 없습니다. 단순히 “이 메모리 페이지가 디스크의 몇 번째 슬롯에 있는가?”만 알면 됩니다. 하지만 범용 구조체를 쓰다 보니 불필요한 오버헤드가 발생했죠.
- Lock Contention: 대규모 시스템에서 Swap이 격렬하게 일어날 때, 이
XArray락(Lock)을 잡기 위한 경합이 성능 저하의 주범이 되곤 했습니다.
2. Kernel 6.18의 해결책: The Swap Table
커널 6.18에서 도입된 Swap Table 은 이 모든 복잡성을 걷어내고 직관적인 ‘배열(Array)’ 구조로 회귀했습니다. 핵심 아이디어는 간단합니다. 이미 존재하는 swap_cluster_info 구조체에 직접적인 매핑 테이블을 붙이는 것입니다.
/* 변경된 swap_cluster_info 구조체 (간소화됨) */
struct swap_cluster_info {
/* ... 기존 필드들 ... */
atomic_long_t __rcu *table; // 직접적인 Lookup 테이블
};
이제 커널은 복잡한 트리 구조를 탈 필요가 없습니다. Swap 엔트리(swp_entry_t)만 있으면, 해당 클러스터의 테이블을 통해 즉시 페이지의 상태를 확인할 수 있습니다.
이 변화가 가져온 효과는 생각보다 큽니다:
- XArray 제거: Swap 관리에서 XArray 의존성을 제거함으로써 메모리 오버헤드와 CPU 사이클을 동시에 줄였습니다.
- Locality 향상: Swap Cluster는 CPU별로 캐싱되어 관리되므로, 데이터 접근의 지역성(Locality)이 크게 향상되었습니다.
- 성능: 벤치마크 결과, 처리량(Throughput)과 빌드 시간 등에서 5~20%의 성능 향상 이 보고되었습니다. 커널 레벨에서 20% 향상은 엄청난 수치입니다.
3. 엔지니어의 시선: “왜 이제서야?”
솔직히 말해서, 저는 이 패치를 보며 “드디어!”라는 생각과 함께 “왜 이제서야?”라는 아쉬움이 동시에 들었습니다.
우리는 종종 소프트웨어 엔지니어링에서 “재사용(Reuse)” 을 미덕으로 여깁니다. 리눅스 커널 초기에 파일 시스템의 address_space를 재사용해 Swap을 구현한 건, 당시로서는 똑똑한 선택이었을 겁니다. 코드를 중복해서 짤 필요가 없었으니까요. 하지만 시간이 지나 하드웨어 스펙이 올라가고 메모리 압박이 심해지면서, 그 ‘재사용된 추상화’가 오히려 독이 되었습니다.
이번 패치는 “과도한 추상화를 걷어내고, 문제의 본질에 맞는 자료구조를 쓰자” 는 엔지니어링의 기본 원칙을 다시 한번 상기시켜 줍니다. 범용 도구(XArray)보다 전용 도구(Direct Table)가 훨씬 효율적인 상황이 분명히 존재합니다.
4. 커뮤니티의 반응: 성능 vs 사용자 경험
Hacker News의 반응은 기술적인 환호보다는, 실제 사용자들이 겪는 ‘고통’에 대한 토로가 주를 이뤘습니다. 이 부분은 CTO나 시니어 엔지니어들이 특히 주목해야 할 포인트입니다.
”시스템이 벽돌이 돼요”
가장 많은 공감을 얻은 의견은 리눅스의 OOM(Out of Memory) 처리 방식에 대한 불만이었습니다.
“메모리가 100%에 도달하면 커널이 실행 코드(Executable Pages)를 날려버리기 시작합니다. 디스크에서 다시 읽어오느라 시스템이 멈춘 것처럼 보이죠. 차라리 빨리 죽여줬으면 좋겠는데 말이죠.”
이건 Swap 자체의 성능 문제라기보다, 커널의 Page Reclaim 정책 문제입니다. Swap Table이 빨라진다고 해서, 시스템이 버벅거리는 현상(Thrashing) 자체가 사라지지는 않습니다. 다만 그 고통의 시간이 조금 짧아질 뿐이죠.
MGLRU (Multi-Gen LRU)
댓글에서는 이에 대한 해결책으로 MGLRU 가 언급되었습니다. 구글이 크롬북을 위해 개발했고 커널 6.1부터 들어온 기능인데, 기존의 LRU 알고리즘보다 훨씬 똑똑하게 “어떤 페이지를 내쫓을지” 결정합니다.
제 경험상으로도, 데스크탑이나 인터랙티브한 서버 환경에서는 Swap 성능 개선(이번 패치)보다 MGLRU 활성화 가 체감 성능 향상에 훨씬 도움이 됩니다. (아직 안 켜보셨다면 /sys/kernel/mm/lru_gen/enabled를 확인해보세요.)
ZRAM/ZSwap의 여전한 인기
디스크 I/O가 병목인 상황에서, 메모리를 압축해서 쓰는 ZRAM/ZSwap 에 대한 선호도는 여전히 높습니다. 특히 SSD 수명을 걱정하거나 랩탑을 쓰는 유저들에게는 Swap file보다 훨씬 매력적인 대안입니다. 이번 Swap Table 개선이 ZSwap 성능에도 간접적인 긍정적 영향을 미칠 것으로 보입니다.
5. 결론: 기본기의 승리
이번 커널 6.18의 Swap Table 도입은 화려한 AI 기능이나 새로운 파일 시스템처럼 눈에 띄는 변화는 아닙니다. 하지만 시스템의 가장 밑바닥에 있는 배관 공사를 다시 하여, 물 흐름을 20%나 개선한 훌륭한 엔지니어링 사례입니다.
요약 및 제언:
- 서버 운영자: 커널 6.18+로 업데이트하면 대규모 빌드나 메모리 집약적 워크로드에서 공짜로 성능 향상을 얻을 수 있습니다.
- 데스크탑 유저: 이 패치만으로 시스템 프리징이 해결되진 않습니다. MGLRU를 켜세요.
- 엔지니어링 교훈: 레거시 코드의 ‘재사용성’이 현재의 ‘성능 병목’이 되고 있지 않은지 점검해 봅시다. 때로는 무식해 보이는 배열(Array) 하나가 복잡한 트리(Tree)보다 낫습니다.
Swap은 죽지 않았습니다. 오히려 더 빠르고 가벼운 모습으로 진화하고 있습니다.