Last Updated on 2월 5, 2023 by Jade(정현호)
Contents
What is Page?
Page 는 메모리 관리의 작은 데이터 단위 이며 ,page 는 가상 메모리를 특정 사이즈(normal 기준 4k) 로 분할한 단위 입니다
리눅스 x86 에서 page 크기를 normal 4KB , 2MB, 설정시 1GB 를 지원 하고 있습니다
보편적으로 리눅스(x86) 에서는 Normal Size 인 4KB 인 페이지를 사용하여 데몬과 어플리케이션이 사용되고 있습니다.
위에서 언급 한 것처럼 4KB 외 더 큰 사이즈의 페이지가 지원 되고 큰 사이즈의 페이즈를 large page 나 huge page 라고 합니다.
이런 large page 를 사용 할 수 있는 어플리케이션이나 데몬에서 이런 큰 사이즈의 페이지를 사용할 수 있는 기능이 지원이 되어야 사용이 가능 합니다.
그래서 보통의 데몬이나 어플리케이션은 4k normal page 를 사용하게 됩니다.
2MB 사이즈의 Large Page 를 사용하는 어플리케이션에는 대표적으로 Database 제품중에 Oracle Database , PHP-CGI 인 PHP-FPM 도 Large Page를 사용 할 수 있습니다(그외 다수)
Database 는 file 에 저장된 블럭을 Buffer Pool 메모리 공간에 Cache 하여 사용하게 되고 Database 에는 수많은 데이터가 저장되어 있습니다.
수 gb 부터 ~ 수백 GB(그 이상도) 까지 Buffer Cache 를 설정 하여 사용 하게 되고 그래서 Database 는 항상 많은 메모리를 사용 하게 됩니다
리눅스 플렛폼에서의 Orace Database를 사용할 때 LargePage 사용은 벤더사의 권장 사항이기도 합니다.
Large Page 를 사용 할 수 있는 Database 에는 Oracle 외 MySQL 도 사용 할 수 있습니다.
InnoDB Buffer Pool 영역에 대해서 사용 할 수 있으며 default는 OS나 MySQL 에서 설정되어 있지 않기 때문에 Normal Page 를 사용하는것이 default 설정입니다.
HugePage 사용시 장점
HugePage(LargePage) 를 활용하게 되면 아래와 같은 장점이 있게 됩니다.
1. 적은 수의 페이지
기본 normal page 는 4KB 이며 HugePage는 2MB 또는 1GB 로, 2MB 기준으로 이는 Hugepage가 512배(512 times) 적은 페이지의 처리를 의미 합니다.
[참고] 포스팅에서는 Hugepage 크기의 기준을 2MB 로 계산이나 테스트 하였습니다.
2. Reduced Page Table Walking
Hugepage 가 normal page 보다 더 큰 영속 가상주소 범위를 다루기 때문에(covers greater), TLB entry 당 TLB Hit Ratio 가 일반 페이지에 비해 높으며 이는 가상 주소에서 물리적 주소를 얻기 위해 페이지를 탐석 하는 횟수를 줄어 듭니다.
TLB는 Translation Lookaside Buffer 약자로 가상 메모리 주소를 물리적인 주소로 변환하는 속도를 높이기 위해 사용되는 캐시로 TLB는 최근에 일어난 가상 메모리 주소와 물리 주소의 변환 테이블을 저장하기 때문에 일종의 주소 변환 캐시라고 할 수 있습니다.
TLB는 CPU와 CPU 캐시 사이, CPU 캐시와 메인 메모리 사이 등 여러가지 다른 레벨의 캐시들 사이에서 주소를 변환하는데 사용할 수 있습니다.
그래서 프로그램에 의한 메모리 접근은 최소 2번의 접근이 필요 하게 됩니다.
2-1) 실제 주소를 얻기 위한 메모리 주소 접근
=> cpu로 부터 생성된 가상주소를 메모리에 있는 page table 을 통해 실제주소(physical address) 로 변한
2-2) 데이터를 얻기 위한 실제적인 접근
* TLB(Translation Lookaside Buffer)란 page table 에 대한 cache 라고 볼수 있습니다.
3. Faster overall memory performance
위에서 설명한 내용과 같이 2번의 접근 과정에 대해서 page가 적고 page table내에 entry가 적기 때문에 page tabe에 대한 access bottleneck을 줄이거나 피할수 있습니다.
On virtual memory systems each memory operation is actually two abstract memory operations.
Since there are fewer pages to work on, the possible bottleneck on page table access is clearly avoided.
4. Decreased page table overhead
page table entry 당 소요되는 메모리의 량은 64bytes보다 크다고 하며 , 50GB의 물리 메모리를 관리하기 위한 pagetable 에서 사용되는 메모리 량은 대략 800MB 정도 소요 됩니다.
(50GB / 4096(normal page size) * 64(bytes) = 약 800MB
또한 50GB의 메모리를 관리하기 위해서는 1,300 만개의 page(13,107,200 = 50 * 1024* 1024 KB / 4 KB)가 유지되어야 하고 Hugepage 사용할 경우 25,600 개로
page가 줄어들고 이에 따라 overhead의 감소와 메모리도 절약 됩니다.
5. Less Memory Usage
Linux kernel will use less memory to create pagetables to maintain virtual to physical mappings for SGA address range, in comparison to regular size pages.
This makes more memory to be available for process-private computations or PGA usage.
리눅스 Kernel 은 Database 에서 사용되는 Buffer(ie. oracle에서는 SGA) 의 주소에 대한 가상 과 물리적 매핑(physical mappings) 를 유지하기 위한 page table를 만드는데 더 적은 메모리를 사용 합니다.
6. No Swapping
4k normal page와 다르게 Hugepage는 swap 되지 않습니다 따라서 page-in/out의 성능 overhead 및 swap io부하를 예방할수 있습니다.
7. No 'kswapd' Operations
kswapd will get very busy if there is a very large area to be paged (i.e. 13 million page table entries for 50GB memory) and
will use an incredible amount of CPU resource.
When HugePages are used, kswapd is not involved in managing them.
* 참고) 포스트 환경 : OS - Centos Linux 7.8 / MySQL 5.7.31 입니다.
OS - Large Page 설정
OS 에서 Large Page 설정에 대해서 확인 해보도록 하겠습니다.
Large Page 설정 시 유의사항
Large Page는 사용할 만큼의 페이지수를 사전에 설정(커널 파라미터) 하고 사용하는 방식 입니다.
설정하게 되면 2MB 단위의 페이지가 할당하게 되고, Large Page를 사용 불가한 보통의 데몬이나 어플리케이션은 해당 공간은 사용하지 못하게 됩니다.
그러므로 DB 외에 다른 web/was나 ETL 등의 메모리를 별도로 많이 사용하는 어플리케이션과 같이 같이 사용하는 환경이라면 Large Page 설정에 유의 해야 합니다.
DB를 단독으로 사용 하는 환경이라도 위에서 설명한 것처럼 large page를 설정한 만큼은 사용 불가함으로 DB에서 사용 할 만큼만 계산하여 설정해야 합니다
vm.nr_hugepages 설정
먼저 현재 메모리 hugepage 상태를 확인 합니다.
[root]# cat /proc/meminfo | grep -i huge
AnonHugePages: 0 kB
HugePages_Total: 0
HugePages_Free: 0
HugePages_Rsvd: 0
HugePages_Surp: 0
Hugepagesize: 2048 kB
-> 현재는 hugepage 로 설정 된 내역이 없음
large page 의 커널 파라미터는 vm.nr_hugepages 입니다.
Oracle의 경우 SGA 사이즈 , MySQL 은 Innodb Buffer Pool 사이즈 만큼에서 +@ 계산을 해서 설정 합니다.
예를 들어 innodb_buffer_pool_size = 35G 으로 설정되어 있다면 (35G+10%여유분) / 2MB 으로 계산해서 설정하면 됩니다.
MySQL 내에서는 쿼리를 통해서 조회하면 아래와 같습니다.
mysql> select (@@innodb_buffer_pool_size+(@@innodb_buffer_pool_size*0.1))/1024/1024/2 calc; +---------------------+ | calc | +---------------------+ | 19712.0000000000000 | +---------------------+
mysql --login-path 관련 해서는 아래 포스팅을 참조하시면 됩니다.

위의 계산 대로 19712 정도를 현재 시스템에서는 설정 하도록 하겠습니다.
[root]# vi /etc/sysctl.conf
## 아래 내용 추가
vm.nr_hugepages=19712
vm.swappiness=1
추가로 swappiness 가 높게 설정되어 있다면 수치를 낮춰서 설정을 합니다.
vm.hugetlb_shm_group 설정
hugetable 를 사용할 수 있는 OS 그룹을 지정 하는 커널 파라미터 입니다.
[root]# cat /etc/group | grep mysql
mysql:x:1002:
포스팅에서는 mysql OS 그룹의 gid 가 1002 입니다. 확인 되는 1002 gid 값을 커널 파라미터에 설정을 하면 됩니다.
[root]# vi /etc/sysctl.conf
## 내용 추가
vm.hugetlb_shm_group=1002
memlock 내용 추가
리눅스나 유닉스에서는 OS 계정별로 각 자원의 사용량을 컨트롤 하는 ulimit 값이 있습니다.
필요에 따라서 적절히 수치를 증가 및 조정이 필요 하게 됩니다.
Large Page 사용시 memlock 수치의 변경이 필요하기에 limit.conf 에 아래와 같이 내용을 추가 하도록 하겠습니다.
[root]# vi /etc/security/limits.conf
mysql soft memlock unlimited
mysql hard memlock unlimited
-> 2개 라인 내용 추가
Transparent Huge Pages 비활성화
Transparent Huge Pages (THP) 기능을 비활성화 합니다
THP에 관해서는 이전에 포스팅 된 내역이 있습니다.
아래 링크 글을 참조하여 서비스 등록하여 비활성화 하면 됩니다.

MySQL 설정 변경 및 중지
Large Page 관련하여 기능 사용에 대한 MySQL 설정을 변경 하도록 하겠습니다.
my.cnf 에 를 수정하여 파라미터를 추가 합니다
[root]# vi /etc/my.cnf
[mysqld] <--- 항목에 추가
large-pages
MySQL 을 중지 합니다.
[root]# systemctl stop mysqld
커널 파라미터 적용 및 MySQL 시작
커널 파라미터를 적용하게 되면 설정한 만큼의 2MB Large Page를 확보하게 됩니다. 그래서 파라미터 적용 전 메모리가 충분한지 한번 쯤은 확인 해 봐야 합니다.
MySQL 이 정상 종료 되고 MySQL 에서 사용하던 메모리도 모두 반환 되어 준비가 되었다면 커널 파라미터를 적용 합니다.
[root]# sysctl -p
LargePage 현황을 조회 해봅니다.
[root]# cat /proc/meminfo | grep -i huge
AnonHugePages: 0 kB
HugePages_Total: 19712 < **
HugePages_Free: 19712 <**
HugePages_Rsvd: 0
HugePages_Surp: 0
Hugepagesize: 2048 kB
위에서 확인 되듯 Hugepage 수가 설정한 만큼 확보가 된것을 확인 할 수 있습니다.
# MySQL 시작
[root]# systemctl start mysqld
로그 및 상태 확인
• Large Page 로 정상 기동 된 상태
[Note] InnoDB: Initializing buffer pool, total size = 35G, instances = 2, chunk size = 128M
[Note] InnoDB: Completed initialization of buffer pool
위의 로그가 정상적으로 Large Page 로 시작된 상태 입니다.
# meminfo 를 조회 하면 아래와 같이 사용 중임 알 수 있습니다.
[root@wmp ~]# cat /proc/meminfo | grep -i huge
AnonHugePages: 98304 kB
HugePages_Total: 19712
HugePages_Free: 15107
HugePages_Rsvd: 13902
HugePages_Surp: 0
Hugepagesize: 2048 kB
총 19712개 페이지 중 4605개를 사용중이고(19712-15107) 13902개가 사용 하기위해서 reserved 상태로 예약된 상태 입니다.
MySQL 시작 초기에 Buffer Pool 이 사용량이 미비할 때 입니다.
사용량에 따라 Hugepage의 현황은 달라 집니다.
• 일부 혹은 전부 Large Page 로 기동 되지 못한 상태
large-pages 가 설정된 상태에서 커널 파라미터에 설정된 large page 수가 부족 하는 등 맞지 않아도 MySQL은 기동 됩니다
다만 로그상에서는 일부(혹은 전부)가 일반 페이지로 가동 되었다고 메세지를 확인 할 수 있습니다.
[Warning] InnoDB: Failed to allocate 138412032 bytes. errno 12
[Warning] InnoDB: Using conventional memory pool
하여 MySQL 재시작등 가동 이후 로그를 확인하여 정상적으로 Large Page를 사용 하였는지 한번은 확인이 필요 합니다.
보통의 경우라면 DB외 Large Page 를 사용 할 수 있는 어플리케이션이나 데몬이 없을 것입니다.
그래서 설정된 Large Page 가 부족 할 수가 없는것이 보통의 경우 입니다.
테스트중 PHP-FPM 도 Large Page 를 사용하여 Page 수가 부족하여 MySQL 메모리 일부가 Normal Page 로 가동된 상황이 있었습니다
그래서 Database 임으로 가동시 당연히 로그를 확인 하겠지만 Large Page 사용시 이부분도 확인은 해봐야 할 것 입니다.
[참고] Oracle Database 에서는 파라미터에서 Large Page만 사용하도록 강제 하는 파라미터가 존재 합니다
설정의 문제나 기타의 문제로 인하여 Large Page 의 allocation이 불가능한 상황일때 로그와 사용자에게 메세지를 발생됩니다.
또한 DB도 가동되지 않아 문제를 바로 직관적으로 알수있는 파라미터가 제공 되기도 합니다
HugePage 사용량 확인
위의 내용에서 4605개를 사용 중으로 /proc/meminfo 를 통해 확인 하였습니다.
[root@wmp ~]# cat /proc/meminfo | grep -i huge
AnonHugePages: 98304 kB
HugePages_Total: 19712
HugePages_Free: 15107
HugePages_Rsvd: 13902
HugePages_Surp: 0
Hugepagesize: 2048 kB
그럼 4605개의 Large Page 를 MySQL 이 사용 중인 지를 확인 하고 싶을수 있습니다.
혹은 MySQL 에서 사용중인 Large Page 수를 조회 해보고 싶을 수 있습니다
아래 Perl 스크립트를 통해서 쉽게 조회해 볼 수 있습니다
[root]# vi counthugepages.pl ## 아래 내용으로 작성 ## sub counthugepages { my $pid=$_[0]; open (NUMAMAPS, "/proc/$pid/numa_maps") || die "can't open numa_maps"; my $HUGEPAGECOUNT=0; while (<NUMAMAPS>) { if (/huge.*dirty=(\d+)/) { $HUGEPAGECOUNT+=$1; } } close NUMAMAPS; return ($HUGEPAGECOUNT); } printf "%d huge pages\n",counthugepages($ARGV[0]);
위와 같이 스크립트를 먼저 생성 후 mysql pid를 입력하여 조회 합니다
[root@wmp ~]# ps -ef| grep mysql | grep -v grep | grep -v root
mysql 6033 1 0 Oct12 ? 00:00:01 /usr/sbin/mysqld <중략>
[root]# perl counthugepages.pl 6033
4605 huge pages < ***
/proc/meminfo 에서 Total - Free 를 계산한 4605개가 동일 함으로 현재는 mysql만이 Large Page를 사용한다고 보면 되겠습니다.
이렇게 LargePage를 사용하게되면 대용량 메모리를 사용 할 수록 메모리, 페이지, CPU 연산등에 overhead 를 줄여주는 등의 도움이 될 것 입니다.
SysBench 테스트
성능 테스트는 sysbench를 이용하여 진행 하였습니다 sysbench 에 관한 내용은 아래글을 보시면 됩니다.

테스트 환경 : Intel Xeon CPU 2.20GHz 56 core(하이퍼스레드 포함) ,OS 메모리 128gb , MySQL InnDB Buffer Pool 35G
Sysbench 조건 : 테이블 10개 , 테이블당 1,000만건(약 2143MB), Thread 16, warmup:60초, 수행시간 120초 , report-interval : 2초 , 사용 스크립트 oltp_read_only.lua
- 4kb Normal Page : 134492 qps
- 2MB Large Page : 142498 qps
포스팅의 테스트 시스템에서는 HugePage 이 4K에 비해 약 5-7% 가량의 개선 또는 성능 향상을 확인 할 수 있었으며 시스템 스펙과 상황에 따라 결과는 다소 차이가 있을 수 있습니다.
연관된 다른 글




Principal DBA(MySQL, AWS Aurora, Oracle)
핀테크 서비스인 핀다에서 데이터베이스를 운영하고 있어요(at finda.co.kr)
Previous - 당근마켓, 위메프, Oracle Korea ACS / Fedora Kor UserGroup 운영중
Database 외에도 NoSQL , Linux , Python, Cloud, Http/PHP CGI 등에도 관심이 있습니다
purityboy83@gmail.com / admin@hoing.io