feat: 가상화 문서들 추가

This commit is contained in:
DongHyeonka
2026-09-10 08:54:05 +09:00
parent e9f6a93327
commit 43e1aadef0
695 changed files with 153404 additions and 12754 deletions
@@ -0,0 +1,102 @@
---
id: 6a60abe7-ea2c-46c2-bb9f-8281bfbe9644
kind: QUESTION
slug: balloon-target-vs-guest-available-memory
title: balloon target 을 바꾸면 게스트가 쓸 수 있는 메모리는 어떻게 따라 움직이는가
topic: memory-virtualization
topicName: 메모리 가상화
project: virtualization
status: 초안
questionStatus: OPEN
studio: "https://hyeonworks.com/studio/documents/6a60abe7-ea2c-46c2-bb9f-8281bfbe9644/edit"
sourceRevision: no-commit · 밖에서 반입한 문서 한 편. 고정할 저장소 리비전이 없다
source:
- final/document.md#83-실제-환경에서-확인할-open-question-oq-9
- final/document.md#66-balloon-inflate
- final/document.md#68-balloon-deflate
- final/document.md#69-ballooning을-과도하게-하면-guest가-압박을-받는다
---
# balloon target 을 바꾸면 게스트가 쓸 수 있는 메모리는 어떻게 따라 움직이는가
virtio-balloon 은 게스트에 RAM 을 새로 붙여 주는 장치가 아니라, 이미 있는 게스트 RAM 의 backing 을 호스트와 게스트가 협력해 회수하고 되돌려주는 가상 장치다. 호스트는 balloon target 을 조정해 그 balloon 을 부풀리거나 줄인다. 개념 문서는 방향까지 적어 두었는데, inflate 하면 게스트가 쓸 수 있는 RAM 이 줄고 deflate 하면 늘어난다.
개념 문서가 방향만 적고 크기는 적지 않아서, 이 물음이 받는 것은 방향이 아니라 크기와 시점이다. 이 호스트에서 목표값을 한 단계 움직였을 때 게스트가 쓸 수 있는 메모리가 얼마나 줄어드는지를 아직 값으로 받아 본 적이 없다. 그 변화가 언제 보이는지, 어느 지점부터 게스트가 reclaim 과 스왑을 시작하는지도 마찬가지다.
## 관계
- **virtio-balloon 이 Guest 메모리를 회수하고 돌려주는 방식**
inflate 와 deflate 가 게스트가 쓸 수 있는 메모리를 어느 방향으로 움직이는지를 그 개념이 설명한다.
- **Host 메모리 압박이 Guest 와 스토리지까지 내려가는 경로**
과도한 inflate 가 게스트를 밀어 넣는 곳이 그 경로다.
- **이 가상 머신들에 virtio-balloon 이 붙어 있는가**
balloon 이 붙어 있다는 답을 받은 뒤에 이 실험을 연다.
- **메모리 실험 결과에는 Host · VM · Workload 조건을 함께 남긴다**
단계마다 받아 적을 조건을 그 기준이 정한다.
## 사실
- 호스트가 게스트 메모리를 회수하려고 할 때 balloon 을 inflate 한다. 게스트 안의 balloon 이 커지기 때문에 게스트가 쓸 수 있는 RAM 이 줄어들고, 호스트가 회수할 수 있는 backing memory 는 늘어난다.
- 호스트가 게스트에게 메모리를 다시 내줄 수 있으면 balloon target 을 줄인다. 그러면 게스트의 balloon 드라이버가 balloon page 를 반환하고 게스트가 쓸 수 있는 메모리가 늘어난다.
- 게스트의 balloon 드라이버는 게스트 page 를 확보하고 그 사실을 호스트 쪽에 알린다. 호스트가 그 backing memory 를 실제로 언제 어떻게 회수하는지는 QEMU 와 KVM 버전, backing 종류, 설정에 따라 달라질 수 있다고 개념 문서가 적어 두었다.
- 게스트 애플리케이션의 working set 이 큰데 balloon 을 과도하게 inflate 하면 다음 순서로 이어질 수 있다. 마지막에 오는 OOM(Out Of Memory)은 reclaim 으로도 필요한 메모리를 확보하지 못해 커널이 프로세스를 종료할 수 있는 상태다.
Guest available memory 감소 → Guest memory pressure → Guest reclaim → page cache 회수 → Guest swap → 심하면 Guest OOM
- 호스트 RAM 을 확보하려던 조치가 게스트의 스토리지 I/O 와 애플리케이션 지연을 늘릴 수 있다.
- 개념 문서가 적은 관측 순서는 호스트와 libvirt 의 메모리 설정을 바꾸고, 게스트에서 free -h 와 /proc/meminfo 를 본 다음, 게스트의 reclaim 과 스왑이 어떻게 달라지는지 보는 것이다.
- 과도한 ballooning 구간의 지연과 스왑, OOM 가능성은 별도 실험으로 보라고 같은 항목이 적어 두었다.
- Ballooning 은 기존 게스트 메모리 용량 안에서 쓸 수 있는 메모리를 회수하고 되돌려준다. 용량 자체를 늘리는 memory hotplug 와 다르고 virtio-mem 같은 다른 동적 메모리 관리 방식도 있으므로, 셋을 하나로 묶어 일반화하지 않는다.
- 이 호스트에서 balloon target 을 움직여 본 기록이 없다. 게스트가 쓸 수 있는 메모리를 찍어 둔 값도 없다.
## 가정
- 이 가상 머신들에 virtio-balloon 이 붙어 있다고 보고 실험을 짠다. 붙어 있는지 자체는 별도 물음이 받는다.
- balloon target 을 낮췄다가 원래 값으로 되돌릴 수 있다고 본다.
- 관측하는 동안 게스트의 워크로드가 일정하다고 전제한다. 그래야 쓸 수 있는 메모리가 달라진 것을 목표값을 바꾼 탓으로 읽을 수 있다.
- 게스트 안에서 읽은 값이 balloon 의 현재 크기를 반영한다고 본다. 두 값을 이 호스트에서 나란히 대조하지는 않았다.
## 미지수
- 목표값을 한 단계 낮췄을 때 게스트가 쓸 수 있는 메모리가 같은 크기만큼 줄어드는지, 그보다 덜 줄어드는지.
- 목표값을 바꾼 직후에 게스트 쪽 값이 바뀌는지, 반영에 시간이 걸리는지.
- 어느 목표값부터 게스트의 reclaim 과 스왑이 시작되는지.
- deflate 로 되돌렸을 때 그 값이 원래대로 돌아오는지.
- balloon target 을 바꾸는 명령. 개념 문서는 호스트와 libvirt 의 메모리 설정이라고만 적고 명령은 적지 않았다.
## 제약
- balloon 이 붙어 있지 않으면 목표값을 움직일 대상이 없으므로, 이 실험은 붙어 있다는 확인이 끝난 뒤에 연다.
- 개념 문서가 그 구간을 별도 실험으로 지정했으니 과도 inflate 구간은 같은 실행에 이어 붙이지 않고 따로 돌린다.
- 단계마다 Host · VM · Workload 조건을 함께 적는다. 조건을 남기지 않은 결과는 다른 환경에서 다시 쓰기 어렵다.
- 게스트 OOM 까지 밀어 볼지는 이 실험에서 정하지 않는다.
- 개념 문서가 목표값을 바꾸는 명령을 적어 주지 않았으므로 실행한 명령과 그 출력을 증거로 함께 남긴다.
- 호스트가 실제로 회수한 backing memory 는 이 실험에서 재지 않는다. 개념 문서가 그 동작을 QEMU 와 KVM 버전, backing 종류, 설정에 따라 달라질 수 있다고만 적고 단정을 피했고, §83 OQ-9 가 준 관측 순서도 호스트 설정을 바꾼 뒤 게스트 쪽 값과 게스트의 reclaim 과 스왑 변화를 보는 데까지다.
## 선택지
### 1. 목표값을 여러 단계로 나눠 낮추고 단계마다 게스트 값을 받아 적는다
한 번에 크게 줄이지 않고 단계를 나누면 목표값과 게스트가 쓸 수 있는 메모리의 대응이 표로 남는다. reclaim 과 스왑이 시작되는 지점도 어느 단계와 어느 단계 사이인지까지 좁혀진다.
단계 수만큼 실행이 늘어나고, 단계마다 게스트 값을 같은 방법으로 받아 적어야 한다.
### 2. 한 단계만 낮췄다가 되돌린다
inflate 와 deflate 가 개념 문서가 적은 방향으로 움직이는지만 이 호스트에서 확인한다. 실행이 짧고 되돌리기도 쉽다.
대신 목표값과 게스트 메모리를 짝지은 값이 한 쌍만 나온다. reclaim 이 시작되는 지점은 이 방법으로 나오지 않아서, 그것까지 알아야 하면 결국 첫 번째 선택지로 돌아간다.
### 3. 과도 inflate 까지 한 번에 밀어 본다 — 제외
게스트가 압박을 받는 구간까지 한 실행으로 내려가서 정상 구간과 압박 구간을 함께 보자는 방법이다.
제외한 이유는 둘이다. 개념 문서가 그 구간을 별도 실험으로 분리해 두었고, 게스트 스왑과 OOM 이 걸리면 그 실행에서 받은 앞 단계 값도 같은 조건으로 읽기 어려워지기 때문이다.
## 다음 검증
1. balloon 이 이 가상 머신들에 붙어 있다는 확인을 먼저 받는다.
2. 게스트에서 free -h 와 /proc/meminfo 와 vmstat 1 을 찍어 기준값으로 둔다.
3. 호스트에서 balloon target 을 한 단계 낮추고 같은 셋을 다시 찍는다.
4. 단계를 몇 번 반복해 목표값과 게스트가 쓸 수 있는 메모리의 대응을 한 표로 만든다.
5. 목표값을 바꾸는 데 쓴 명령과 그 출력을 함께 남긴다. 개념 문서에 적혀 있지 않은 명령이다.
6. 과도 inflate 구간은 실행을 나누고, 그 구간에서는 게스트 애플리케이션 지연을 같이 잰다.
닫는 조건 : 목표값과 게스트가 쓸 수 있는 메모리가 표로 대응되고 reclaim 과 스왑이 시작되는 지점이 적히면 닫는다. 게스트 스왑이나 OOM 까지 갔으면 그 구간이 Case 가 되고, 운영에서 balloon 을 쓸지와 목표값 하한을 얼마로 둘지는 그 Case 가 나온 뒤 Decision 으로 넘긴다.
@@ -0,0 +1,98 @@
---
id: 074a1cb4-cea8-4dad-bc4c-899692ff9aa9
kind: QUESTION
slug: guest-page-fault-vs-workload
title: 게스트 page fault 증가는 workload 변화를 따라가는가
topic: memory-virtualization
topicName: 메모리 가상화
project: virtualization
status: 초안
questionStatus: OPEN
studio: "https://hyeonworks.com/studio/documents/074a1cb4-cea8-4dad-bc4c-899692ff9aa9/edit"
sourceRevision: no-commit · 밖에서 반입한 문서 한 편. 고정할 저장소 리비전이 없다
source:
- final/document.md#83-실제-환경에서-확인할-open-question-oq-13
- final/document.md#45-guest-page-fault
- final/document.md#46-page-fault의-대표적인-원인
---
# 게스트 page fault 증가는 workload 변화를 따라가는가
게스트 안에서 page fault 가 늘었다는 관측 하나로는 무슨 일이 일어났는지 갈리지 않는다. 개념 문서가 든 대표적인 원인은 다섯인데, 그 가운데 demand paging 과 copy-on-write 는 정상 동작이다. 나머지 중 swap-in 은 게스트 RAM 이 모자란다는 신호이고, invalid access 만 프로그램 오류로 이어진다.
이 물음은 이 호스트의 게스트에서 부하를 올렸을 때 fault 지표가 함께 오르는지를 구간을 나눠 받는다. 올랐다면 그 증가가 다섯 원인 가운데 어느 쪽으로 설명되는지까지 본다.
다섯 원인을 하나씩 묻지 않고 한 물음으로 묶었다. 원인마다 물음을 세우면 개념 문서에서 한 줄이던 것이 다섯 편이 되고, §83 OQ-13 이 갈라 보라고 한 네 갈래는 같은 구간의 같은 지표에서 나온다.
## 관계
- **VM 에서 page fault 는 세 계층에서 따로 일어난다**
게스트 안에서 본 fault 가 어느 계층의 사건인지를 그 개념이 가른다.
- **지금 게스트와 호스트에서 swap 이 실제로 오가고 있는가**
swap-in 이 실제로 있는지는 그 물음이 받는다. 여기서는 같은 구간의 스왑 활동을 함께 적어 fault 증가와 겹치는지만 본다.
- **호스트 major fault 와 스토리지 지연은 같은 시간축에서 함께 움직이는가**
호스트 쪽 fault 는 그 물음이 받고, 이 물음이 보는 것은 게스트 안의 fault 다.
- **메모리 증상 하나로 계층을 단정하지 않는다**
fault 증가 하나로 결론을 내지 않는 기준을 그 문서가 정한다.
## 사실
- 게스트 page fault 는 게스트 프로세스가 쓰는 주소인 GVA(Guest Virtual Address)를 게스트 페이지 테이블로 변환하는 첫 단계에서 그 접근을 지금 끝낼 수 없을 때 발생한다. 게스트 커널의 핸들러가 페이지를 확보하고 매핑을 갱신한 뒤 그 명령을 다시 실행한다.
- page fault 자체가 프로그램 오류를 뜻하지 않는다고 개념 문서가 밝혔다.
- 개념 문서가 든 대표적인 원인은 다섯이다.
demand paging : 영역은 있는데 아직 물리 페이지가 필요하지 않았고, 첫 접근에서 게스트 커널이 페이지를 준비한다.
swap-in : 필요한 페이지가 게스트 RAM 에 없어 게스트 스왑에서 읽어 RAM 을 복원하고 페이지 테이블을 갱신한다.
permission fault : 매핑은 있는데 권한이 맞지 않는다. 읽기 전용 페이지에 쓰면 발생할 수 있다.
copy-on-write : write fault 를 일부러 이용해 페이지를 복제하고 쓰기 가능한 매핑을 새로 만든다.
invalid access : 게스트 커널이 정상 매핑으로 해결할 수 없는 접근이고 SIGSEGV 등으로 이어질 수 있다.
- Page Fault 와 Segmentation Fault 는 다르다.
- 개념 문서의 확인 항목은 게스트에서 page-fault 관련 지표를 보되 정상 demand paging 인지, copy-on-write 인지, 게스트 swap-in 인지, 애플리케이션의 working set 이 커진 것인지를 갈라 보라고 적었다.
- 같은 항목이 page fault 증가만으로 오류라고 판단하지 말라고 적었다.
- 개념 문서는 page fault 지표를 무엇으로 읽는지 적지 않았다. 게스트와 호스트의 스왑 활동을 볼 때 쓰라고 적어 둔 명령은 free -h 와 vmstat 1 이다.
- 이 호스트의 게스트에서 fault 지표를 시간에 따라 찍어 둔 기록이 없다.
## 가정
- idle 구간과 부하 구간을 나눠 만들 수 있고, 두 구간에서 같은 방법으로 지표를 받을 수 있다고 본다.
- 부하를 만드는 방법이 게스트의 메모리 사용량도 함께 올린다고 전제한다. CPU 만 쓰는 부하라면 fault 지표가 움직이지 않을 수 있기 때문이다.
- 두 구간 사이에 게스트의 다른 조건이 바뀌지 않는다고 보고 견준다.
- 게스트 안에서 읽은 fault 지표가 게스트 page fault 를 센 것이라고 본다. EPT(Extended Page Tables) 관련 사건과 호스트 쪽 fault 는 게스트 안에서 보이지 않는다.
## 미지수
- 부하를 올렸을 때 fault 지표가 실제로 함께 오르는지.
- 오른 것이 minor 인지 major 인지.
- 그 증가가 다섯 원인 가운데 어느 쪽으로 설명되는지.
- minor 와 major 를 프로세스 단위로 가르는 방법. 개념 문서가 명령을 적지 않아 실행하는 쪽이 정한다.
- 애플리케이션의 working set 을 이 환경에서 무엇으로 재는지.
## 제약
- 같은 구간의 스왑 활동을 함께 적지 않으면 demand paging 과 swap-in 이 갈리지 않는다.
- fault 지표 하나로 원인을 확정하지 않는다. 개념 문서가 네 갈래를 갈라 보라고 적은 이유가 이것이다.
- 부하를 만드는 방법을 두 실행에서 같게 둔다. 방법이 바뀌면 fault 증가가 부하 때문인지 방법 때문인지 갈리지 않는다.
- 이 호스트에서 잰 값이 없으므로 다른 환경의 fault 수치를 근거로 삼지 않는다.
## 선택지
### 1. idle 구간과 부하 구간을 나눠 시간에 따른 변화를 받는다
두 구간에서 vmstat 1 로 시간에 따른 값을 받고, 같은 구간의 스왑 활동과 애플리케이션의 working set 을 함께 남긴다. 부하가 올라간 시각과 fault 가 오른 시각이 겹치는지가 그대로 보이고, 스왑 활동이 없는데 fault 만 올랐으면 demand paging 쪽으로 좁혀진다.
minor 와 major 를 프로세스 단위로 가르는 것까지는 이 방법으로 나오지 않는다.
### 2. 프로세스 단위로 minor 와 major 를 갈라 받는다
게스트 안의 대상 프로세스를 정해 그 프로세스의 fault 를 minor 와 major 로 나눠 받는다. major 가 함께 오르면 swap-in 쪽으로 좁혀지고, minor 만 오르면 demand paging 이나 copy-on-write 로 좁혀진다.
읽는 방법을 개념 문서가 적어 두지 않아서, 실행하는 쪽이 정하고 그 방법을 증거로 남겨야 한다.
## 다음 검증
1. 게스트에서 idle 구간을 먼저 정하고 그 구간의 fault 지표와 스왑 활동을 vmstat 1 로 받아 기준값으로 둔다.
2. 같은 게스트에 부하를 걸고 같은 방법으로 같은 항목을 다시 받는다.
3. 두 구간에 애플리케이션의 working set 을 함께 적는다.
4. 프로세스 단위로 minor 와 major 를 가른 경우에는 그 값을 읽은 방법을 같이 남긴다.
5. 두 구간을 한 시간축에 놓고 부하가 오른 시각과 fault 가 오른 시각이 겹치는지 본다.
닫는 조건 : 부하 구간의 fault 증가가 minor 위주이고 swap-in 이 없으면 정상 demand paging 으로 설명된다고 적고 닫는다. major fault 가 함께 오르면 게스트 swap-in 을 의심하고 그 구간을 스왑 쪽 물음으로 넘긴다. 어느 쪽으로도 설명되지 않으면 그 관측이 Case 가 된다.
@@ -0,0 +1,101 @@
---
id: a2cbc828-59ab-4e70-916a-d053e71960ae
kind: QUESTION
slug: host-major-fault-vs-storage-latency
title: 호스트 major fault 와 스토리지 지연은 같은 시간축에서 함께 움직이는가
topic: memory-virtualization
topicName: 메모리 가상화
project: virtualization
status: 초안
questionStatus: OPEN
studio: "https://hyeonworks.com/studio/documents/a2cbc828-59ab-4e70-916a-d053e71960ae/edit"
sourceRevision: no-commit · 밖에서 반입한 문서 한 편. 고정할 저장소 리비전이 없다
source:
- final/document.md#83-실제-환경에서-확인할-open-question-oq-14
- final/document.md#49-host-page-fault도-별도로-존재한다
- final/document.md#62-memory-pressure와-storage-contention의-연결
---
# 호스트 major fault 와 스토리지 지연은 같은 시간축에서 함께 움직이는가
개념 문서는 호스트의 메모리 압박에서 시작해 애플리케이션 지연으로 끝나는 사슬을 그려 두었다. 호스트 메모리 압박이 reclaim 과 스왑을 부르고, 그 스왑 I/O 가 스토리지 I/O 를 늘리고, 늘어난 I/O 가 한 물리 장치에서 경합하면 데이터베이스 지연을 거쳐 애플리케이션 지연까지 간다는 순서다.
사슬의 각 마디는 개념으로 이어져 있지만, 이 호스트에서 네 마디가 같은 구간에 함께 움직이는지는 아직 받아 본 적이 없다. 이 물음은 압박 실험을 한 번 돌릴 때 네 계열을 같은 타임스탬프로 받아 그 사슬이 여기서 이어지는지 끊기는지를 가른다.
## 관계
- **VM 에서 page fault 는 세 계층에서 따로 일어난다**
호스트 쪽 fault 가 게스트 쪽 fault 와 어떻게 다른 사건인지를 그 개념이 가른다.
- **Host 메모리 압박이 Guest 와 스토리지까지 내려가는 경로**
이 물음이 확인하려는 사슬을 그 개념이 그렸다.
- **호스트 메모리 압박이 게스트 애플리케이션 지연을 실제로 밀어 올리는가**
압박을 만드는 실험은 그쪽이 돌리고, 이 물음은 같은 실행에서 계열 넷을 받는다.
- **지금 게스트와 호스트에서 swap 이 실제로 오가고 있는가**
평상시 스왑 활동은 그 물음이 받고, 여기서는 압박 구간의 스왑 활동을 본다.
- **메모리 증상 하나로 계층을 단정하지 않는다**
네 계열을 함께 봐야 하는 근거를 그 기준이 정한다.
## 사실
- QEMU 도 호스트의 일반 userspace 프로세스이므로 QEMU 의 memory backing 에는 호스트의 가상 메모리 관리가 적용된다. demand allocation 이나 reclaim 과 스왑 때문에 호스트 쪽에서도 page fault 가 발생할 수 있다.
- VM 메모리 분석에서는 게스트 page fault 와 호스트 page fault, EPT(Extended Page Tables) 관련 사건을 적어도 셋으로 구분한다.
- 게스트와 호스트가 동시에 메모리 압박을 겪으면 게스트 스왑 I/O 와 호스트 스왑 I/O, 데이터베이스 I/O, filesystem writeback 이 한 물리 NVMe 로 몰릴 수 있다.
- 개념 문서가 그린 사슬은 호스트 메모리 압박에서 reclaim 과 스왑으로, 거기서 스토리지 I/O 증가와 스토리지 경합으로, 다시 데이터베이스 지연과 애플리케이션 지연으로 이어진다. 가능한 경로라고 적었지 이 호스트에서 확인했다고 적지는 않았다.
- CPU 사용률이 낮다고 해서 메모리나 스토리지 문제가 없다고 볼 수 없다.
- 개념 문서는 swap used 값 하나로 장애를 판단하지 말라고 하면서, 대신 swap-in 과 swap-out 이 지속되는지, reclaim pressure 가 증가하는지, major fault 가 증가하는지, 스토리지 지연이 같이 증가하는지를 묻는다. 그 확인에 적어 둔 명령은 free -h 와 vmstat 1 이고, 게스트와 호스트를 동시에 본다.
- 확인 항목은 호스트 fault 와 스왑 활동, 스토리지 지연, 게스트 애플리케이션 지연을 같은 시간축에 놓고 견주라고 적었다.
- 같은 문서의 스토리지 부분은 장치 I/O 관측 명령으로 iostat -xz 1 을 적었다. 메모리 쪽 확인 항목에는 스토리지 지연을 무엇으로 재는지 적혀 있지 않다.
- 호스트 쪽 major fault 를 이 장비에서 찍어 둔 기록이 없다.
## 가정
- 호스트에 메모리 압박을 걸었다가 풀 수 있다고 보고 실험을 짠다. 압박을 만드는 방법 자체는 별도 물음이 정한다.
- 네 계열을 같은 시계에서 받아 적을 수 있다고 본다. 시각이 어긋나면 함께 움직였는지 판단할 수 없기 때문이다.
- 압박 구간에 게스트 쪽 워크로드를 일정하게 유지할 수 있다고 전제한다.
- 호스트의 스왑 영역과 가상 머신 디스크 이미지가 같은 물리 장치 위에 있다고 보고 경합을 예상한다. 이 호스트에서 두 경로가 실제로 같은 장치를 쓰는지는 확인하지 않았다.
## 미지수
- 압박 구간에서 호스트 major fault 가 실제로 오르는지.
- 오른다면 같은 구간에 스왑 활동과 스토리지 지연도 같은 방향으로 움직이는지.
- 그 움직임이 게스트 애플리케이션 지연과 시간적으로 겹치는지.
- major fault 는 오르는데 스토리지 지연은 오르지 않는 구간이 있는지.
- 호스트 쪽 major fault 와 스토리지 지연을 이 환경에서 어떤 명령으로 읽는지. 메모리 쪽 확인 항목이 적지 않았다.
## 제약
- 압박 실험을 이 물음 때문에 따로 한 번 더 돌리지 않고, 지연 쪽 물음의 실행에서 계열을 함께 받는다. §84 의 권장 실험 순서가 압박 실험을 열 번째에 두고 게스트와 호스트의 스왑 및 스토리지 지연 비교를 그 다음 열한 번째에 두었다.
- 한 물리 장치를 여러 가상 머신이 나눠 쓸 때 무슨 일이 생기는지는 스토리지 가상화 주제가 따로 묻고 있다. 여기서는 그 물음을 다시 열지 않고 스토리지 지연을 같은 시간축에 놓는 데까지만 간다.
- swap used 값 하나로 판단하지 않는다.
- baseline 과 압박과 회복 세 구간을 모두 남긴다. 압박 구간만 있으면 오른 것인지 원래 그런 것인지 갈리지 않는다.
- 이 호스트에서 잰 값이 없으므로 다른 환경에서 네 계열이 함께 움직였다는 관찰을 근거로 삼지 않는다.
## 선택지
### 1. 압박 실험 한 번에서 네 계열을 같은 타임스탬프로 받는다
지연 쪽 물음이 돌리는 실행에 계열 넷을 붙여 baseline 과 압박과 회복 구간에서 모두 받는다. 같은 실행이라 시각이 어긋나지 않고, 네 계열을 한 시간축에 놓는 것이 이 물음이 답하려는 것과 같은 모양이다.
받을 항목이 늘어나므로 실행 전에 무엇을 어떤 명령으로 받을지 정해 두어야 한다.
### 2. 호스트 쪽 두 계열을 먼저 받고 스토리지는 뒤에 붙인다
major fault 와 스왑 활동만 먼저 받아 압박이 호스트에 실제로 걸렸는지 확인하고, 스토리지 지연과 게스트 지연은 다음 실행에서 붙인다. 첫 실행이 가볍고, 압박을 만드는 방법이 통하는지도 여기서 걸러진다.
두 실행 사이에 조건이 달라지면 네 계열을 한 시간축에 놓을 수 없어서, 결국 첫 번째 선택지로 다시 돌아가게 된다.
### 3. swap used 값이 오르는지로 판단한다 — 제외
호스트의 swap used 가 오르면 사슬이 이어진 것으로 읽자는 방법이다.
개념 문서가 그 판단을 직접 막았다. 과거에 swap-out 된 cold page 가 남아 있어도 값은 올라가 있어서, 지금 압박이 있는지는 그 값으로 갈리지 않기 때문이다.
## 다음 검증
1. 지연 쪽 물음의 실행 계획에 이 계열 넷을 넣는다.
2. baseline 구간에서 호스트의 major fault 와 스왑 활동을 vmstat 1 로, 스토리지 지연과 게스트 애플리케이션 지연을 각각 정한 방법으로 받는다.
3. 압박 구간에서 같은 넷을 같은 타임스탬프로 다시 받는다.
4. 압박을 푼 회복 구간에서 한 번 더 받는다.
5. 세 구간의 네 계열을 한 시간축에 놓고 어느 계열이 언제 움직였는지 적는다.
6. 스토리지 지연을 읽은 명령을 함께 남긴다. 메모리 쪽 확인 항목에 없는 것이라 실행한 쪽이 정한다.
닫는 조건 : 네 계열이 같은 구간에서 함께 오르면 개념 문서가 그린 사슬이 이 환경에서 이어진다는 것을 확인한 것이 되고, 그 시계열이 Case 가 된다. major fault 는 오르는데 스토리지 지연이 따라 오르지 않으면 이 장치 구성에서는 사슬이 거기서 끊긴다고 적고 닫는다. 어느 쪽이든 장치 분리나 스왑 위치 변경 같은 스토리지 쪽 대응은 그 뒤 Decision 으로 넘긴다.
@@ -0,0 +1,112 @@
---
id: a05fe2a6-eb7c-4bcc-a7da-58e729436468
kind: QUESTION
slug: host-memory-pressure-vs-guest-latency
title: 호스트 메모리 압박이 게스트 애플리케이션 지연을 실제로 밀어 올리는가
topic: memory-virtualization
topicName: 메모리 가상화
project: virtualization
status: 초안
questionStatus: OPEN
studio: "https://hyeonworks.com/studio/documents/a05fe2a6-eb7c-4bcc-a7da-58e729436468/edit"
sourceRevision: no-commit · 밖에서 반입한 문서 한 편. 고정할 저장소 리비전이 없다
source:
- final/document.md#83-실제-환경에서-확인할-open-question-oq-7
- final/document.md#59-host-memory-pressure와-reclaim
- final/document.md#60-host-swap이-vm에-미치는-영향
- final/document.md#62-memory-pressure와-storage-contention의-연결
---
# 호스트 메모리 압박이 게스트 애플리케이션 지연을 실제로 밀어 올리는가
게스트는 자기가 RAM 에 접근한다고 생각하는데, 그 backing page 가 호스트 RAM 에 없으면 호스트에서는 page fault 와 swap-in I/O 를 기다린 뒤에야 게스트 실행이 이어진다. 개념 문서는 그 경로가 스토리지 경합을 거쳐 애플리케이션 지연까지 이어질 수 있다고 그려 두었을 뿐 이 호스트에서 재지 않았다.
이 물음은 baseline 을 잡고 호스트에 메모리 압박을 유도한 뒤 게스트 지연을 다시 재서, 그 경로가 실제로 이어지는지 확인한다.
## 관계
- **Host 메모리 압박이 Guest 와 스토리지까지 내려가는 경로**
이 실험이 확인하려는 경로를 그 개념이 단계별로 설명한다.
- **VM 에서 page fault 는 세 계층에서 따로 일어난다**
압박 구간에서 늘어나는 fault 가 어느 계층의 것인지를 그 개념이 가른다.
- **지금 게스트와 호스트에서 swap 이 실제로 오가고 있는가**
그 물음이 잰 평상시 상태가 이 실험의 baseline 이 된다.
- **호스트 major fault 와 스토리지 지연은 같은 시간축에서 함께 움직이는가**
압박 구간에서 스토리지 지연이 오르면 그 상관을 그 물음이 따로 본다.
- **메모리 실험 결과에는 Host · VM · Workload 조건을 함께 남긴다**
세 구간 모두에 그 기준이 요구하는 조건을 남겨야 다른 환경과 견줄 수 있다.
## 사실
- §59 는 호스트 RAM 수요가 실제로 쓸 수 있는 물리 메모리에 다다르면 Linux 가 메모리 reclaim 을 시도한다고 적었다.
회수 가능한 캐시와 페이지를 먼저 처리하고, 필요하면 anonymous memory 를 스왑으로 내리고, 그래도 부족하면 심각한 압박이나 OOM 으로 갈 수 있는 순서다.
- §59 는 file-backed clean page 와 anonymous page 를 갈라 적었다.
clean file-backed page 는 원본이 스토리지에 있으므로 RAM 에서 버렸다가 필요할 때 다시 읽을 수 있다. 힙이나 스택 같은 anonymous memory 는 원본을 다시 읽을 수 없어서 스왑 같은 backing 이 필요할 수 있다.
- §60 은 게스트 RAM backing 의 호스트 물리 페이지가 swap-out 될 수 있는 구성을 놓고 두 관점을 나란히 그렸다.
게스트 쪽에서는 Keycloak 이 메모리를 읽는 것으로 끝난다. 호스트 쪽에서는 필요한 backing page 가 RAM 에 없어 호스트 page fault, swap-in I/O, 물리 RAM 으로 복원, 게스트 실행 계속으로 바뀔 수 있다.
- §60 은 그래서 게스트 관점의 RAM 접근이 호스트에서는 스토리지 I/O 를 기다리는 상황으로 바뀔 수 있다고 적었다.
- §62 는 게스트와 호스트가 동시에 메모리 압박을 겪으면 게스트 스왑 I/O · 호스트 스왑 I/O · 데이터베이스 I/O · filesystem writeback 이 한 물리 NVMe 로 몰릴 수 있다고 그렸다.
이어지는 사슬은 호스트 메모리 압박에서 reclaim 과 스왑으로, 거기서 스토리지 I/O 증가와 스토리지 경합으로 간다. 그 다음이 데이터베이스 지연 증가와 애플리케이션 지연 증가다.
- §62 는 CPU 사용률이 낮다고 해서 메모리나 스토리지 문제가 없는 것은 아니라고 밝혔다.
- §83 OQ-7 은 실험 개념을 다섯 단계로 적었다.
Baseline
게스트 애플리케이션 지연 측정
호스트 메모리 압박 유도
호스트 reclaim/swap 관측
게스트 지연 재측정
- §83 OQ-7 은 같은 구간에 CPU 와 스토리지도 동시에 관측하라고 덧붙였다.
- 개념 문서는 호스트 메모리 압박을 어떤 방법으로 유도하는지 적지 않았다. 압박의 크기와 지속 시간도 적혀 있지 않다.
- 이 호스트에서 게스트 애플리케이션 지연을 잰 기록이 개념 문서에 없다.
## 가정
- 호스트에 메모리 압박을 만들었다가 되돌릴 수 있다고 본다. 되돌린 뒤 상태가 baseline 과 같아지는지는 세 번째 구간에서 확인한다.
- 게스트 애플리케이션 지연을 세 구간에서 같은 방법으로 잴 수 있다고 전제한다. 같은 요청 부하를 세 번 거는 것이 이 구성에서 가능한지는 해 보기 전에 알 수 없다.
- 압박 구간에서 reclaim 이나 스왑이 실제로 돌 만큼 압박을 줄 수 있다고 보고 실험을 짠다. 어느 정도가 그 지점인지는 이 호스트에서 확인되지 않았다.
- 세 구간 사이에 게스트 워크로드와 가상 머신 구성이 바뀌지 않는다고 두고 세 기록을 견준다.
- 호스트와 게스트의 시계가 맞아 네 종류 지표를 같은 시간축에 놓을 수 있다고 본다.
## 미지수
- 압박을 유도했을 때 이 호스트에서 reclaim 과 스왑이 실제로 도는지.
- 돈다면 같은 구간의 게스트 애플리케이션 지연이 baseline 과 얼마나 다른지.
- 그 변화가 CPU 쪽 지표가 아니라 메모리와 스토리지 쪽 지표와 같은 방향으로 움직이는지. §62 는 CPU 사용률이 낮아도 메모리나 스토리지 문제가 있을 수 있다고 적었다.
- 호스트 압박을 유도하는 방법. 개념 문서가 적지 않아 실행하는 쪽이 정하고 무엇을 썼는지 남겨야 한다.
- 압박을 걷은 뒤 게스트 지연이 baseline 으로 돌아오는지, 돌아온다면 얼마나 걸리는지.
## 제약
- 세 구간 모두에 §85 가 요구한 호스트 · VM · 워크로드 조건을 남긴다. 조건을 남기지 않으면 이 결과를 다른 환경에 다시 쓸 수 없다.
- 게스트 쪽 스왑은 「지금 게스트와 호스트에서 swap 이 실제로 오가고 있는가」와 같은 방법으로 찍는다. 두 물음의 값이 같은 방식으로 남아야 나란히 놓을 수 있다.
- 압박을 유도한 상태로 운영 실험을 겹쳐 돌리지 않는다. 같은 스토리지를 쓰는 다른 실험이 있으면 시간을 나눈다.
- 지연이 올랐다는 관측만으로 원인을 호스트 메모리로 확정하지 않는다. 같은 구간의 CPU 와 스토리지 지표를 함께 놓고 §86 의 분류로 계층을 가른다.
- 압박의 허용 범위를 정하는 일은 이 물음 밖이다. 여기서는 경로가 이어지는지만 본다.
- 이 실험을 순서에서 앞당기지 않는다. §84 의 권장 실험 순서에서 압박 실험은 열두 단계 가운데 열 번째이고, 앞의 다섯 단계가 호스트와 가상 머신 조건을 채워 두므로 먼저 돌리면 세 구간에 남길 조건을 그때 다시 모아야 한다.
## 선택지
### 1. 세 구간을 한 번에 돌리고 네 종류 지표를 같이 남긴다
baseline, 압박, 압박 해제 세 구간에서 게스트 지연 · 호스트 vmstat · 스토리지 지연 · CPU 를 같은 시각에 기록한다. §83 OQ-7 이 적은 순서 그대로이고, 세 구간이 한 표에 들어가면 지연 변화가 어느 지표와 함께 움직였는지 그 표에서 읽힌다.
압박을 유도하는 방법을 먼저 정해야 하고, 게스트에 같은 부하를 세 번 거는 준비가 필요하다.
### 2. 압박 없이 baseline 만 먼저 여러 번 잰다
같은 워크로드로 게스트 지연을 몇 번 재서 평상시 변동 폭을 먼저 잡는다. 압박 구간의 지연 변화가 그 변동 폭 안인지 밖인지 가릴 기준이 생긴다.
이 순서만으로는 이 물음이 닫히지 않는다. 압박 구간이 없으면 확인할 경로가 시작되지 않기 때문이다.
### 3. 호스트 swappiness 를 바꿔 가며 지연을 비교한다 — 제외
압박을 유도하는 대신 설정을 바꿔 스왑이 도는 정도를 조절하는 방법이다. 지금 필요한 답은 이 구성에서 경로가 이어지는지 하나인데, 설정을 바꾸면 baseline 과 압박 구간이 서로 다른 구성에서 나온 값이 된다. 설정을 어떻게 둘지는 경로가 이어진다는 것이 확인된 뒤의 결정이다.
## 다음 검증
1. baseline 구간에서 게스트 애플리케이션 지연과 호스트 vmstat 1, 스토리지 지연, CPU 를 같은 시각에 기록한다.
2. 호스트에 메모리 압박을 유도하고, 무엇으로 어느 정도의 압박을 얼마나 오래 걸었는지 함께 적는다.
3. 압박 구간에서 같은 네 가지를 다시 기록한다. 게스트 쪽 스왑은 「지금 게스트와 호스트에서 swap 이 실제로 오가고 있는가」와 같은 방법으로 찍는다.
4. 압박을 걷고 세 번째 구간을 같은 방법으로 찍는다.
5. 세 구간 모두에 호스트 · VM · 워크로드 조건을 남긴다.
닫는 조건 : 압박 구간에서 호스트 reclaim 이나 스왑이 돌았는데도 게스트 지연이 baseline 과 다르지 않으면, 이 구성에서는 그 정도의 압박이 게스트까지 오지 않는다고 적고 닫는다. 지연이 오르면 세 구간 표가 Case 가 되고 이 물음은 그 Case 가 닫는다. 압박을 어디까지 허용할지 — swappiness 를 바꿀지, 가상 머신 배치를 바꿀지, ballooning 을 쓸지 — 는 그 Case 가 나온 뒤 Decision 으로 넘긴다.
@@ -0,0 +1,102 @@
---
id: 50730203-df5f-4604-8535-7e93ab6fb724
kind: QUESTION
slug: host-thp-policy
title: 이 호스트의 THP 정책과 huge page 상태는 무엇인가
topic: memory-virtualization
topicName: 메모리 가상화
project: virtualization
status: 초안
questionStatus: OPEN
studio: "https://hyeonworks.com/studio/documents/50730203-df5f-4604-8535-7e93ab6fb724/edit"
sourceRevision: no-commit · 밖에서 반입한 문서 한 편. 고정할 저장소 리비전이 없다
source:
- final/document.md#83-실제-환경에서-확인할-open-question-oq-4
- final/document.md#53-thp-transparent-huge-pages
- final/document.md#56-thp와-hugetlb-비교
---
# 이 호스트의 THP 정책과 huge page 상태는 무엇인가
THP(Transparent Huge Pages, 투명한 대형 페이지)는 커널이 조건이 맞는 메모리 영역에 Huge Page 를 알아서 활용하려는 기능이다. 그 활용 범위를 정하는 정책 값이 커널과 배포판, 호스트 설정에 따라 다르다 보니, 개념 문서는 값을 적지 않고 실제 시스템에서 읽으라고만 했다.
이 물음은 그 값을 읽는 데서 끝난다. 정책이 always 인지 madvise 인지 never 인지, 그리고 huge page 항목 넷의 값이 호스트와 두 게스트에 대해 적히면 닫힌다.
§83 이 적은 열린 물음 열넷 가운데 확인 명령이 함께 적힌 것은 아홉이고 OQ-4 가 그 아홉에 든다. 명령이 없는 다섯은 전부 구간을 나눠 견주는 실험이고, 이 물음은 명령 두 줄의 출력으로 닫힌다.
## 관계
- **Huge Page 를 VM 에서 볼 때 갈라지는 세 자리**
게스트 단계와 호스트 backing 을 따로 읽어야 한다는 설명이 이 물음을 호스트와 게스트로 나눠 찍는 이유다.
- **가상 머신 RAM 이 HugeTLB 로 명시적으로 backing 되어 있는가**
여기서 읽은 HugePages_Total 이 그 물음의 입력이 된다.
- **메모리 실험 결과에는 Host · VM · Workload 조건을 함께 남긴다**
THP policy 가 그 기준이 요구하는 호스트 조건 목록에 들어 있다.
## 사실
- §53 은 THP 를 Linux 가 가능한 메모리 영역에 Huge Page 를 투명하게 활용하려는 기능으로 적었다.
애플리케이션이 일반 malloc()/mmap() 을 부르면 커널이 조건이 맞을 때 Huge Page 활용을 시도하는 경로다.
- §53 은 상태 확인 명령으로 cat /sys/kernel/mm/transparent_hugepage/enabled 를 들고 출력 예로 always [madvise] never 를 적었다.
대괄호가 붙은 값이 지금 정책이다.
- §53 은 현재 정책이 커널과 배포판, 호스트 설정에 따라 다르므로 실제 시스템에서 확인한다고 밝혔다.
값을 문서에서 옮겨 올 수 없다는 뜻이고, 이 물음이 있는 이유다.
- §56 은 호스트 확인 명령으로 두 줄을 들었다.
grep -i huge /proc/meminfo
cat /sys/kernel/mm/transparent_hugepage/enabled
- §56 은 AnonHugePages 와 HugePages_Total 이 같은 뜻이 아니라고 못 박았다.
같은 표에서 THP 는 커널이 알아서 하는 활용, HugeTLB 는 명시적으로 잡아 두는 풀로 갈라 적었다.
- §83 OQ-4 는 확인할 것으로 다섯을 적었다.
THP policy
AnonHugePages
HugePages_Total
HugePages_Free
Hugepagesize
- 이 호스트에서 그 다섯을 읽은 기록이 개념 문서에 없다. 게스트 쪽 값도 없다.
## 가정
- 호스트에 붙어 sysfs 파일과 /proc/meminfo 를 읽을 수 있다고 본다.
- 두 명령의 출력이 읽는 시점의 상태라고 본다. 그 뒤에 값이 바뀌지 않는다는 근거는 개념 문서에 없으므로 읽은 시각을 함께 남긴다.
- 게스트 커널도 같은 두 파일을 제공한다고 보고 같은 명령을 게스트에서도 찍는다. 게스트 배포판에 그 파일이 실제로 있는지는 확인하지 않았다.
## 미지수
- 이 호스트의 THP 정책이 always 인지 madvise 인지 never 인지.
- AnonHugePages · HugePages_Total · HugePages_Free · Hugepagesize 의 실제 값.
- HugeTLB 풀이 잡혀 있는지. HugePages_Total 이 0 이면 없는 것이고, 0 이 아니면 그 풀을 누가 쓰는지는 이 물음이 답하지 않는다.
- 두 가상 머신 안에서 같은 다섯 항목이 어떻게 보이는지, 그리고 호스트 값과 다른지.
## 제약
- 값을 읽는 데서 끝낸다. 정책을 바꾸거나 풀을 새로 잡는 일은 이 물음에 들어 있지 않다.
- 호스트와 게스트 값을 한 줄에 합쳐 적지 않는다. §52 가 게스트의 page-size 선택과 호스트 backing 을 하나의 동일한 설정으로 취급하지 말라고 적었다.
- AnonHugePages 와 HugePages_Total 을 같은 값으로 읽지 않는다. §56 이 둘을 구분했다.
- 이 호스트에서 잰 값이 없어 다른 장비의 기본 정책을 이 호스트의 값으로 삼지 않는다.
## 선택지
### 1. 호스트 다섯 항목만 먼저 읽는다
명령 두 줄이면 끝나고, 그 다섯 값이 §85 가 요구하는 호스트 조건 가운데 THP policy 칸을 바로 채운다. 실험을 시작하기 전에 한 번 찍어 두는 용도로 충분하다.
게스트 쪽 정책은 남는다. HugeTLB 쪽으로 넘어갈 때 게스트 값을 다시 받으러 붙어야 한다.
### 2. 호스트와 두 게스트를 한 번에 읽는다
같은 두 명령을 호스트에서 한 번, 각 게스트에서 한 번씩 찍어 세 벌을 만든다. §52 가 요구한 구분이 값으로 남고, 게스트가 madvise 인데 호스트가 always 인 것 같은 차이도 세 벌을 나란히 놓으면 바로 보인다.
게스트에 접속해야 하고, 두 가상 머신이 같은 시각에 켜져 있어야 한다.
### 3. 배포판 기본값을 적어 두고 넘어간다 — 제외
정책 값을 조사하는 대신 배포판이 보통 쓰는 기본값을 적는 방법이다. §53 이 정책은 커널과 배포판, 호스트 설정에 따라 다르니 실제 시스템에서 확인하라고 적었으므로, 이 방법으로는 이 물음이 닫히지 않는다.
## 다음 검증
1. 호스트에서 cat /sys/kernel/mm/transparent_hugepage/enabled 를 찍고 대괄호가 붙은 값을 정책으로 적는다.
2. 같은 시각에 호스트에서 grep -i huge /proc/meminfo 를 찍어 AnonHugePages · HugePages_Total · HugePages_Free · Hugepagesize 를 그대로 옮긴다.
3. 같은 두 명령을 가상 머신마다 따로 찍고 호스트 값과 나란히 적는다.
4. 실행한 명령과 출력, 찍은 시각을 함께 증거로 남긴다.
닫는 조건 : 다섯 항목의 값이 호스트와 각 게스트에 대해 적히면 닫는다. HugePages_Total 이 0 이 아니면 그 풀을 가상 머신이 쓰고 있는지는 「가상 머신 RAM 이 HugeTLB 로 명시적으로 backing 되어 있는가」가 받는다. 정책이 always 로 나오고 지연에 민감한 워크로드를 돌리고 있으면 §54 가 든 compaction 영향을 측정할지는 Decision 으로 넘긴다. 이 물음 자체는 정책 값을 확정하는 데서 끝난다.
@@ -0,0 +1,91 @@
---
id: 380d4975-3be5-451d-aede-2e24c5a2a09e
kind: QUESTION
slug: numa-remote-access-vs-workload-latency
title: NUMA remote access 가 이 작업의 지연을 실제로 바꾸는가
topic: memory-virtualization
topicName: 메모리 가상화
project: virtualization
status: 초안
questionStatus: OPEN
studio: "https://hyeonworks.com/studio/documents/380d4975-3be5-451d-aede-2e24c5a2a09e/edit"
sourceRevision: no-commit · 밖에서 반입한 문서 한 편. 고정할 저장소 리비전이 없다
source:
- final/document.md#83-실제-환경에서-확인할-open-question-oq-12
- final/document.md#74-local-memory와-remote-memory
- final/document.md#77-guest-numa
---
# NUMA remote access 가 이 작업의 지연을 실제로 바꾸는가
NUMA(Non-Uniform Memory Access, 비균일 메모리 접근)는 어느 CPU 가 어느 RAM 에 접근하느냐에 따라 비용이 달라질 수 있는 구조다. 배치가 어긋나 있다는 것과 그 어긋남 때문에 느려진다는 것은 다른 확인이다.
개념 문서는 remote access 가 local access 와 같은 비용이라고 가정할 수 없다고까지 적었는데, 얼마나 다른지는 적지 않았다. 단순 토폴로지만 보고 성능 문제라고 단정하지 말라는 단서도 같은 항목에 달렸다. 이 물음은 이 호스트에서 같은 워크로드를 local 배치와 remote 위주 배치로 각각 돌려 두 값을 견주는 데까지 간다.
§83 의 열린 물음 열넷 가운데 둘은 이 주제로 올리지 않고 CPU 가상화 쪽 물음에 합쳤다. 노드 수와 vCPU 배치는 한 번 읽으면 닫히고 그 물음이 이미 같은 것을 묻고 있어서다. 이 물음은 합치지 않았는데, 토폴로지를 아는 것과 지연이 달라지는 것이 한 번의 측정으로 함께 닫히지 않기 때문이다.
## 관계
- **NUMA 에서는 vCPU 배치와 메모리 배치를 함께 본다**
local 배치와 remote 배치가 무엇으로 갈리는지를 그 개념이 설명한다.
- **QEMU 메모리는 vCPU 가 도는 NUMA node 와 같은 node 에 있는가**
지금 배치가 어떤지는 그 물음이 먼저 적는다. 이 실험은 그 위에서 배치를 일부러 바꿔 견준다.
- **이 호스트의 NUMA 토폴로지는 가상 머신 성능을 고려해야 할 구조인가**
node 가 하나면 이 실험은 열리지 않는다.
- **메모리 실험 결과에는 Host · VM · Workload 조건을 함께 남긴다**
두 구간 모두에 남길 조건을 그 기준이 정한다.
## 사실
- remote access 는 local access 와 동일한 비용이라고 가정할 수 없으며, 추가 지연과 대역폭 비용이 있을 수 있다.
- 큰 가상 머신에서는 게스트에게 NUMA 토폴로지 자체를 노출할 수 있고, 가능하면 게스트가 인식하는 토폴로지와 실제 호스트 배치가 합리적으로 맞물리도록 구성할 수 있다. 개념 문서가 든 예는 노드마다 vCPU 여덟과 RAM 32 GiB 를 둔 가상 머신이고, 이 프로젝트의 가상 머신이 그 크기인지는 적혀 있지 않다.
- 개념 문서가 적은 실험 순서는 local 배치로 baseline 을 잡고 지연과 처리량과 메모리 지표를 받은 뒤, remote 위주 배치로 바꿔 동일 워크로드를 다시 돌려 견주는 것이다.
- 같은 항목이 NUMA node 가 2개 이상인 경우에만 우선순위를 높이라고 적었다.
- 단순 토폴로지만 보고 성능 문제라고 단정하지 않는다는 단서도 같은 항목에 있다.
- 개념 문서는 이 비교에 쓸 워크로드도, 지연과 처리량을 재는 명령도 적지 않았다. 실험 순서만 적혀 있다.
- 이 호스트에서 두 배치를 각각 구성해 본 기록이 없다.
## 가정
- 호스트가 다중 NUMA node 이고 배치를 두 가지로 만들 수 있다고 보고 실험을 짠다.
- 같은 워크로드를 두 번 돌렸을 때 배치 말고 다른 조건이 바뀌지 않는다고 전제한다.
- 두 구간의 차이가 측정 오차보다 크면 배치 때문이라고 읽는다. 오차 범위를 이 호스트에서 재 본 적은 없어서, 그 범위는 baseline 을 여러 번 돌려 정해야 한다.
- Keycloak 처럼 지금 쓰고 있는 작업이 메모리 접근에 민감한지는 확인하지 않았고, 민감하지 않으면 두 배치의 차이가 지표에 나오지 않을 수 있다.
## 미지수
- local 배치와 remote 위주 배치에서 같은 워크로드의 지연과 처리량이 다른지, 다르다면 얼마나 다른지.
- 이 가상 머신들이 게스트에게 NUMA 토폴로지를 노출한 구성인지. 개념 문서에 적혀 있지 않다.
- 어떤 워크로드로 견줄지. 개념 문서는 동일 워크로드라고만 적었다.
- remote 위주 배치를 이 환경에서 어떤 방법으로 만드는지.
- 차이가 나왔을 때 그것이 이 프로젝트가 실제로 돌리는 작업에서도 같은 크기로 나타나는지.
## 제약
- node 가 하나로 확정되면 우선순위를 낮추고 이 실험을 열지 않는다.
- 지금 배치가 적히기 전에는 열지 않는다. 무엇이 local 이고 무엇이 remote 위주인지 정하려면 현재 분포가 먼저 있어야 한다.
- 두 구간 모두에 Host · VM · Workload 조건을 남긴다. 조건 없이 남긴 비교는 다른 환경에서 다시 쓰기 어렵다.
- 토폴로지만 보고 결론을 적지 않는다. 두 구간의 값이 없으면 이 물음은 닫히지 않는다.
## 선택지
### 1. 같은 워크로드를 두 배치에서 돌려 값을 견준다
local 배치에서 지연과 처리량과 메모리 지표를 받고, remote 위주로 바꿔 같은 워크로드를 같은 조건으로 다시 돌린다. 개념 문서가 적은 순서 그대로이고, 차이가 나든 나지 않든 그 값이 다음 판단의 근거가 된다.
배치를 바꾸는 방법을 먼저 정해야 하고, 두 실행 사이에 다른 조건을 고정하는 데 손이 간다.
### 2. 지금 배치 그대로 지표만 받아 둔다 — 제외
배치를 건드리지 않고 현재 상태에서 지연과 처리량을 재 두자는 방법이다.
비교할 다른 배치가 없어서 그 값이 높은지 낮은지 판단할 근거가 없다. 개념 문서가 단순 토폴로지만 보고 단정하지 말라고 한 것도 이 때문이다.
## 다음 검증
1. node 수와 현재 배치가 각각 적힌 뒤에 연다.
2. local 배치로 맞춘 구성에서 같은 워크로드를 돌려 지연과 처리량과 메모리 지표를 기록한다.
3. remote 위주 배치로 바꾸고 같은 워크로드를 같은 조건으로 다시 돌린다.
4. 두 구간 모두에 Host · VM · Workload 조건을 남긴다.
5. 배치를 바꾸는 데 쓴 방법과 지표를 받은 명령을 함께 적는다. 개념 문서에 없는 것이라 실행한 쪽이 정한다.
닫는 조건 : 두 배치의 지연과 처리량이 측정 오차 안에서 다르지 않으면 이 워크로드에서는 NUMA locality 가 우선순위가 아니라고 적고 닫는다. 차이가 나면 그 비교표가 Case 가 되고, vCPU pinning 과 memory binding 을 운영 구성으로 채택할지는 그 Case 가 나온 뒤 Decision 으로 넘긴다. 단일 NUMA node 로 나오면 개념 문서가 적은 대로 우선순위를 낮추고 닫는다.
@@ -0,0 +1,100 @@
---
id: 1b59e6de-16f1-42b2-81bb-01d6198e34bf
kind: QUESTION
slug: qemu-memory-numa-placement
title: QEMU 메모리는 vCPU 가 도는 NUMA node 와 같은 node 에 있는가
topic: memory-virtualization
topicName: 메모리 가상화
project: virtualization
status: 초안
questionStatus: OPEN
studio: "https://hyeonworks.com/studio/documents/1b59e6de-16f1-42b2-81bb-01d6198e34bf/edit"
sourceRevision: no-commit · 밖에서 반입한 문서 한 편. 고정할 저장소 리비전이 없다
source:
- final/document.md#83-실제-환경에서-확인할-open-question-oq-11
- final/document.md#75-vcpu와-numa의-연결
- final/document.md#76-vcpu-pinning만으로는-numa-최적화가-끝나지-않는다
- final/document.md#78-numa는-실제-장비-topology부터-확인한다
---
# QEMU 메모리는 vCPU 가 도는 NUMA node 와 같은 node 에 있는가
NUMA(Non-Uniform Memory Access)는 어느 CPU 가 어느 RAM 에 닿느냐에 따라 접근 비용이 달라지는 구조를 말한다. 게스트의 vCPU 는 호스트에서 QEMU 의 vCPU 스레드이고, 그 스레드를 어느 논리 CPU 에 올릴지는 호스트 스케줄러가 정한다. 그 가상 머신의 메모리를 실제로 떠받치는 호스트 쪽 페이지가 어느 노드에 있는지는 그것과 따로 정해진다. 둘이 다른 노드로 갈리면 게스트 안에서는 평범한 memory load 로 보이는 동작이 실제 하드웨어에서는 노드 사이 interconnect 를 건넌다.
이 물음이 받는 것은 그 어긋남이 성능을 바꾸는지가 아니다. 이 호스트의 가상 머신마다 vCPU 배치와 메모리 배치가 지금 어디에 놓여 있는지를 값으로 적는 데까지다.
## 관계
- **NUMA 에서는 vCPU 배치와 메모리 배치를 함께 본다**
두 배치를 왜 따로 볼 수 없는지를 그 개념이 설명한다.
- **이 호스트의 NUMA 토폴로지는 가상 머신 성능을 고려해야 할 구조인가**
노드가 몇 개인지는 그 물음이 받는다. 다중 노드라는 답이 나온 뒤에 이 물음을 연다.
- **NUMA remote access 가 이 작업의 지연을 실제로 바꾸는가**
여기서 어긋남을 찾으면 그것이 지연까지 바꾸는지는 그쪽이 받는다.
- **메모리 실험 결과에는 Host · VM · Workload 조건을 함께 남긴다**
배치를 적을 때 함께 남길 조건을 그 기준이 정한다.
## 사실
- 게스트 vCPU 는 호스트에서 QEMU 의 vCPU 스레드이고, 그 스레드는 호스트 Linux 스케줄러를 거쳐 호스트 논리 CPU 에서 실행된다.
- 어떤 가상 머신의 vCPU 스레드가 Node 0 의 CPU 에서 도는데 그 가상 머신의 호스트 쪽 physical backing page 가 Node 1 에 있으면 remote access 가 생길 수 있다. 게스트 안에서는 그것도 단순한 memory load 로 보인다.
- vCPU 를 특정 노드의 CPU 에 pinning 해도 메모리가 다른 노드에 주로 배치되어 있으면 pinning 이후에도 remote memory access 가 많아질 수 있다. 그래서 vCPU 배치와 메모리 배치를 함께 본다.
- 개념 문서가 이상적인 예로 든 구성은 한 가상 머신의 vCPU 넷이 Node 0 의 CPU 에 붙고 그 가상 머신의 메모리 backing 도 Node 0 RAM 인 경우다.
- 개념 문서는 이 확인에 쓸 명령을 적어 두었다.
QEMU 프로세스별 메모리 분포 : numastat -p <QEMU_PID>
vCPU 배치 : virsh vcpupin <VM_NAME> 와 virsh vcpuinfo <VM_NAME>
장비 토폴로지 : lscpu 와 numactl --hardware
- 같은 문서의 확인 항목은 numastat 결과를 vCPU 배치와 나란히 놓고 vCPU 와 메모리가 같은 노드인지 다른 노드인지 가르라고 적었다.
- 같은 문서는 vCPU 배치를 따로 묻는 항목도 두고, 그 확인을 CPU 가상화 SSOT 의 pinning/overcommit 관측과 연결한다고 적었다. 그래서 이 주제는 그 물음을 다시 세우지 않았다. vCPU 배치는 CPU 가상화 쪽 물음이 받고 여기서는 메모리 분포와 둘의 어긋남을 받는다.
- 개념 문서의 권장 실험 순서도 vCPU placement 확인을 여덟째에, QEMU NUMA memory distribution 확인을 아홉째에 두어 앞뒤를 갈라 놓았다.
- 이 호스트에서 numastat 을 QEMU 프로세스에 돌린 기록이 없다. vCPU 배치를 적어 둔 기록도 없다.
## 가정
- 호스트가 다중 NUMA 노드라고 보고 이 실험을 짠다. 노드 수 자체는 CPU 가상화 쪽 물음이 받는다.
- 두 가상 머신이 모두 떠 있는 동안 QEMU 프로세스를 가상 머신마다 가려낼 수 있다고 본다.
- 관측하는 동안 vCPU 스레드가 다른 노드의 CPU 로 옮겨 다니지 않는다고 전제한다. pinning 이 걸려 있지 않으면 이 전제가 깨질 수 있고, 옮겨 다니는지는 CPU 가상화 쪽에서 따로 묻고 있다.
- numastat 이 보고하는 노드별 분포가 그 가상 머신의 게스트 RAM backing 을 대표한다고 본다. QEMU 프로세스에는 게스트 RAM 말고 다른 할당도 들어 있다.
## 미지수
- 각 가상 머신의 QEMU 메모리가 노드별로 얼마씩 나뉘어 있는지.
- 그 분포가 한 노드로 모여 있는지, 두 노드에 걸쳐 있는지.
- vCPU 스레드가 도는 노드와 메모리가 몰린 노드가 같은지 다른지.
- 두 가상 머신이 같은 노드를 함께 쓰고 있는지.
- 지금 구성에서 memory binding 을 걸 수 있는지. 개념 문서는 두 배치를 함께 보라고만 적었고 이 환경에서 binding 을 바꾸는 방법은 적지 않았다.
## 제약
- 노드 수를 여기서 다시 재지 않는다. 단일 노드로 확정되면 이 물음은 이 환경에 적용되지 않는다.
- 배치를 바꾸는 일은 이 물음에 들어 있지 않다. 지금 놓여 있는 상태를 적는 것까지다.
- 두 값은 같은 시각에 받아 적는다. 시각이 어긋나면 스케줄러가 vCPU 스레드를 옮긴 뒤의 배치를 앞서 찍은 메모리 분포와 견주게 된다.
- 이 호스트에서 잰 값이 없으므로 다른 장비의 NUMA 배치를 근거로 삼지 않는다.
## 선택지
### 1. 가상 머신마다 메모리 분포와 vCPU 배치를 한 번에 받아 적는다
QEMU 프로세스마다 numastat -p 를 돌리고, 같은 시각에 virsh vcpuinfo 와 virsh vcpupin 으로 vCPU 배치를 받아 두 값을 한 표에 넣는다. 어긋남이 있으면 그 표에 그대로 드러나고, 없으면 없다는 것도 같은 표로 남는다.
### 2. 부하를 준 상태에서 한 번 더 받는다
idle 상태의 배치만 보면 메모리가 아직 실제로 할당되지 않은 구간을 볼 수 있다. 게스트에서 workload 를 돌린 뒤 같은 두 값을 다시 받으면 실제로 쓰이는 메모리가 어느 노드에 잡히는지까지 나온다.
실행이 두 번으로 늘고 어느 workload 를 쓸지 먼저 정해야 하는데, 그 선택이 결과를 바꾸기 때문에 workload 조건을 함께 적는다.
### 3. 게스트 안에서 numactl 로 확인한다 — 제외
게스트에서도 NUMA 를 볼 수 있으니 게스트 안에서 확인하자는 방법이다.
게스트가 보는 토폴로지는 가상 머신에 노출된 것이고 이 물음이 찾는 것은 호스트 쪽 physical backing 이 어느 노드에 있느냐이므로, 게스트 쪽 값으로는 그 배치를 알 수 없다.
개념 문서는 큰 가상 머신에서 게스트에게 NUMA 토폴로지 자체를 노출하고 게스트 노드와 호스트 배치가 대응되도록 구성할 수 있다고 적어 두었다. 이 프로젝트의 가상 머신이 그런 구성인지는 그 문서에 없어서, 게스트 값이 호스트 배치를 어디까지 반영하는지도 재기 전에는 모른다.
## 다음 검증
1. 호스트가 다중 NUMA 노드라는 확인을 CPU 가상화 쪽 물음에서 먼저 받는다.
2. 가상 머신마다 QEMU 프로세스를 찾아 numastat -p <QEMU_PID> 로 노드별 메모리 분포를 찍는다.
3. 같은 시각에 virsh vcpuinfo <VM_NAME> 와 virsh vcpupin <VM_NAME> 로 vCPU 배치를 적는다.
4. 두 값을 가상 머신마다 한 표로 나란히 놓고, 노드가 같은지 갈리는지 적는다.
5. Host · VM · Workload 조건을 같은 기록에 남긴다.
닫는 조건 : 노드별 메모리 분포와 vCPU 배치가 가상 머신마다 한 표로 적히면 닫는다. 둘이 같은 노드로 모여 있으면 개념 문서가 경고한 어긋남이 이 환경에는 없다고 적고 닫는다. 어긋나 있으면 그 표가 Case 가 되고, 그 어긋남이 지연까지 바꾸는지는 「NUMA remote access 가 이 작업의 지연을 실제로 바꾸는가」가 받는다. memory binding 을 걸지 말지는 그 뒤 Decision 으로 넘긴다. 단일 NUMA 노드로 나오면 이 물음은 이 환경에 적용되지 않는다고 적고 닫는다.
@@ -0,0 +1,111 @@
---
id: fa5b3782-9fcf-4113-8f51-a55c8023b2db
kind: QUESTION
slug: qemu-resident-memory-distribution
title: QEMU 프로세스가 실제로 붙잡고 있는 호스트 메모리는 얼마이고 어떻게 나뉘어 있는가
topic: memory-virtualization
topicName: 메모리 가상화
project: virtualization
status: 초안
questionStatus: OPEN
studio: "https://hyeonworks.com/studio/documents/fa5b3782-9fcf-4113-8f51-a55c8023b2db/edit"
sourceRevision: no-commit · 밖에서 반입한 문서 한 편. 고정할 저장소 리비전이 없다
source:
- final/document.md#83-실제-환경에서-확인할-open-question-oq-3
- final/document.md#40-qemu는-guest-ram을-어떻게-준비하는가
- final/document.md#41-kvm_set_user_memory_region
- final/document.md#42-configured-memory와-실제-physical-ram-사용량은-같지-않을-수-있다
---
# QEMU 프로세스가 실제로 붙잡고 있는 호스트 메모리는 얼마이고 어떻게 나뉘어 있는가
게스트 RAM 은 QEMU(Quick Emulator, 가상 머신을 실행하는 호스트 userspace 프로그램) 프로세스의 주소 공간 안에 마련된다고 §40 이 적었다. 그래서 「이 가상 머신이 호스트 메모리를 얼마나 쓰고 있는가」는 그 프로세스가 지금 얼마나 큰지를 읽는 물음이 된다.
이 물음은 실행 중인 가상 머신마다 QEMU 프로세스가 호스트에 얼마나 resident 한지, 그 값이 설정한 메모리(configured memory)와 얼마나 벌어져 있는지, 그리고 그 backing 이 anonymous 인지 huge page 인지를 적는다. 이 호스트에서 그 값을 읽은 기록은 없다.
## 관계
- **Guest 메모리 주소가 물리 RAM 에 닿기까지 — GVA · GPA · HPA**
QEMU 가 마련한 호스트 주소 공간이 게스트 물리 주소와 어떻게 이어지는지를 그 기록이 설명한다.
- **이 호스트의 가상 머신들은 설정한 메모리와 지금 잡고 있는 메모리가 얼마나 다른가**
같은 접속에서 값을 받는다. 그쪽이 적는 설정 값을 옆에 놓아야 여기서 벌어짐을 적을 수 있다.
- **가상 머신 RAM 이 HugeTLB 로 명시적으로 backing 되어 있는가**
여기서 huge page 항목이 보이면 그 물음으로 넘긴다.
- **메모리 실험 결과에는 Host · VM · Workload 조건을 함께 남긴다**
여기서 읽는 값은 VM 묶음의 메모리 backing 설정과 짝이 되므로 그 기준을 따라 남긴다.
## 사실
§40 은 QEMU 를 호스트 userspace 프로세스로 두고, QEMU 자신도 호스트 가상 주소 공간을 가지며 게스트 RAM 을 떠받치는 메모리도 그 안에 마련된다고 적었다. QEMU 가 물리 주소 X 부터 8 GiB 를 달라고 RAM 하드웨어를 직접 제어하는 것은 아니라고 같은 절이 못 박았다.
같은 절은 QEMU 메모리도 일반 호스트 프로세스 메모리처럼 관리된다고 적었다. QEMU 의 호스트 가상 주소에서 호스트 페이지 테이블을 지나 호스트 물리 주소로 간다.
§41 은 QEMU 가 마련한 호스트 userspace 메모리 영역이 게스트 GPA 의 어느 범위를 떠받치는지를 KVM 에 등록한다고 적고, 대표 ioctl 로 KVM_SET_USER_MEMORY_REGION 을 들었다. 역할은 셋으로 갈린다. QEMU 는 게스트 RAM 을 위한 호스트 userspace backing 을 내주고, KVM 은 게스트의 메모리 영역과 가상화 매핑을 관리하며, 실행 중의 주소 변환은 CPU 가 한다.
§42 는 설정한 메모리와 게스트가 현재 실제 사용하는 메모리, 호스트에서 현재 resident 한 물리 메모리 셋이 같지 않을 수 있다고 적었다. 그 차이를 만드는 것으로 호스트의 demand paging, backing 종류, HugeTLB, memory locking, preallocation, overcommit 정책을 들었다.
§83 의 OQ-3 은 확인 명령으로 ps -ef | grep qemu 와 ps -o pid,rss,vsz,cmd -p <QEMU_PID> 를 적었다. 필요하면 cat /proc/<QEMU_PID>/status 와 cat /proc/<QEMU_PID>/smaps_rollup 을 보고, 설정한 메모리와 RSS/anonymous/huge-page 상태를 비교하라고 했다.
§42 를 이 호스트에서 재는 물음은 §83 에 둘로 나뉘어 있다. 설정 값과 게스트 사용량은 virsh 와 게스트 안에서 읽는 OQ-2 가 받고, 호스트 프로세스가 실제로 얼마나 붙잡고 있는지는 OQ-3 인 이 물음이 받는다. 어디서 읽는지가 달라 한 물음으로 묶지 않았다. §84 의 권장 실험 순서도 가상 머신 설정 값 확인과 게스트 free/meminfo 확인을 둘째·셋째에 두고 QEMU RSS/HVA backing 상태 확인을 넷째에 두었다.
ps 가 내는 rss 는 RSS(Resident Set Size, 프로세스가 지금 호스트 물리 메모리에 올려 둔 크기)이고 vsz 는 VSZ(Virtual Size, 그 프로세스 가상 주소 공간의 크기)다. 개념 문서는 두 열의 뜻을 따로 풀어 적지 않았다.
## 가정
실행 중인 가상 머신마다 QEMU 프로세스를 하나씩 찾을 수 있다고 전제한다. §40 이 QEMU 를 호스트 프로세스로 서술했지만 이 호스트에서 프로세스 목록을 확인한 기록은 없다.
ps -ef | grep qemu 의 출력에서 가상 머신 이름을 읽어 프로세스와 가상 머신을 짝지을 수 있다고 전제한다. 명령줄에 그 이름이 실려 있지 않으면 짝짓기를 다른 방법으로 해야 한다.
smaps_rollup 을 읽을 권한이 있다고 전제한다. 다른 사용자의 프로세스면 항목이 비어 나올 수 있다.
값을 한 번 찍으면 그 시점의 상태로 충분하다고 전제한다. resident 크기는 게스트가 메모리를 더 건드리면 올라가기 때문에, 한 번 찍은 값은 그 순간의 크기다.
## 미지수
각 가상 머신의 QEMU 프로세스가 지금 호스트에서 얼마나 resident 한가.
그 프로세스의 가상 주소 공간 크기는 얼마이고 resident 크기와 얼마나 차이가 나는가.
두 값이 그 가상 머신에 설정한 메모리와 얼마나 벌어져 있는가.
그 backing 이 anonymous 인가 huge page 인가.
## 제약
이 호스트에서 QEMU 프로세스의 크기를 읽은 값이 없다. §40 의 8 GiB 와 §42 의 16 GiB 는 설명을 위한 예시이므로 이 환경의 값으로 옮겨 쓰지 않는다.
설정한 메모리를 옆에 놓지 않으면 벌어짐을 적을 수 없다. 그 값은 「이 호스트의 가상 머신들은 설정한 메모리와 지금 잡고 있는 메모리가 얼마나 다른가」가 받는다.
§42 가 게스트 사용량과 호스트 resident 를 다른 값으로 갈라 놓았기 때문에, resident 크기 하나로는 게스트가 그 메모리를 지금 쓰고 있는지 알 수 없다.
huge page 항목이 보이더라도 그것이 THP(Transparent Huge Pages, 커널이 조건이 맞는 메모리 영역에 큰 페이지를 자동으로 쓰는 기능)로 붙은 것인지 HugeTLB 로 명시 구성된 것인지는 여기서 닫지 않는다. 그 구분은 HugeTLB backing 을 묻는 물음이 받는다.
## 선택지
### 1. ps 두 명령만으로 먼저 표를 채운다
ps -ef | grep qemu 로 프로세스를 찾고 ps -o pid,rss,vsz,cmd -p <QEMU_PID> 로 가상 머신마다 한 줄을 적는다. 명령이 둘뿐이라 짧고, 설정 값과 견주는 데 필요한 숫자는 이 실행에서 다 나온다.
backing 이 anonymous 인지 huge page 인지는 나오지 않는다. 그 항목이 필요해지면 한 번 더 붙어야 한다.
### 2. status 와 smaps_rollup 까지 같은 실행에서 읽는다
§83 이 「필요하면」으로 둔 두 명령을 처음부터 함께 돌려 anonymous 와 huge page 항목까지 한 번에 적는다. HugeTLB 쪽 물음으로 넘길지 여부가 이 실행에서 정해진다.
출력이 길어서 어느 값을 표에 옮길지 미리 정해 두어야 한다. 정하지 않으면 파일만 쌓이고 표는 채워지지 않는다.
### 3. 게스트 안에서 본 사용량으로 대신한다 — 제외
게스트의 free -h 를 읽어 그 값을 호스트가 잡고 있는 크기로 삼자는 방법이다. 접속 한 번으로 끝난다.
§42 가 게스트 사용량과 호스트 resident 를 서로 다른 값으로 갈라 놓았으므로 한쪽으로 다른 쪽을 대신할 수 없다. 게스트 사용량은 설정한 메모리와 지금 쓰는 메모리를 묻는 물음이 이미 받고 있다.
## 다음 검증
1. ps -ef | grep qemu 로 실행 중인 QEMU 프로세스의 PID 를 찾고 가상 머신 이름과 짝짓는다 (§83 OQ-3).
2. 프로세스마다 ps -o pid,rss,vsz,cmd -p <QEMU_PID> 를 찍는다.
3. cat /proc/<QEMU_PID>/status 와 cat /proc/<QEMU_PID>/smaps_rollup 을 남겨 anonymous 와 huge page 항목을 읽는다.
4. 같은 접속에서 설정한 메모리와 지금 쓰는 메모리를 묻는 물음의 값을 옆에 놓고 벌어짐을 적는다.
5. 남기는 조건은 메모리 실험 조건 기준을 따른다.
닫는 조건 : 가상 머신마다 설정 값 · RSS · VSZ 와 anonymous/huge-page 구성이 한 표에 적히면 닫는다. RSS 가 설정 값에 크게 못 미치면 §42 가 말한 차이를 이 호스트에서 확인한 것이 되므로, 주소 변환 개념 기록의 확인 사례로 넣는다. huge page backing 이 보이면 HugeTLB backing 을 묻는 물음으로 넘긴다.
@@ -0,0 +1,99 @@
---
id: d3e8501f-e1b5-4f8f-aa9a-89f9c89a308e
kind: QUESTION
slug: swap-activity-in-guest-and-host
title: 지금 게스트와 호스트에서 swap 이 실제로 오가고 있는가
topic: memory-virtualization
topicName: 메모리 가상화
project: virtualization
status: 초안
questionStatus: OPEN
studio: "https://hyeonworks.com/studio/documents/d3e8501f-e1b5-4f8f-aa9a-89f9c89a308e/edit"
sourceRevision: no-commit · 밖에서 반입한 문서 한 편. 고정할 저장소 리비전이 없다
source:
- final/document.md#83-실제-환경에서-확인할-open-question-oq-6
- final/document.md#63-swap-used만-보고-장애를-판단하면-안-된다
- final/document.md#61-guest-swap과-host-swap
---
# 지금 게스트와 호스트에서 swap 이 실제로 오가고 있는가
Swap Used 가 2 GiB 로 나와도 그것이 지금 메모리 압박이 심하다는 뜻은 아니다. 그 값이 과거에 swap-out 된 cold page 때문에 커져 있을 수도 있어서, §63 은 값이 얼마인가 대신 지금 swap-in/out 이 지속되는가를 물으라고 적었다. 이 물음은 그 질문을 이 호스트와 두 게스트에서 같은 시각에 던진다. 게스트 swap 과 호스트 swap 은 서로 다른 경로이므로 한쪽만 보고 다른 쪽을 짐작하지 않는다.
## 관계
- **Host 메모리 압박이 Guest 와 스토리지까지 내려가는 경로**
게스트 swap 과 호스트 swap 이 왜 다른 경로인지를 그 개념이 설명한다.
- **VM 에서 page fault 는 세 계층에서 따로 일어난다**
호스트 쪽 swap-in 은 호스트 page fault 로 시작하고, 그 계층이 게스트 page fault 와 다르다.
- **호스트 메모리 압박이 게스트 애플리케이션 지연을 실제로 밀어 올리는가**
압박을 유도하는 실험은 여기서 잰 평상시 상태를 기준값으로 쓴다.
- **호스트 major fault 와 스토리지 지연은 같은 시간축에서 함께 움직이는가**
§63 이 함께 보라고 든 넷 가운데 major fault 와 storage latency 를 그 물음이 받는다.
- **메모리 증상 하나로 계층을 단정하지 않는다**
Swap Used 값 하나로 판정하지 않는다는 것이 그 기준의 사례다.
## 사실
- §63 은 Swap Used = 2 GiB 라는 값만으로 지금 메모리 압박이 심하다고 단정할 수 없다고 적었다. 과거에 swap-out 된 cold page 가 남아 있을 수도 있기 때문이다.
- §63 은 더 중요한 질문으로 넷을 들었다.
현재 swap-in/out 이 지속되는가
reclaim pressure 가 증가하는가
major fault 가 증가하는가
storage latency 가 같이 증가하는가
- §63 은 게스트와 호스트를 동시에 확인해야 한다고 적고 확인 명령으로 free -h 와 vmstat 1 을 들었다.
- §83 OQ-6 도 게스트와 호스트 양쪽에 같은 두 명령을 적고, swap-used 값 하나보다 지금의 swap-in/out 활동과 메모리 압박을 함께 보라고 했다.
- §61 은 게스트 swap 을 게스트 애플리케이션에서 시작해 게스트 메모리 압박, 게스트 커널, 게스트 swap, /dev/vda, virtio-blk, QEMU 를 거쳐 호스트 스토리지로 내려가는 경로로 그렸다.
- §61 은 호스트 swap 을 게스트 RAM 이 QEMU 의 메모리 backing 을 거쳐 호스트 메모리 압박을 받고 호스트 커널이 호스트 swap 으로 내리는 경로로 그렸다. 같은 절이 두 경로를 같지 않다고 적고, 게스트가 메모리 여유가 있어 보이는데 호스트에서 swap 이나 reclaim 이 심할 수도 있다고 덧붙였다.
- 개념 문서는 vmstat 출력에서 어느 열을 swap-in 과 swap-out 으로 읽는지 적지 않았다.
- 이 호스트와 두 게스트에서 free -h 나 vmstat 를 찍은 기록이 개념 문서에 없다.
## 가정
- 호스트와 두 게스트에 동시에 접속해 같은 구간을 관측할 수 있다고 본다.
- 관측하는 동안 실험용 부하를 따로 걸지 않고 평상시 상태를 재는 것으로 둔다. 그 상태가 이 호스트의 대표적인 상태인지는 한 번의 관측으로 알 수 없다.
- 게스트와 호스트의 시계가 맞아 두 기록을 같은 시간축에 놓을 수 있다고 전제한다.
- 두 가상 머신 모두 swap 영역을 갖고 있다고 보고 게스트 쪽을 읽는다. 설정에 swap 이 없으면 게스트 쪽 관측은 그 사실로 끝난다.
## 미지수
- 관측 구간에서 swap-in 과 swap-out 이 실제로 오가는지, 오간다면 게스트 쪽인지 호스트 쪽인지 둘 다인지.
- Swap Used 가 0 이 아니라면 그 값이 과거에 내려간 cold page 때문인지 지금 진행 중인 swap 활동 때문인지.
- §63 이 든 나머지 셋 가운데 reclaim pressure 와 major fault 를 이 환경에서 어떤 값으로 읽는지. 그 둘을 읽는 명령은 개념 문서에 없다.
- 관측을 얼마나 오래 해야 지속 여부를 말할 수 있는지. 개념 문서는 vmstat 1 만 적고 관측 길이를 적지 않았다.
## 제약
- 게스트 값으로 호스트 상태를 말하거나 그 반대로 말하지 않는다. §61 이 두 경로를 갈라 놓았다.
같은 문서의 결론도 게스트 하나의 free -h 만 보고 메모리 상태를 판단하지 않고 Guest, QEMU, Host, NUMA, Storage 로 이어지는 영향을 같은 시간축에서 관측해야 한다고 적었다.
- Swap Used 값 하나를 결론으로 적지 않는다. §63 이 그 판단을 막았다.
- 부하를 걸어 압박을 만드는 일은 이 물음에 들어 있지 않다. 그 실험은 「호스트 메모리 압박이 게스트 애플리케이션 지연을 실제로 밀어 올리는가」가 받는다.
§84 의 권장 실험 순서가 이미 그렇게 갈라 놓았다. 게스트와 호스트 vmstat 동시 관측이 여섯째이고 memory pressure 실험은 열째, swap 과 storage latency 를 견주는 일은 열한째다. 이 물음은 여섯째까지다.
- 게스트는 가상 머신마다 따로 찍는다. 한 대의 값을 다른 한 대에 옮기지 않는다.
## 선택지
### 1. 게스트와 호스트에서 같은 구간을 동시에 관측한다
세 곳에서 free -h 를 한 번 찍어 기준을 남기고, vmstat 1 을 같은 시각에 시작해 같은 길이로 돌린다. §61 이 갈라 놓은 두 경로가 같은 시간축의 값으로 남아 한쪽만 움직이는 경우와 둘 다 움직이는 경우를 구분할 수 있다.
세 곳에 동시에 붙어야 하고 관측 길이를 먼저 정해야 한다.
### 2. 호스트만 먼저 관측한다
호스트에서 swap 이 전혀 오가지 않으면 §61 의 두 경로 중 호스트 쪽은 지금 문제가 아니라고 그 관측 하나로 정한다. 접속이 한 곳이라 반복해서 찍기 쉽다.
게스트 쪽 swap 은 호스트 값에 드러나지 않는다. 게스트 커널이 /dev/vda 로 내리는 경로라 호스트에서는 스토리지 I/O 로만 보인다. 그래서 게스트를 다시 찍어야 한다.
### 3. Swap Used 값만 세 곳에서 받아 적는다 — 제외
free -h 한 번씩으로 끝내는 방법이다. §63 이 그 값만으로 판단하지 말라고 적은 것이 이 물음의 출발점이므로 이 방법으로는 닫히지 않는다.
## 다음 검증
1. 호스트와 각 게스트에서 free -h 를 한 번씩 찍어 그 시점의 Swap Used 를 기준으로 남긴다.
2. 세 곳에서 vmstat 1 을 같은 시각에 시작해 미리 정한 길이만큼 돌리고, 출력에서 swap-in 과 swap-out 으로 읽은 열의 이름을 함께 적는다.
3. 같은 구간에서 §63 이 든 나머지 셋 가운데 읽을 수 있는 것 — reclaim pressure · major fault · storage latency — 을 어떤 명령으로 읽었는지와 함께 남긴다.
4. 세 기록을 같은 시간축에 놓고 어느 쪽에서 무엇이 움직였는지 적는다.
닫는 조건 : 관측 구간 내내 게스트와 호스트 모두 swap-in 과 swap-out 이 0 이면 지금은 swap 이 오가지 않는다고 적고 닫는다. Swap Used 가 0 이 아니어도 그렇게 적는다. 한쪽에서 swap 이 오가면 §61 의 두 경로 중 어느 쪽인지를 적고, 그 구간의 스토리지 지연과 게스트 지연을 함께 적어 「호스트 메모리 압박이 게스트 애플리케이션 지연을 실제로 밀어 올리는가」로 넘긴다.
@@ -0,0 +1,87 @@
---
id: 63aef96b-03ef-4dbd-9ba6-9e61c6e695e1
kind: QUESTION
slug: virtio-balloon-configured
title: 이 가상 머신들에 virtio-balloon 이 붙어 있는가
topic: memory-virtualization
topicName: 메모리 가상화
project: virtualization
status: 초안
questionStatus: OPEN
studio: "https://hyeonworks.com/studio/documents/63aef96b-03ef-4dbd-9ba6-9e61c6e695e1/edit"
sourceRevision: no-commit · 밖에서 반입한 문서 한 편. 고정할 저장소 리비전이 없다
source:
- final/document.md#83-실제-환경에서-확인할-open-question-oq-8
- final/document.md#65-virtio-balloon-구조
- final/document.md#64-ballooning이-필요한-이유
---
# 이 가상 머신들에 virtio-balloon 이 붙어 있는가
virtio-balloon 은 게스트 커널 쪽 드라이버와 QEMU 쪽 장치가 virtqueue 로 맞물려 동작한다. 장치가 없거나 게스트 쪽 드라이버가 올라와 있지 않으면 balloon target 을 바꾸는 실험 자체가 성립하지 않으므로, 동적 메모리 회수를 다루기 전에 이 확인이 먼저다. 개념 문서는 확인 명령까지만 적고 이 호스트의 설정은 읽지 않았다.
## 관계
- **virtio-balloon 이 Guest 메모리를 회수하고 돌려주는 방식**
드라이버와 장치가 무엇을 주고받는지를 그 개념이 설명한다. 이 물음은 그 구성이 이 호스트에 있는지만 본다.
- **balloon target 을 바꾸면 게스트가 쓸 수 있는 메모리는 어떻게 따라 움직이는가**
장치가 붙어 있다는 답이 나와야 그 실험이 시작된다.
- **이 호스트의 가상 머신들은 설정한 메모리와 지금 잡고 있는 메모리가 얼마나 다른가**
두 물음이 virsh dommemstat 을 같이 읽으므로 한 번 찍어 나눠 쓴다.
## 사실
- §64 는 호스트가 QEMU 의 게스트 RAM backing 을 볼 수 있지만 게스트 내부에서 어떤 메모리가 중요한지 완전히 알지 못한다고 적었다.
게스트는 자기 메모리를 애플리케이션 working set · JVM heap · page cache · free 로 구분해 알고 있다.
- §64 는 그래서 호스트가 무작정 게스트 backing 을 swap-out 하기보다 게스트 커널과 협력해 불필요한 메모리를 돌려받는 편이 유리할 수 있다고 적고, 대표적인 메커니즘으로 virtio-balloon 을 들었다.
- §65 는 그 구조를 게스트 커널 아래 virtio-balloon 드라이버와 virtqueue, VM 경계 건너편의 QEMU virtio-balloon 장치, 그리고 호스트 메모리 관리로 그렸다.
- §65 는 virtio-balloon 이 게스트 RAM 자체를 제공하는 장치가 아니라고 못 박았다. 이미 존재하는 게스트 RAM backing 을 호스트와 게스트가 협력해 회수하고 반환하는 데 쓰는 가상 장치다.
- §83 OQ-8 은 확인 명령으로 virsh dumpxml <VM_NAME> 을 들고, 게스트에서도 관련 드라이버나 장치 상태를 확인하라고 적었다.
- §83 OQ-8 은 환경에 따라 드라이버 이름과 표시 방식이 달라질 수 있으므로 실제 장비에서 검증하라는 단서를 달았다.
그래서 개념 문서에는 게스트 쪽에서 무엇을 찾아야 하는지가 이름으로 적혀 있지 않다.
- §83 OQ-2 는 가상 머신 메모리 확인 명령으로 virsh dominfo <VM_NAME> · virsh dumpxml <VM_NAME> · virsh dommemstat <VM_NAME> 셋을 들었다.
- 이 호스트의 가상 머신 설정에서 balloon 관련 요소를 읽은 기록이 개념 문서에 없다.
## 가정
- 두 가상 머신 모두 libvirt 로 정의되어 있어 virsh dumpxml 로 설정을 통째로 읽을 수 있다고 본다.
- 설정에 balloon 장치가 있으면 게스트 쪽에도 대응하는 드라이버가 보인다고 전제한다. 그 전제가 이 게스트 배포판에서 맞는지는 확인하지 않았다.
- 게스트에 접속해 장치 목록이나 커널 모듈 상태를 읽을 수 있다고 본다.
## 미지수
- 각 가상 머신의 libvirt 설정에 balloon 장치가 있는지.
- 있다면 게스트 안에서 그 드라이버가 실제로 올라와 있는지.
- 이 환경에서 그 드라이버나 장치가 어떤 이름으로 보이는지. 개념 문서가 환경마다 다를 수 있다고만 적고 이름을 남기지 않았다.
- 게스트 쪽 상태를 어떤 명령으로 읽는지. 개념 문서가 게스트 확인 명령을 적지 않아 실행하는 쪽이 정한다.
## 제약
- 이 물음에서 balloon target 을 움직이지 않는다. 구성 여부를 적는 것이 전부다.
- 설정에 장치가 있다는 것만으로 동작한다고 적지 않는다. §83 OQ-8 이 게스트 쪽 상태도 확인하라고 적었다.
- 설정과 드라이버가 둘 다 보여도 호스트가 backing 을 실제로 언제 회수하는지는 이 확인으로 알 수 없다. §67 이 정확한 Host-side release 동작은 QEMU/KVM 버전, backing 종류 및 설정에 따라 달라질 수 있다고 적고 그 동작을 단정하지 않았다. 개념 문서가 단정하지 않은 것을 이 물음이 대신 단정하지 않는다.
- 게스트 쪽에서 쓴 명령과 그 출력을 그대로 남긴다. 이름이 환경마다 다르므로 다음 사람이 같은 것을 찾으려면 무엇을 봤는지가 필요하다.
- 장치가 없는 것으로 나와도 그것을 결함으로 적지 않는다. 이 실험 기반에서 ballooning 을 쓰기로 한 기록이 개념 문서에 없다.
§70 은 virtio-mem 같은 다른 동적 memory 관리 방식도 존재하므로 모든 동적 VM memory 관리를 ballooning 하나로 일반화하면 안 된다고 적었다. 그래서 balloon 장치가 없다는 답은 이 환경에 동적 메모리 관리가 없다는 뜻이 아니라 이 장치가 없다는 뜻까지다.
## 선택지
### 1. 설정과 게스트 상태를 한 번에 확인한다
가상 머신마다 virsh dumpxml 을 찍어 balloon 관련 요소를 인용하고, 이어서 각 게스트에서 드라이버나 장치 상태를 읽어 실제로 보이는 이름과 함께 적는다. §83 OQ-8 이 요구한 두 확인이 한 번에 끝난다.
게스트 두 대에 접속해야 하고, 게스트 쪽 확인 명령을 실행하는 쪽이 정해야 한다.
### 2. 호스트 설정만 읽고 넘어간다
virsh dumpxml 두 번으로 끝난다. 설정에 balloon 장치가 없으면 게스트 쪽을 볼 이유가 없어 이 물음이 거기서 닫힌다.
장치가 있는 것으로 나오면 게스트 쪽 드라이버가 올라와 있는지를 확인하러 다시 가야 한다.
## 다음 검증
1. 가상 머신마다 virsh dumpxml <VM_NAME> 을 남기고 balloon 관련 요소를 그대로 인용한다.
2. 각 게스트에서 balloon 관련 드라이버나 장치 상태를 확인하고, 실행한 명령과 실제로 보인 이름을 함께 적는다.
3. 같은 실행에서 virsh dommemstat <VM_NAME> 출력도 받아 남긴다. 「이 호스트의 가상 머신들은 설정한 메모리와 지금 잡고 있는 메모리가 얼마나 다른가」가 같은 출력을 읽는다.
닫는 조건 : 설정과 게스트 쪽 상태가 둘 다 적히면 닫는다. 붙어 있지 않으면 이 환경에서는 ballooning 이 동작하지 않는다고 적고 「balloon target 을 바꾸면 게스트가 쓸 수 있는 메모리는 어떻게 따라 움직이는가」는 열지 않은 채로 둔다. 장치가 없으면 그 실험이 성립하지 않는다. 붙어 있으면 그 물음으로 넘긴다.
@@ -0,0 +1,116 @@
---
id: 67285d51-7eaf-4540-9577-cfd0b273b40e
kind: QUESTION
slug: vm-configured-vs-current-memory
title: 이 호스트의 가상 머신들은 설정한 메모리와 지금 잡고 있는 메모리가 얼마나 다른가
topic: memory-virtualization
topicName: 메모리 가상화
project: virtualization
status: 초안
questionStatus: OPEN
studio: "https://hyeonworks.com/studio/documents/67285d51-7eaf-4540-9577-cfd0b273b40e/edit"
sourceRevision: no-commit · 밖에서 반입한 문서 한 편. 고정할 저장소 리비전이 없다
source:
- final/document.md#83-실제-환경에서-확인할-open-question-oq-2
- final/document.md#42-configured-memory와-실제-physical-ram-사용량은-같지-않을-수-있다
- final/document.md#57-memory-overcommit
---
# 이 호스트의 가상 머신들은 설정한 메모리와 지금 잡고 있는 메모리가 얼마나 다른가
§42 는 가상 머신에 설정한 메모리와 게스트가 지금 실제로 쓰는 메모리, 그리고 호스트에서 지금 resident 한 물리 메모리를 서로 다른 세 값으로 갈라 놓았다. 이 물음은 그 세 값이 이 호스트에서 각각 얼마인지를 가상 머신마다 적는다.
세 값이 벌어져 있는지에 따라 다음에 무엇을 잴지가 갈린다. 설정한 총량이 호스트 RAM 을 넘으면 §57 이 서술한 overcommit 구성에 이 환경이 들어가고, 넘지 않으면 그 절의 시나리오는 여기 걸리지 않는다. 이 호스트의 물리 RAM 도 각 가상 머신에 설정한 메모리도 개념 문서에 적혀 있지 않다.
## 관계
- **Guest 메모리 주소가 물리 RAM 에 닿기까지 — GVA · GPA · HPA**
설정한 값과 resident 값이 왜 갈리는지를 그 기록이 주소 변환 경로로 설명한다.
- **Host 메모리 압박이 Guest 와 스토리지까지 내려가는 경로**
설정 총량이 호스트 RAM 을 넘는 구성에서 실제 수요가 함께 오를 때 무엇이 이어지는지를 그 기록이 다룬다.
- **QEMU 프로세스가 실제로 붙잡고 있는 호스트 메모리는 얼마이고 어떻게 나뉘어 있는가**
같은 실행에서 값을 받는다. 세 값 가운데 호스트 resident 쪽을 프로세스 단위로 재는 물음이 그쪽이다.
- **메모리 실험 결과에는 Host · VM · Workload 조건을 함께 남긴다**
여기서 남기는 값이 이후 메모리 실험의 VM 묶음이 되므로 그 기준을 따라 적는다.
## 사실
§42 는 가상 머신에 16 GiB 를 설정했다고 해서 모든 일반 구성에서 시작 순간 실제 호스트 RAM 16 GiB 가 반드시 모두 즉시 물리적으로 점유되는 것은 아니라고 적었다.
같은 절은 세 값을 나란히 놓고 서로 같지 않을 수 있다고 밝혔다.
Configured Memory
Guest 가 현재 실제 사용하는 Memory
Host 에서 현재 resident 한 Physical Memory
세 값을 갈라 놓는 요인으로 §42 가 든 것은 호스트의 demand paging, backing 종류, HugeTLB, memory locking, preallocation, overcommit 정책이다. 그래서 가상 머신 RAM 16 GiB 를 호스트 RAM 에서 고정된 연속 16 GiB 로 단순화하면 안 된다고 같은 절이 적었다.
§57 은 게스트에 설정한 메모리 총량이 호스트 물리 RAM 보다 큰 구성이 가능할 수 있는 이유를, 설정 용량과 현재 실제 working set 또는 resident 메모리가 같지 않을 수 있다는 데서 찾았다. 다만 모든 가상 머신의 실제 수요가 동시에 증가하면 문제가 발생한다고 이어 적었다.
§83 의 OQ-2 는 확인 명령을 호스트 쪽과 게스트 쪽으로 나눠 적었다. 호스트에서는 virsh dominfo <VM_NAME> 과 virsh dumpxml <VM_NAME>, virsh dommemstat <VM_NAME> 을 쓰고, 게스트에서는 free -h 와 cat /proc/meminfo 를 쓴 뒤 호스트의 QEMU 프로세스 상태와 비교한다.
이 호스트의 물리 RAM 과 각 가상 머신에 설정한 메모리를 적은 값은 개념 문서 어디에도 없다. §57 의 32 GiB 와 16 GiB, §42 의 16 GiB 는 설명을 위한 예시다.
§85 가 실험마다 함께 남기라고 적은 VM 조건에 Configured RAM 과 Current RAM 이 들어 있다. 이 물음이 내는 값은 여기서 한 번 쓰고 마는 것이 아니라 뒤따르는 메모리 실험의 조건 칸으로 그대로 들어간다.
## 가정
가상 머신들이 libvirt 로 관리되고 있어 virsh 로 값을 읽을 수 있다고 전제한다. §83 이 든 명령이 전부 virsh 인데 이 호스트에서 그 명령을 돌린 기록은 없다.
측정하는 동안 각 가상 머신이 실행 중이라고 전제한다. 꺼져 있으면 현재 메모리와 게스트 사용량이 나오지 않고 설정 값만 읽힌다.
호스트 쪽 세 명령과 게스트 쪽 두 명령을 사실상 같은 시각에 찍을 수 있다고 전제한다. 사이가 벌어지면 세 값이 서로 다른 시점의 상태가 된다.
이 호스트에 있는 가상 머신 전부를 셀 수 있다고 전제한다. 몇 대가 실행 중인지도 개념 문서에 없다.
## 미지수
이 호스트의 물리 RAM 은 얼마인가.
각 가상 머신에 설정한 메모리는 얼마이고, 그 합이 호스트 RAM 을 넘는가.
넘든 넘지 않든, 지금 각 게스트가 실제로 쓰고 있는 메모리는 얼마이고 호스트에서 그 가상 머신 몫으로 resident 한 메모리는 얼마인가.
세 값이 설정 값과 얼마나 벌어져 있는가.
## 제약
이 호스트에서 잰 값이 없다. §42 와 §57 이 든 숫자는 개념을 보이려고 든 예시이므로 이 환경의 값으로 옮겨 쓰지 않는다.
§84 의 권장 실험 순서는 가상 머신 설정 값 확인과 게스트 free/meminfo 확인을 둘째와 셋째로 나눠 적었다. 여기서는 그 둘을 한 물음으로 묶는다. 이 물음이 답할 것이 세 값의 차이라서 호스트 쪽과 게스트 쪽을 다른 시각에 찍으면 그 차이가 어느 시점의 것인지 말할 수 없다.
세 값을 서로 다른 시각에 찍으면 비교가 성립하지 않는다. 게스트 사용량은 workload 가 달라지면 같이 움직인다.
이 물음은 설정한 값과 실제 사용량의 차이를 적는 데까지다. 그 차이가 있을 때 무엇이 일어나는지는 swap 과 호스트 메모리 압박을 다루는 물음들이 받는다.
QEMU 프로세스 쪽 값은 여기서 닫지 않는다. virsh 가 보고하는 값과 프로세스가 실제로 잡고 있는 크기는 다른 관측이고, 그것은 「QEMU 프로세스가 실제로 붙잡고 있는 호스트 메모리는 얼마이고 어떻게 나뉘어 있는가」가 받는다.
## 선택지
### 1. 실행 중인 가상 머신 전부를 한 번에 찍는다
virsh list 로 실행 중인 가상 머신을 세고, 각각에 대해 호스트 세 명령과 게스트 두 명령을 같은 시각에 돌린다. 설정 총량과 호스트 RAM 을 그 자료 하나로 견줄 수 있어서 overcommit 여부가 이 실행에서 정해진다.
가상 머신이 여럿이면 명령 수가 늘어 같은 시각을 지키기 어려워진다. 그럴 때는 호스트 쪽을 먼저 한 번에 돌리고 게스트 쪽을 이어서 돌린 뒤 두 시각을 함께 적는다.
### 2. 가상 머신 하나로 표 모양을 먼저 정하고 나머지로 넓힌다
한 대에 대해 다섯 명령을 돌려 세 값을 어디서 읽는지 확정한 다음 나머지에 같은 순서를 적용한다. 값을 잘못 읽어 표를 다시 만드는 일을 줄인다.
두 번 붙어야 하고, 첫 실행과 두 번째 실행 사이에 게스트 사용량이 달라진다. overcommit 판정에 필요한 설정 값은 그 사이에 바뀌지 않으므로 판정 자체는 갈리지 않는다.
### 3. QEMU 프로세스 값까지 이번에 함께 읽는다 — 제외
호스트에 한 번 붙는 김에 ps 로 QEMU 프로세스의 크기까지 받아 적자는 방법이다. 실행 횟수는 줄어든다.
QEMU 쪽은 별도의 물음이 이미 받고 있고 그쪽은 anonymous 인지 huge page 인지까지 보기 때문에, 여기서 함께 읽으면 어느 물음의 기준으로 닫혔는지가 남지 않는다. 두 물음의 실행 시각을 맞추고 싶으면 같은 접속에서 순서대로 돌리고 각각의 기록에 남긴다.
## 다음 검증
1. virsh list 로 실행 중인 가상 머신 이름을 적는다.
2. 가상 머신마다 호스트에서 virsh dominfo <VM_NAME> 으로 configured/current memory 를, virsh dumpxml <VM_NAME> 으로 memory backing 설정을, virsh dommemstat <VM_NAME> 으로 balloon 계열 값을 남긴다 (§83 OQ-2).
3. 같은 시각에 각 게스트에서 free -h 와 cat /proc/meminfo 를 찍는다.
4. 호스트의 free -h 도 함께 남겨 물리 RAM 과 현재 여유를 적는다.
5. 남기는 조건은 메모리 실험 조건 기준을 따른다. QEMU 프로세스의 resident 값은 QEMU 쪽 물음이 받는다.
닫는 조건 : 설정 값 · 게스트 사용량 · 호스트 resident 세 값을 가상 머신마다 한 표로 적으면 닫는다. 설정 총량이 호스트 RAM 을 넘으면 이 환경이 overcommit 상태라는 사실을 확정한 것이 되고, 그 상태에서 무엇이 일어나는지는 swap 을 묻는 물음과 호스트 메모리 압박을 묻는 물음이 받는다. 넘지 않으면 §57 의 시나리오가 이 환경에 적용되지 않는다.
@@ -0,0 +1,98 @@
---
id: f460e9a2-35ef-46ff-81cf-b36627a1b231
kind: QUESTION
slug: vm-ram-backed-by-hugetlb
title: 가상 머신 RAM 이 HugeTLB 로 명시적으로 backing 되어 있는가
topic: memory-virtualization
topicName: 메모리 가상화
project: virtualization
status: 초안
questionStatus: OPEN
studio: "https://hyeonworks.com/studio/documents/f460e9a2-35ef-46ff-81cf-b36627a1b231/edit"
sourceRevision: no-commit · 밖에서 반입한 문서 한 편. 고정할 저장소 리비전이 없다
source:
- final/document.md#83-실제-환경에서-확인할-open-question-oq-5
- final/document.md#55-hugetlb
- final/document.md#52-vm에서-huge-page를-볼-때-주의할-점
---
# 가상 머신 RAM 이 HugeTLB 로 명시적으로 backing 되어 있는가
HugeTLB 는 관리자가 미리 잡아 둔 Huge Page pool 을 가상 머신이나 애플리케이션이 명시적으로 지정해 쓰는 방식이다. 이 호스트의 두 가상 머신이 그 방식으로 RAM 을 받고 있는지는 libvirt 설정 한 곳만 봐서는 끝나지 않는다. §83 OQ-5 가 설정을 읽은 뒤 호스트 /proc/meminfo, QEMU smaps 계열과 교차 검증하라고 적었기 때문이다. 세 자료가 서로 맞는지까지 확인해야 이 환경이 어느 쪽으로 backing 되어 있는지가 정해진다.
## 관계
- **Huge Page 를 VM 에서 볼 때 갈라지는 세 자리**
§52 가 나눈 세 단계 가운데 호스트 backing 쪽만 이 물음이 확정한다.
- **이 호스트의 THP 정책과 huge page 상태는 무엇인가**
HugePages_Total 과 HugePages_Free 를 그쪽이 읽는다. 그 값이 이 물음의 교차 검증 재료가 된다.
- **QEMU 프로세스가 실제로 붙잡고 있는 호스트 메모리는 얼마이고 어떻게 나뉘어 있는가**
두 물음이 같은 smaps_rollup 출력을 읽으므로 한 번 찍어 나눠 쓴다.
- **메모리 실험 결과에는 Host · VM · Workload 조건을 함께 남긴다**
memory backing 설정이 그 기준의 VM 조건 목록에 들어 있다.
## 사실
- §55 는 HugeTLB 를 명시적인 Huge Page pool 을 쓸 수 있는 Linux 메커니즘으로 적었다.
THP 는 애플리케이션이 일반 메모리 할당을 하면 커널이 알아서 Huge Page 를 활용하는 경로이고, HugeTLB 는 관리자가 풀을 준비한 뒤 애플리케이션이나 가상 머신이 명시적으로 쓰는 경로다.
- §55 는 물리 RAM 안에 일반 메모리 영역과 2 MiB 단위 HugeTLB Pool 이 나뉘어 있는 그림으로 그 풀을 그렸다.
- §55 는 사전 확보로 예측 가능성을 높일 수 있지만 일반 메모리 할당의 유연성이 감소하는 trade-off 가 있다고 밝혔다.
- §52 는 가상 머신에 translation 단계가 둘이라 "Huge Page 를 사용한다"는 말만으로는 부족하다고 적고 셋을 구분하라고 했다.
게스트 page-table 단계에서 큰 페이지를 쓰는가
호스트 backing 이 Huge Page 인가
EPT mapping 에서 큰 mapping 을 활용하는가
- §52 는 게스트와 호스트의 page-size 선택을 하나의 동일한 설정으로 취급하면 안 된다고 못 박았다.
- §83 OQ-5 는 확인 명령으로 virsh dumpxml <VM_NAME> 을 들고, libvirt memory backing 관련 설정을 확인한 뒤 호스트 /proc/meminfo, QEMU smaps 계열과 교차 검증하라고 적었다.
- §83 OQ-3 이 QEMU 프로세스 쪽 명령으로 cat /proc/<QEMU_PID>/smaps_rollup 을 들었다.
smaps 계열에서 huge page 사용량을 어느 항목 이름으로 읽는지는 개념 문서가 적지 않았다.
- 세 자료 가운데 호스트 쪽은 항목 이름이 적혀 있다. §56 이 호스트 확인 명령을 적으면서 AnonHugePages 와 HugePages_Total 은 같은 의미가 아니라고 못 박았고, §83 OQ-4 도 THP policy · AnonHugePages · HugePages_Total · HugePages_Free · Hugepagesize 를 확인 항목으로 들었다. 이름이 없는 것은 QEMU smaps 쪽 하나다.
- 이 호스트의 libvirt 설정을 읽은 기록이 개념 문서에 없다.
## 가정
- 두 가상 머신 모두 libvirt 로 정의되어 있어 virsh dumpxml 로 설정을 통째로 읽을 수 있다고 본다.
- 설정에 memory backing 관련 요소가 없으면 명시적 HugeTLB backing 을 쓰지 않는 것으로 읽는다. 그 해석이 이 libvirt 버전에서 맞는지는 확인하지 않았다.
- 세 자료를 같은 시각에 찍으면 같은 순간의 상태를 가리킨다고 전제한다.
- QEMU 프로세스 번호를 가상 머신마다 가려낼 수 있다고 본다.
## 미지수
- 각 가상 머신의 libvirt 설정에 memory backing 항목이 있는지, 있다면 HugeTLB 를 가리키는지.
- 있다면 그 요구량이 호스트 HugePages_Total 및 HugePages_Free 와 맞물리는지.
- QEMU smaps 계열에서 huge page 사용량을 어느 항목으로 읽는지. 개념 문서가 항목 이름을 적지 않아 실행하는 쪽이 정한다.
- 설정과 호스트 값이 어긋나는 상태가 이 호스트에 실제로 있는지.
## 제약
- 게스트 안에서 본 huge page 상태를 호스트 backing 의 증거로 쓰지 않는다. §52 가 두 단계를 구분하라고 적었다.
- 세 자료 중 하나만으로 결론을 적지 않는다. OQ-5 가 교차 검증을 지시했다.
- 이 물음에서 풀을 새로 잡거나 backing 설정을 바꾸지 않는다. 현재 상태를 확정하는 것이 전부다.
- §84 의 권장 실험 순서는 THP/HugeTLB 상태 확인을 다섯째 한 단계로 묶었지만 §83 은 호스트 정책을 OQ-4 로, 가상 머신 backing 을 OQ-5 로 갈라 물었다. 앞의 것은 호스트 하나에 대해 한 번 읽는 값이고 뒤의 것은 가상 머신마다 갈릴 수 있는 설정이다. 이 물음이 받는 것은 뒤쪽이고, 앞쪽 값은 「이 호스트의 THP 정책과 huge page 상태는 무엇인가」가 읽어 여기에 교차 검증 재료로 들어온다.
- 개념 문서가 smaps 항목 이름을 적지 않았으므로 실행한 명령과 출력을 그대로 남겨야 다음 사람이 같은 값을 다시 읽는다.
## 선택지
### 1. libvirt 설정부터 읽고 backing 항목이 없으면 거기서 끝낸다
virsh dumpxml 을 두 번 찍는 것으로 시작한다. 두 설정 모두 memory backing 관련 요소가 없으면 명시적 HugeTLB backing 이 아니라는 답이 거의 정해지고, 호스트 HugePages_Total 이 0 인지만 확인하면 닫힌다.
설정에 항목이 있으면 결국 세 자료를 다 받아야 하므로 호스트와 QEMU 쪽을 다시 찍으러 간다.
### 2. 세 자료를 한 번에 찍어 나란히 놓는다
설정과 호스트 /proc/meminfo, QEMU smaps_rollup 을 같은 시각에 받아 나란히 둔다. OQ-5 가 요구한 교차 검증이 한 번의 실행으로 끝나고, 설정과 실제 값이 어긋나는 경우에도 그 어긋남이 같은 시각의 자료로 남는다.
QEMU 프로세스 번호를 먼저 가려내야 하고, 두 가상 머신이 같은 시각에 켜져 있어야 한다.
### 3. 호스트 HugePages_Total 하나로 가른다 — 제외
풀이 잡혀 있지 않으면 어떤 가상 머신도 HugeTLB 로 backing 될 수 없으니 그 값 하나로 끝내자는 방법이다. 0 이 아닌 경우에는 그 풀을 쓰는 것이 이 가상 머신들인지 다른 프로세스인지 가리지 못한다. 그 구분이 이 물음이 답해야 하는 내용이다.
## 다음 검증
1. 가상 머신마다 virsh dumpxml <VM_NAME> 을 남기고 memory backing 관련 요소를 그대로 인용한다.
2. 같은 시각에 호스트에서 grep -i huge /proc/meminfo 를 찍는다.
3. 같은 시각에 각 QEMU 프로세스에 대해 cat /proc/<QEMU_PID>/smaps_rollup 을 찍고, huge page 로 읽은 항목의 이름을 함께 적는다.
4. 세 출력을 나란히 놓고 서로 맞는지, 어긋나면 어느 값이 어떻게 다른지 적는다.
닫는 조건 : 세 자료가 서로 맞으면 이 환경이 어느 쪽으로 backing 되어 있는지를 확정하고 닫는다. 설정에 backing 이 없고 HugePages_Total 도 0 이면 이 가상 머신들은 명시적 HugeTLB backing 을 쓰지 않는다고 적고 닫는다. 그 경우 남는 것은 §54 가 적은 THP 쪽 특성이고, 정책 값은 「이 호스트의 THP 정책과 huge page 상태는 무엇인가」가 읽는다. 설정과 호스트 값이 어긋나면 그 어긋남이 Case 가 된다.