Last Updated on 2월 15, 2021 by 태랑(정현호)
Page는 메모리 관리의 작은 데이터 단위
page 는 가상 메모리를 특정 사이트(normal 기준 4k) 사이즈 단위로 분할한 단위 입니다
x86 에서 page 크기를 normal 4KB , 2MB 등을 지원 하고 있습니다
보편적으로 리눅스(x86) 에서는 Normal Size 인 4KB 인 페이지를 사용하여 데몬과 어플리케이션이 사용되고 있습니다.
위에서 언급 한 것처럼 4KB 외 더 큰 사이즈의 페이지가 지원 되고 큰 사이즈의 페이즈를 large page 나 huge page 라고 합니다.
이런 large page 를 사용 할 수 있는 어플리케이션이나 데몬에서 이런 큰 사이즈의 페이지를 사용할 수 있는 기능이 지원이 되어야 사용이 가능 합니다.
그래서 보통의 데몬이나 어플리케이션은 4k normal page 를 사용하게 됩니다.
2MB size의 Large Page 를 사용하는 어플리케이션에는 대표적으로 Database 제품중에 Oracle Database , PHP-CGI 인 PHP-FPM 도 Large Page를 사용 할 수 있습니다(그외 다수)
Database 는 Datafile 에 저장된 블럭을 Buffer Cache 의 메모리 공간에 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 사용의 장점 다음과 같습니다
1. Default normal page 는 4KB 이며 HugePage는 2MB 로, 이는 Hugepage가 512배(512 times) 적은 페이지의 처리를 의미 합니다.
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 설정
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 = 384M 으로 설정되어 있다면 (384MB+10%여유분) / 2MB 으로 계산해서 설정하면 됩니다.
mysql 내에서는 쿼리를 통해서 조회하면 아래와 같습니다.
[root]# mysql --login-path=dba
Server version: 5.7.31 MySQL Community Server (GPL)
Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved.
mysql> select (@@innodb_buffer_pool_size+(@@innodb_buffer_pool_size*0.1)) /1024/1024/2 calc;
+-------------------+
| calc |
+-------------------+
| 211.2000000000000 |
+-------------------+
1 row in set (0.00 sec)
mysql --login-path 관련 해서는 아래 포스팅을 참조하시면 됩니다.

위의 계산 대로 211 정도를 현재 시스템에서는 설정 하도록 하겠습니다.
[root]# vi /etc/sysctl.conf
vm.nr_hugepages=211
-> 내용 추가
# vm.hugetlb_shm_group 설정
hugetable 를 사용할 수 있는 그룹을 지정 하는 커널 파라미터 입니다.
[root]# cat /etc/group | grep mysql
mysql:x:1002:
[root]# vi /etc/sysctl.conf
vm.hugetlb_shm_group=1002
-> 내용 추가
# memlock 수정
[root]# vi /etc/security/limits.conf
mysql soft memlock unlimited
mysql hard memlock unlimited
-> 2개 라인 내용 추가
# Transparent Huge Pages 기능 비활성화
THP 기능을 비활성화 합니다 이전에 THP 비활성화에 대해서 포스팅 한 내용이 있습니다.
아래 링크 글을 참조하여 서비스 등록하여 비활성화 하면 됩니다.

추가로 swappiness 가 높게 설정되어 있다면 수치를 낮춰서 설정을 합니다.
[root]# vi /etc/sysctl.conf
vm.swappiness=10
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: 211 < **
HugePages_Free: 211 <**
HugePages_Rsvd: 0
HugePages_Surp: 0
Hugepagesize: 2048 kB
위에서 확인 되듯 Hugepage 수가 설정한 만큼 확보가 된것을 확인 할 수 있습니다.
# Mysq 기동
[root]# systemctl start mysqld
로그 및 상태 확인
== Large Page 로 정상 기동 된 상태
[Note] InnoDB: Initializing buffer pool, total size = 384M, instances = 1, chunk size = 128M
[Note] InnoDB: Completed initialization of buffer pool
위의 로그가 정상적으로 Large Page 로 가동된 상태 입니다.
# meminfo 를 조회 하면 아래와 같이 사용 중임 알 수 있습니다.
[root@wmp ~]# cat /proc/meminfo | grep -i huge
AnonHugePages: 12288 kB
HugePages_Total: 211
HugePages_Free: 200
HugePages_Rsvd: 191
HugePages_Surp: 0
Hugepagesize: 2048 kB
총 211개 페이지 중 11개를 사용중이고(211-200-free) 191개가 사용 하기위해서 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 사용량 확인
위에서 11개를 사용 중으로 /proc/meminfo 를 통해 확인 하였습니다.
[root@wmp ~]# cat /proc/meminfo | grep -i huge
AnonHugePages: 12288 kB
HugePages_Total: 211
HugePages_Free: 200
HugePages_Rsvd: 191
HugePages_Surp: 0
Hugepagesize: 2048 kB
그럼 11개의 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
11 huge pages < ***
/proc/meminfo 에서 Total - Free 를 계산한 11개가 동일 함으로 현재는 mysql만이 Large Page를 사용한다고 보면 되겠습니다.
이렇게 LargePage를 사용하게되면 대용량 메모리를 사용 할 수록 메모리, 페이지, CPU 연산등에 overhead 를 줄여주는 등의 도움이 될 것 입니다.
SysBench 테스트
성능 테스트는 sysbench를 이용하여 진행 하였습니다 sysbench 에 관한 내용은 아래글을 보시면 됩니다.

테스트 환경 : CPU 4 core , OS 12gb , Mysql InnDB Buffer Pool 8G
Sysbench 조건 : 테이블 7개 , 테이블당 500만건(약 1GB), Thread 4, warmup:30초, 수행시간 60초 , report-interval : 2초 , 사용 스크립트 select_random_ranges.lua
4kb Normal Page : 15664 qps
2MB Large Page : 16281 qps
각자의 시스템 스펙과 상황에 따라 결과는 다소 차이가 있을 수 있습니다.
InnoDB Buffer Pool 이 더 크다면 Normal / Large Page 간의 선능이나 qps 의 차이가 더 많이 날 것으로 예측 됩니다.
연관된 다른 글



Senior DBA(Mysql, Oracle) - 현재 위메프에서 많은 새로움을 경험중입니다
At WeMakePrice / Previous - Oracle Korea ACS Support / Fedora Kor UserGroup 운영중
Database 외에도 NoSQL , Linux , Cloud, Http/PHP CGI 등에도 관심이 있습니다
purityboy83@gmail.com / admin@hoing.io