Linux HugePages와 Transparent Huge Pages는 언제 사용해야 할까?
Linux 서버의 메모리가 부족하지 않은데도 애플리케이션 성능이 기대만큼 나오지 않는 경우가 있다.
CPU 사용률도 심각하지 않고 디스크 I/O에도 특별한 문제가 없는데, 데이터베이스나 대용량 메모리를 사용하는 애플리케이션의 응답 시간이 일정하지 않게 흔들리기도 한다.
이럴 때 확인해야 할 영역 중 하나가 메모리 페이지(Page) 관리 방식이다.
Linux는 일반적으로 메모리를 작은 페이지 단위로 관리한다. 하지만 서버가 수십 GB, 수백 GB의 메모리를 사용하기 시작하면 페이지 수 자체가 크게 증가하고, 이를 관리하기 위한 CPU 작업도 무시하기 어려워진다.
이 문제를 줄이기 위해 Linux에는 HugePages와 **Transparent Huge Pages(THP)**라는 기능이 존재한다.
두 기능 모두 더 큰 메모리 페이지를 사용한다는 점에서는 비슷하지만 동작 방식과 운영 목적은 상당히 다르다.
특히 데이터베이스 서버에서는 THP를 무조건 활성화하는 것이 오히려 성능 변동의 원인이 될 수도 있다.
메모리가 충분한데도 HugePages가 필요한 이유
Linux의 일반적인 메모리 페이지 크기는 대부분의 x86-64 환경에서 4KB다.
예를 들어 하나의 프로세스가 32GB의 메모리를 사용한다고 생각해보자.
4KB 페이지를 기준으로 단순 계산하면 약 800만 개가 넘는 페이지가 필요하다.
프로세스가 가상 메모리 주소에 접근하면 CPU와 운영체제는 해당 주소가 실제 물리 메모리의 어느 위치에 존재하는지 알아야 한다.
이 매핑 정보를 관리하는 구조가 Page Table이다.
문제는 사용하는 메모리가 커질수록 관리해야 하는 페이지와 Page Table 엔트리 역시 증가한다는 것이다.
CPU는 매번 Page Table 전체를 탐색하지 않기 위해 **TLB(Translation Lookaside Buffer)**라는 캐시를 사용한다.
TLB에는 최근 사용한 가상 주소와 물리 주소의 매핑 정보가 저장된다.
하지만 TLB 역시 CPU 내부의 제한된 자원이다.
애플리케이션이 매우 넓은 메모리 영역에 반복적으로 접근하면 필요한 주소 변환 정보를 모두 TLB에 보관할 수 없게 되고 TLB Miss가 증가한다.
결국 CPU가 Page Table을 추가로 탐색해야 하므로 메모리는 충분한데 CPU가 주소 변환 작업에 더 많은 시간을 사용하는 상황이 발생할 수 있다.
HugePages는 바로 이 문제를 줄이기 위한 방법 중 하나다.
HugePages는 어떻게 동작하는가
HugePages는 기본 4KB보다 훨씬 큰 페이지를 사용하는 방식이다.
Linux 환경에서는 대표적으로 2MB Huge Page를 사용할 수 있으며 CPU와 시스템 구성에 따라 더 큰 페이지 크기를 지원하기도 한다.
예를 들어 1GB 메모리를 매핑한다고 가정해보자.
4KB 페이지를 사용하면 약 262,144개의 페이지가 필요하다.
반면 2MB Huge Page를 사용하면 필요한 페이지는 약 512개로 줄어든다.
페이지 수가 크게 감소하면서 Page Table의 규모도 줄어들고 하나의 TLB 엔트리가 담당할 수 있는 메모리 범위도 훨씬 커진다.
즉,
일반 페이지
프로세스 → 많은 Page Table 엔트리 → 많은 TLB 엔트리 필요 → TLB Miss 증가 가능
HugePages
프로세스 → 적은 Page Table 엔트리 → 넓은 메모리 범위 매핑 → TLB 효율 향상
이라는 구조가 된다.
따라서 대규모 메모리를 지속적으로 사용하는 데이터베이스나 JVM 같은 환경에서는 HugePages가 성능 안정성에 영향을 줄 수 있다.
중요한 것은 HugePages가 메모리를 더 빠른 메모리로 바꾸는 기능은 아니라는 점이다.
핵심 목적은 메모리 주소 변환 과정에서 발생하는 관리 비용을 줄이는 것이다.
HugePages와 THP는 같은 기능이 아니다
운영 환경에서 가장 많이 혼동하는 부분이다.
Linux에는 크게 두 가지 방식이 있다.
HugePages
관리자가 Huge Page용 메모리 영역을 명시적으로 확보하고 애플리케이션이 이를 사용하도록 구성한다.
Transparent Huge Pages
커널이 일반 메모리 페이지를 자동으로 큰 페이지로 합치거나 Huge Page 형태로 할당하려고 시도한다.
THP의 핵심은 이름 그대로 Transparent, 즉 애플리케이션이 특별히 의식하지 않아도 커널이 자동으로 처리한다는 것이다.
확인은 다음과 같이 할 수 있다.
cat /sys/kernel/mm/transparent_hugepage/enabled
환경에 따라 다음과 비슷한 결과가 나타난다.
always [madvise] never
대괄호로 표시된 값이 현재 설정이다.
always는 가능한 경우 적극적으로 THP를 사용한다는 의미이고, madvise는 애플리케이션이 필요성을 알린 메모리 영역을 중심으로 적용하는 방식이다.
never는 THP를 사용하지 않는 설정이다.
여기서 중요한 점은 THP가 활성화되어 있다고 해서 모든 메모리가 즉시 Huge Page로 바뀌는 것은 아니라는 것이다.
커널은 메모리 상태와 할당 조건 등을 고려하면서 Huge Page를 구성한다.
바로 이 자동화 과정이 특정 서버에서는 문제가 될 수 있다.
THP가 오히려 성능 문제를 만드는 이유
Huge Page는 큰 연속 메모리 영역이 필요하다.
서버를 오래 운영하면 메모리에는 다양한 크기의 페이지가 할당되고 반환되는 과정이 반복된다.
결과적으로 충분한 전체 메모리가 남아 있더라도 물리적으로 연속된 큰 영역을 확보하기 어려워질 수 있다.
이를 메모리 단편화(Fragmentation) 문제라고 한다.
THP가 큰 페이지를 만들려고 할 때 커널은 필요에 따라 메모리 페이지를 이동하거나 정리하는 Memory Compaction 작업을 수행할 수 있다.
이 과정에서 CPU 사용량이 증가하거나 메모리 할당 지연이 발생할 수 있다.
특히 데이터베이스처럼 응답 시간의 일관성이 중요한 시스템에서는 평균 성능보다 순간적인 Latency Spike가 더 큰 문제가 될 수 있다.
평소 쿼리가 5ms에 처리되는데 특정 순간마다 100ms 이상으로 튀는 현상이 반복된다면 단순 평균 CPU 사용률만 보고 원인을 찾기 어려울 수 있다.
THP 자체가 모든 지연의 원인이라는 뜻은 아니다.
다만 대용량 메모리 서버에서 원인을 알 수 없는 주기적인 지연이 발생한다면 THP와 메모리 Compaction 활동을 함께 확인할 필요가 있다.
실제 서버에서는 어떤 증상이 나타나는가
HugePages 또는 THP 관련 문제는 단순히 “메모리 부족” 형태로 나타나지 않는 경우가 많다.
대표적으로 다음과 같은 현상이 나타날 수 있다.
- 데이터베이스 쿼리 응답 시간이 순간적으로 증가
- 애플리케이션 Latency가 일정하지 않음
- CPU 사용률은 높지 않은데 처리량이 기대보다 낮음
- 메모리가 충분한데 시스템 반응이 순간적으로 느려짐
- 대용량 메모리 애플리케이션에서 TLB Miss 증가
- 메모리 Compaction 작업 증가
이 때문에 일반적인 모니터링 지표만 확인하면 원인을 찾기 어렵다.
CPU가 40%, 메모리가 60% 사용 중이라고 해서 메모리 관리 비용까지 정상이라는 의미는 아니다.
Linux 성능 분석에서는 사용량뿐 아니라 커널이 해당 자원을 어떻게 관리하고 있는지까지 확인해야 한다.
HugePages 상태는 어떻게 분석해야 할까
가장 먼저 /proc/meminfo를 확인할 수 있다.
grep -i huge /proc/meminfo
예를 들어 다음과 같은 항목을 볼 수 있다.
AnonHugePages: 1048576 kB
HugePages_Total: 512
HugePages_Free: 128
HugePages_Rsvd: 64
Hugepagesize: 2048 kB
각 항목은 의미가 다르다.
HugePages_Total은 시스템에 설정된 Huge Page 전체 개수다.
HugePages_Free는 현재 사용되지 않는 Huge Page 수다.
HugePages_Rsvd는 프로세스가 사용하기 위해 예약한 페이지를 의미한다.
Hugepagesize는 Huge Page 한 개의 크기다.
그리고 AnonHugePages는 익명 메모리 영역에서 THP가 사용되고 있는 규모를 파악하는 데 참고할 수 있다.
여기서 단순히 숫자가 크다고 정상 또는 비정상으로 판단하면 안 된다.
예를 들어 HugePages를 명시적으로 구성하지 않은 서버에서 AnonHugePages가 크게 나타난다면 THP가 상당한 메모리 영역에 적용되고 있을 가능성을 살펴볼 수 있다.
반대로 데이터베이스에 HugePages를 설정했는데 HugePages_Total이 예상보다 작거나 실제 사용량이 거의 없다면 애플리케이션이 해당 영역을 제대로 사용하고 있는지 확인해야 한다.
THP와 메모리 Compaction은 함께 봐야 한다
THP 문제를 분석할 때는 /proc/vmstat도 유용하다.
grep -E 'thp|compact' /proc/vmstat
이 명령은 THP 관련 동작과 메모리 Compaction 통계를 확인하기 위해 사용한다.
시스템과 커널 버전에 따라 표시되는 항목은 다를 수 있지만 thp_ 또는 compact_로 시작하는 여러 카운터를 확인할 수 있다.
여기서 중요한 것은 한 번 출력한 절대값만 보는 것이 아니다.
서버가 수개월 동안 운영됐다면 값이 큰 것은 자연스러울 수 있다.
따라서 일정 시간 간격으로 두 번 확인해 증가량을 비교하는 것이 좋다.
grep -E 'thp|compact' /proc/vmstat
sleep 10
grep -E 'thp|compact' /proc/vmstat
애플리케이션 지연이 발생하는 시간대에 Compaction 관련 카운터가 빠르게 증가한다면 메모리 관리 작업과 지연 사이의 상관관계를 추가로 분석할 근거가 된다.
단, 이것만으로 원인이 THP라고 단정해서는 안 된다.
CPU 스케줄링, 디스크 I/O, NUMA, Swap, GC 등 다른 지표와 시간대를 맞춰 비교해야 한다.
TLB 문제는 어떻게 확인할까
TLB Miss와 같은 CPU 하드웨어 이벤트를 확인하려면 perf를 활용할 수 있다.
환경에 따라 지원되는 이벤트 이름이 다르기 때문에 먼저 확인한다.
perf list | grep -i tlb
그다음 지원되는 이벤트를 이용해 특정 프로세스나 명령의 TLB 관련 동작을 측정할 수 있다.
예를 들어 환경에서 해당 이벤트가 제공된다면 다음과 같은 방식이다.
perf stat -e dTLB-loads,dTLB-load-misses <command>
중요한 것은 단순히 dTLB-load-misses 숫자가 존재한다는 사실이 아니다.
전체 메모리 접근 패턴과 비교해 Miss 비율이 어느 정도인지, 부하가 증가할 때 함께 증가하는지, HugePages 적용 전후에 차이가 있는지를 비교해야 한다.
운영 서버에서는 perf 측정 자체가 시스템에 영향을 줄 수 있으므로 측정 범위와 시간을 제한하는 것이 좋다.
그렇다면 HugePages는 언제 사용하는 것이 좋은가
HugePages는 모든 Linux 서버에 일괄 적용하는 튜닝 옵션이 아니다.
특히 다음과 같은 환경에서 검토 가치가 높다.
첫째, 대용량 메모리를 지속적으로 사용하는 데이터베이스 서버다.
Oracle Database와 같은 대규모 데이터베이스 환경에서는 명시적 HugePages 구성을 사용하는 사례가 많다.
둘째, 큰 Heap을 사용하는 JVM 환경이다.
JVM 역시 수십 GB 이상의 메모리를 사용하는 경우 페이지 관리 비용과 TLB 효율을 검토할 가치가 있다.
다만 JVM 버전과 GC 방식에 따라 메모리 동작이 달라지므로 HugePages만 독립적으로 판단해서는 안 된다.
셋째, 메모리 접근이 매우 많은 고성능 애플리케이션이다.
메모리 집약적인 워크로드에서는 Page Table과 TLB 효율 개선이 실제 성능에 영향을 줄 가능성이 있다.
반대로 수 GB 정도의 메모리만 사용하는 일반적인 웹 서버라면 HugePages를 복잡하게 구성해 얻는 이점이 크지 않을 수도 있다.
튜닝은 기능의 존재 여부가 아니라 현재 병목이 어디에 있는지를 기준으로 판단해야 한다.
THP는 무조건 꺼야 할까
그렇지는 않다.
과거에는 데이터베이스 운영 가이드에서 THP 비활성화를 권장하는 경우가 많았고, 실제 운영 환경에서도 지연 문제 때문에 비활성화하는 사례가 존재한다.
하지만 최신 Linux 커널과 애플리케이션 환경에서는 THP 동작 방식과 기본 설정이 달라질 수 있다.
따라서 인터넷에서 본 설정을 그대로 적용해
THP = 무조건 OFF
라고 판단하는 것은 적절하지 않다.
먼저 현재 설정을 확인하고 애플리케이션 특성과 벤더 권장 사항을 살펴본 뒤 실제 부하에서 성능을 비교해야 한다.
특히 always, madvise, never의 차이를 이해하고 워크로드에 맞는 방식을 선택하는 것이 중요하다.
운영 서버에서 설정을 변경할 때는 평균 처리량뿐 아니라 P95, P99 같은 지연 시간 분포도 함께 비교하는 것이 좋다.
평균 응답 시간은 거의 같더라도 특정 요청의 지연이 크게 감소한다면 운영 관점에서는 중요한 차이가 될 수 있기 때문이다.
HugePages 설정에서 가장 위험한 실수
HugePages는 일반 메모리와 달리 관리자가 미리 확보하는 방식으로 사용할 수 있다.
예를 들어 다음 커널 파라미터를 볼 수 있다.
sysctl vm.nr_hugepages
설정된 페이지 수와 페이지 크기를 곱하면 HugePages용으로 확보된 메모리 규모를 계산할 수 있다.
2MB 페이지를 10,000개 확보한다면 약 20GB의 메모리가 HugePages 용도로 사용된다.
문제는 필요 이상으로 많은 HugePages를 예약하는 경우다.
서버에 64GB RAM이 있다고 해서 50GB를 무작정 HugePages로 확보하면 일반 프로세스와 운영체제가 사용할 수 있는 메모리 영역이 줄어든다.
결과적으로 HugePages를 이용한 성능 최적화가 오히려 일반 메모리 부족이나 Swap 사용 증가라는 새로운 문제를 만들 수 있다.
따라서 HugePages의 개수는 애플리케이션이 실제로 필요로 하는 메모리 크기를 기준으로 계산해야 한다.
설정 후에는 반드시
grep -i huge /proc/meminfo
를 통해 실제 예약량과 사용량을 다시 확인해야 한다.
운영 서버에서는 이렇게 접근하는 것이 안전하다
HugePages 튜닝은 “활성화하면 빨라진다”는 방식으로 접근해서는 안 된다.
먼저 현재 서버에서 실제 문제가 존재하는지 확인해야 한다.
메모리 사용량, Page Table 규모, THP 사용량, Compaction 활동, TLB 관련 지표를 확인한다.
그다음 애플리케이션의 특성을 파악한다.
대규모 데이터베이스인지, JVM인지, 일반 웹 애플리케이션인지에 따라 판단 기준이 달라진다.
변경이 필요하다면 운영 서버에서 바로 적용하기보다 동일한 워크로드를 재현할 수 있는 환경에서 비교하는 것이 좋다.
비교할 때도 단순 평균 CPU 사용률만 봐서는 안 된다.
처리량, 평균 응답 시간, P95/P99 Latency, CPU 사용량, TLB Miss, Compaction 활동 등을 함께 비교해야 한다.
그래야 HugePages 적용으로 실제 성능이 좋아진 것인지 단순히 다른 병목으로 이동한 것인지 판단할 수 있다.
정리
HugePages와 Transparent Huge Pages는 모두 Linux의 메모리 페이지 관리 비용을 줄이기 위한 기술이지만 운영 방식은 다르다.
HugePages는 관리자가 큰 페이지용 메모리를 명시적으로 확보하고 애플리케이션이 이를 사용하도록 구성하는 방식이다.
THP는 커널이 자동으로 큰 페이지를 활용하려고 시도한다.
큰 페이지를 사용하면 Page Table 엔트리 수를 줄이고 TLB가 더 넓은 메모리 영역을 담당할 수 있기 때문에 대용량 메모리 워크로드에서 이점을 얻을 가능성이 있다.
하지만 THP의 자동 페이지 구성 과정에서는 메모리 단편화와 Compaction이 개입할 수 있고, 특정 워크로드에서는 이것이 순간적인 Latency 증가로 이어질 수 있다.
따라서 핵심은 HugePages를 켜느냐 끄느냐가 아니다.
현재 서버에서 페이지 관리 비용이 실제 병목인지 확인하고, 애플리케이션의 메모리 사용 특성에 맞는 방식을 선택하는 것이 중요하다.
Linux 성능 튜닝에서 가장 위험한 방법은 유명한 설정값을 그대로 복사하는 것이다.
좋은 튜닝은 설정 변경에서 시작하지 않는다.
/proc/meminfo, /proc/vmstat, perf 같은 지표를 통해 현재 시스템이 메모리를 어떻게 관리하고 있는지 확인하고, 변경 전후의 결과를 측정하는 것에서 시작한다.
HugePages 역시 같은 원칙으로 접근해야 한다.




댓글 0
첫 댓글을 남겨보세요.