10 KiB
id, kind, slug, title, topic, topicName, project, status, basisVersion, studio, sourceRevision, source
| id | kind | slug | title | topic | topicName | project | status | basisVersion | studio | sourceRevision | source | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| efce9a6e-5f5d-45ec-86e5-056d8cb1b8d2 | CONCEPT | huge-pages-in-a-vm | Huge Page 를 VM 에서 볼 때 갈라지는 세 자리 | memory-virtualization | 메모리 가상화 | virtualization | 초안 | Linux THP(/sys/kernel/mm/transparent_hugepage/enabled) · HugeTLB pool · x86-64 의 4 KiB / 2 MiB / 1 GiB page | https://hyeonworks.com/studio/documents/efce9a6e-5f5d-45ec-86e5-056d8cb1b8d2/edit | no-commit · 밖에서 반입한 문서 한 편. 고정할 저장소 리비전이 없다 |
|
Huge Page 를 VM 에서 볼 때 갈라지는 세 자리
페이지 크기를 키우면 같은 메모리 범위를 더 적은 매핑으로 표현할 수 있고, TLB(Translation Lookaside Buffer, 주소 변환 캐시) 엔트리 하나가 덮는 범위도 넓어진다. 그런데 가상 머신에는 주소 변환 단계가 둘이라 「Huge Page 를 쓴다」는 말만으로는 어디를 말하는지 정해지지 않는다. 게스트 페이지 테이블 단계인지, QEMU 가 마련한 호스트 쪽 메모리인지, EPT(Extended Page Tables) 매핑인지를 나누어 물어야 그 말이 뜻을 갖는다. Linux 가 큰 페이지를 마련하는 방법도 THP(Transparent Huge Pages)와 HugeTLB 두 가지인데, 둘은 관리 주체도 사전 예약 여부도 다르다.
관계
- Guest 메모리 주소가 물리 RAM 에 닿기까지 — GVA · GPA · HPA 페이지 크기 선택이 걸리는 두 변환 단계를 그 글이 세운다.
- 이 호스트의 THP 정책과 huge page 상태는 무엇인가 이 서버의 THP 정책과 huge page 관련 값을 읽는 질문이다. 이 글은 그 값이 무엇을 뜻하는지까지만 적었다.
- 가상 머신 RAM 이 HugeTLB 로 명시적으로 backing 되어 있는가 세 곳 가운데 호스트 쪽을 이 서버에서 확인하는 질문이다.
- 메모리 실험 결과에는 Host · VM · Workload 조건을 함께 남긴다 THP 정책과 huge page 설정은 그 기준이 요구하는 기록 항목에 들어간다.
본문
페이지가 커지면 매핑 수가 준다
같은 메모리 범위라도 페이지 크기에 따라 필요한 매핑 수가 달라진다. 원문은 8 GiB 를 예로 들어 셋을 나란히 계산했다.
| 페이지 크기 | 8 GiB 를 표현하는 데 필요한 페이지 수 |
|---|---|
| 4 KiB | 2,097,152 pages |
| 2 MiB | 4,096 pages |
| 1 GiB | 8 pages |
큰 페이지는 더 적은 매핑으로 넓은 메모리 범위를 표현할 수 있다. 위 8 GiB 는 계산을 보이려고 원문이 든 예시 값이고 이 서버 가상 머신의 설정이 아니다.
TLB 엔트리 하나가 덮는 범위
TLB 엔트리 하나가 가리키는 페이지가 커지면 캐시된 변환 하나로 더 넓은 주소 범위를 덮을 수 있다.
4 KiB page × 512 mappings
= 2 MiB coverage
2 MiB page × 512 mappings
= 1 GiB coverage
실제 CPU 는 페이지 크기마다 TLB 구조와 엔트리 수가 다르기 때문에, 이 숫자를 특정 CPU 의 실제 TLB 용량으로 해석하면 안 된다. 여기서 남는 것은 방향 하나다. 페이지 크기가 커지면 변환 하나가 덮는 범위가 넓어지고 TLB 압박이 줄어들 가능성이 생긴다. 페이지 테이블 엔트리 수와 페이지 테이블 탐색 부담도 함께 줄어들 가능성이 있다.
가상 머신에서는 세 곳을 따로 물어야 한다
가상 머신에는 GVA(Guest Virtual Address)를 GPA(Guest Physical Address)로 바꾸는 단계와, 그 GPA 를 HPA(Host Physical Address)로 바꾸는 단계가 있다.
GVA
│ Guest Page Table
▼
GPA
│ EPT
▼
HPA
그래서 "Huge Page를 사용한다"는 말만으로는 부족하다. 세 가지를 갈라 물어야 한다.
- 게스트 페이지 테이블 단계에서 큰 페이지를 쓰는가?
- 호스트가 그 메모리를 Huge Page 로 받치고 있는가?
- EPT 매핑에서 큰 매핑을 활용하는가?
게스트와 호스트의 페이지 크기 선택을 같은 설정 하나로 묶어 다루면 안 된다. 게스트 안에서 THP 가 켜져 있어도 그것은 첫 질문에 대한 답이고, 그 가상 머신의 RAM 을 호스트가 무엇으로 받치는지는 두 번째 질문이 따로 받는다.
THP — 커널이 조건이 맞을 때 알아서 쓰는 방식
THP 는 Linux 가 가능한 메모리 영역에 대해 Huge Page 를 투명하게 활용하려는 기능이다. 애플리케이션이 평소처럼 malloc() 이나 mmap() 을 부르면 커널이 조건이 맞는 영역에 Huge Page 활용을 시도한다. 애플리케이션이 큰 페이지를 달라고 따로 요청하지 않는다는 뜻에서 투명하다.
지금 어떤 정책이 걸려 있는지는 /sys/kernel/mm/transparent_hugepage/enabled 에서 읽는다.
cat /sys/kernel/mm/transparent_hugepage/enabled
always [madvise] never
이 값은 커널과 배포판, 호스트 설정에 따라 다르므로 실제 시스템에서 확인한다. 그래서 원문은 메모리 실험마다 반드시 같이 남길 조건 목록에 THP policy 를 Host 항목으로, Memory backing 설정을 VM 항목으로 넣어 두었다. 조건을 남기지 않으면 "Memory pressure에서 느려졌다"는 결과를 다른 환경에 재사용하기 어렵다는 것이 그 목록에 붙은 이유다.
THP 가 치르는 비용
Huge Page 에는 이어진 큰 물리 메모리 영역이 필요하다. 2 MiB 하나가 4 KiB 페이지 512 개에 해당해서, 그만큼 이어진 영역을 확보하지 못하면 커널이 compaction 같은 작업을 수행할 수 있다.
Huge Page 필요
↓
큰 contiguous memory 필요
↓
Fragmentation
↓
Compaction 가능
↓
Latency 영향 가능
그래서 THP 는 항상 성능을 높인다고 단정할 수 없다. 특히 지연에 민감한 워크로드에서는 측정이 필요하다고 원문이 직접 적었고, 이 서버에서 그 측정을 하지 않았다.
HugeTLB — 미리 확보해 둔 풀
HugeTLB 는 Huge Page 풀을 명시적으로 두고 쓸 수 있는 Linux 메커니즘이다. 커널이 알아서 활용하는 THP 와 달리, 관리자가 풀을 준비하고 애플리케이션이나 가상 머신이 그 풀을 명시적으로 쓴다.
Physical RAM
┌──────────────────────────┐
│ Normal Memory │
├──────────────────────────┤
│ HugeTLB Pool │
│ 2 MiB │
│ 2 MiB │
│ 2 MiB │
│ ... │
└──────────────────────────┘
미리 확보해 두면 예측 가능성을 높일 수 있지만, 풀로 떼어 둔 만큼은 일반 할당이 쓸 수 없기 때문에 일반적인 메모리 할당의 유연성은 그만큼 줄어든다.
둘을 가르는 여섯 항목
| 무엇을 견주나 | THP | HugeTLB |
|---|---|---|
| 관리 | 커널이 투명하게 활용 | 명시적인 풀 |
| 애플리케이션 개입 | 상대적으로 적음 | 명시적 구성 가능 |
| 유연성 | 상대적으로 높음 | 상대적으로 낮음 |
| 사전 예약 | 핵심 방식 아님 | 가능 |
| compaction 영향 | 발생 가능 | 미리 확보해 일부 상황 회피 가능 |
| 가상 머신 RAM backing | 사용 가능 | 명시적으로 사용 가능 |
호스트에서 두 값을 함께 읽으면 어느 쪽이 쓰이고 있는지 갈린다.
grep -i huge /proc/meminfo
cat /sys/kernel/mm/transparent_hugepage/enabled
AnonHugePages 와 HugePages_Total 은 같은 뜻이 아니다. 앞의 값은 익명 메모리에서 THP 로 쓰이고 있는 양이고, 뒤의 값은 HugeTLB 풀로 확보해 둔 페이지 수다. 한쪽이 0 이어도 다른 쪽이 커질 수 있어서, 두 값을 한 이름으로 묶어 읽으면 어떤 방식이 돌고 있는지 알 수 없다.
이 글이 확정하지 않는 것
이 호스트에서 잰 값은 하나도 없다. THP 정책도 HugePages_Total 도 읽지 않았고 가상 머신의 메모리 backing 설정도 확인하지 않았다. 원문 제2부는 개념 서술이고 실제 서버에 딸린 값은 OQ(Open Question) 번호가 붙은 확인 목록 열넷으로 미뤄져 있다.
호스트 쪽 값은 OQ-4 가 받는다. THP 정책과 함께 AnonHugePages, HugePages_Total, HugePages_Free, Hugepagesize 를 읽어 이 서버가 어느 방식을 쓰고 있는지 확정하는 확인이다.
가상 머신 쪽 backing 은 OQ-5 가 받는다. libvirt 의 memory backing 설정을 읽고 호스트의 /proc/meminfo, QEMU 의 smaps 계열 값과 교차 검증한다.
virsh dumpxml <VM_NAME>
두 확인이 끝나기 전에는 이 글의 세 질문 가운데 어느 것도 이 서버에 대해 답이 없다. 그리고 두 확인이 끝나도 셋째 질문은 남는다. EPT 매핑에서 큰 매핑을 쓰는가를 이 호스트에서 재라고 적은 항목은 그 열넷에 없다. 원문이 커널·QEMU·libvirt 버전을 적지 않아 이 글도 특정 버전에 고정하지 않았고, THP 정책의 기본값이 배포판마다 다르다는 점도 원문이 확인하라고만 적었다.