System Engineering 리뷰 (1) 프로세스와 Memory

Jeongmin Yeo (Ethan)·2022년 3월 11일
2

System Engineering

목록 보기
1/2

시스템 구성정보 확인하기

시스템의 문제점을 분석하고 확인하기 위해서는 먼저 현재 시스템 구성정보를 확인할 수 있어야 한다.

여기서 말하는 정보는 현재 사용중인 커널 버전과 부팅 시 사용한 커널, 그리고 하드웨어인 CPU 와 메모리는 어떤 것들을 사용하는지에 대한 정보들이다.

이 정보들을 바탕으로 특정 커널 버그특정 하드웨어 문제를 해결할 수 있다.

커널 정보 확인하기

uname -a 옵션을 통해서 커널 정보를 확인할 수 있다.

ubuntu@ip-172-31-12-59:~$ uname -a
Linux ip-172-31-12-59 5.11.0-1022-aws #23~20.04.1-Ubuntu SMP Mon Nov 15 14:03:19 UTC 2021 x86_64 x86_64 x86_64 GNU/Linux
  • 위 서버의 커널 버전은 Linux 5.11.0-1022-aws 버전이다. 그리고 x86 계열의 64 비트 운영 체제를 사용하고 있다.

dmesg | grep -i kernel | more  를 통해 커널이 부팅할 때 나오는 디버그 메시지로 운영 중에 발생하는 메시지를 볼 수 있다.****

그리고 커널이 하드웨어를 인식하고 드라이버를 올리는 과정과 부팅시 적용된 커널 파라미터를 확인하는게 가능하다.

ubuntu@ip-172-31-12-59:~$ sudo dmesg | grep -i kernel | more
[    0.000000] KERNEL supported cpus:
[    0.000000] Netfront and the Xen platform PCI driver have been compiled for this kernel: unplug emulated NICs.
[    0.000000] Blkfront and the Xen platform PCI driver have been compiled for this kernel: unplug emulated disks.
               in your root= kernel command line option
[    0.038067] Booting paravirtualized kernel on Xen HVM
[    0.038915] Kernel command line: BOOT_IMAGE=/boot/vmlinuz-5.11.0-1022-aws root=PARTUUID=24ca9e81-01 ro console=tty1 console=ttyS0 nvme_core.io_timeout=4294967295 p
anic=-1 // (1) 
[    0.041653] Memory: 978736K/1048180K available (16393K kernel code, 3488K rwdata, 10372K rodata, 2688K init, 5968K bss, 69184K reserved, 0K cma-reserved) // (2)
[    0.041824] Kernel/User page tables isolation: enabled
[    0.882078] DMA: preallocated 128 KiB GFP_KERNEL pool for atomic allocations
[    0.885991] DMA: preallocated 128 KiB GFP_KERNEL|GFP_DMA pool for atomic allocations
[    0.889978] DMA: preallocated 128 KiB GFP_KERNEL|GFP_DMA32 pool for atomic allocations
[    2.205409] Loaded X.509 cert 'Build time autogenerated kernel key: ecb0788dc66cd3f3e8014485463fe429aa2b1eba'
[    2.220262] Loaded X.509 cert 'Canonical Ltd. Kernel Module Signing: 88f752e560a1e0737e31163a466ad7b70a850c19'
[    2.373456] Freeing unused kernel image (initmem) memory: 2688K
[    2.381969] Write protecting the kernel read-only data: 30720k
[    2.386692] Freeing unused kernel image (text/rodata gap) memory: 2036K
[    2.391819] Freeing unused kernel image (rodata/data gap) memory: 1916K
[    3.307520] systemd[1]: Listening on udev Kernel Socket.
[    3.346216] systemd[1]: Mounting Kernel Debug File System...
[    3.545140] systemd[1]: Mounting Kernel Trace File System...
[    3.611301] systemd[1]: Starting Create list of static device nodes for the current kernel...
[    3.701278] systemd[1]: Starting Load Kernel Module drm...
[    3.793261] systemd[1]: Starting Load Kernel Modules...
[22531.000664] audit: type=1400 audit(1646338108.352:40): apparmor="STATUS" operation="profile_replace" info="same as current profile, skipping" profile="unconfined"
name="snap.lxd.check-kernel" pid=23760 comm="apparmor_parser"
[22554.722873] audit: type=1400 audit(1646338132.073:72): apparmor="STATUS" operation="profile_replace" profile="unconfined" name="snap.lxd.check-kernel" pid=24330 co
mm="apparmor_parser"
  • (1) 에서 부팅 시에 사용한 커널 파라미터를 볼 수 있다.
  • (2) 에서는 부팅 할 때 커널이 인식하는 메모리 정보를 볼 수 있고 물리 메모리와 사용 가능한 메모리 등을 볼 수 있다.

CPU 정보 확인하기

리눅스에서는 dmidecode 를 통해서 하드웨어 정보를 확인할 수 있다. dmidecode 만을 이용하면 너무 많은 정보가 출력되므로 키워드와 함께 사용할 것이 권장된다.

먼저 BIOS 를 살펴보는 명령어다.

dmidecode -t bios 명령어를 통해서 bios 정보를 볼 수 있다. 주로 특정 BIOS 버전에 문제가 있다는 보고를 보고서 확인할 때 사용한다.

ubuntu@ip-172-31-12-59:~$ sudo dmidecode -t bios
# dmidecode 3.2
Getting SMBIOS data from sysfs.
SMBIOS 2.7 present.

Handle 0x0000, DMI type 0, 24 bytes
BIOS Information
	Vendor: Xen
	Version: 4.11.amazon
	Release Date: 08/24/2006
	Address: 0xE8000
	Runtime Size: 96 kB
	ROM Size: 64 kB
	Characteristics:
		PCI is supported
		EDD is supported
		Targeted content distribution is supported
	BIOS Revision: 4.11
  • 이 BIOS 는 xen 에서 만들었고 버전은 4.11.amazon 이다.

다음은 system 키워드다.

dmidecode -t system 명령을 통해 주로 모델명을 확인하는 용도로 사용한다. 모델명을 통해서 해당 장비가 어느 정도의 성능을 내는지 확인할 수 있다.

ubuntu@ip-172-31-12-59:~$ sudo dmidecode -t system
# dmidecode 3.2
Getting SMBIOS data from sysfs.
SMBIOS 2.7 present.

Handle 0x0100, DMI type 1, 27 bytes
System Information
	Manufacturer: Xen
	Product Name: HVM domU
	Version: 4.11.amazon
	Serial Number: ec28691a-0746-fbe7-e8c5-f8a4125a824e
	UUID: ec28691a-0746-fbe7-e8c5-f8a4125a824e
	Wake-up Type: Power Switch
	SKU Number: Not Specified
	Family: Not Specified

Handle 0x2000, DMI type 32, 11 bytes
System Boot Information
	Status: No errors detected
  • 이 제품의 모델은 Xen 에서 만든 HVM domU 이다.

다음은 processor 키워드다.

dmidecode -t processor 명령을 통해서 장비의 CPU 정보를 확인하는게 가능하다.

ubuntu@ip-172-31-12-59:~$ sudo dmidecode -t processor
# dmidecode 3.2
Getting SMBIOS data from sysfs.
SMBIOS 2.7 present.

Handle 0x0401, DMI type 4, 35 bytes
Processor Information
	Socket Designation: CPU 1
	Type: Central Processor
	Family: Other
	Manufacturer: Intel
	ID: F2 06 03 00 FF FB 8B 17
	Version: Not Specified
	Voltage: Unknown
	External Clock: Unknown
	Max Speed: 2400 MHz
	Current Speed: 2400 MHz
	Status: Populated, Enabled
	Upgrade: Other
	L1 Cache Handle: Not Provided
	L2 Cache Handle: Not Provided
	L3 Cache Handle: Not Provided
	Serial Number: Not Specified
	Asset Tag: Not Specified
	Part Number: Not Specified
  • 여기선 하나의 소켓이 있고 코어는 하나다.

다음 명령어를 통해서도 확인이 가능하다. /proc/cpuinfo

ubuntu@ip-172-31-12-59:~$ cat /proc/cpuinfo
processor	: 0
vendor_id	: GenuineIntel
cpu family	: 6
model		: 63
model name	: Intel(R) Xeon(R) CPU E5-2676 v3 @ 2.40GHz
stepping	: 2
microcode	: 0x46
cpu MHz		: 2399.971
cache size	: 30720 KB
physical id	: 0
siblings	: 1
core id		: 0
cpu cores	: 1
apicid		: 0
initial apicid	: 0
fpu		: yes
fpu_exception	: yes
cpuid level	: 13
wp		: yes
flags		: fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ht syscall nx rdtscp lm constant_tsc rep_good nopl xtopology cpuid tsc_known_freq pni pclmulqdq ssse3 fma cx16 pcid sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand hypervisor lahf_lm abm cpuid_fault invpcid_single pti fsgsbase bmi1 avx2 smep bmi2 erms invpcid xsaveopt
bugs		: cpu_meltdown spectre_v1 spectre_v2 spec_store_bypass l1tf mds swapgs itlb_multihit
bogomips	: 4800.04
clflush size	: 64
cache_alignment	: 64
address sizes	: 46 bits physical, 48 bits virtual
power management:

그리고 lscpu 명령을 통해서도 조회가 가능한데 이 경우에는 NUMA 아키텍처와 관련된 내용까지도 알 수 있다.

메모리 정보 확인하기

dmidecode 에서 memory 키워드로 메모리 정보를 확인할 수 있다.

ubuntu@ip-172-31-12-59:~$ sudo dmidecode -t memory
# dmidecode 3.2
Getting SMBIOS data from sysfs.
SMBIOS 2.7 present.

Handle 0x1000, DMI type 16, 19 bytes
Physical Memory Array
	Location: Other
	Use: System Memory
	Error Correction Type: Multi-bit ECC
	Maximum Capacity: 1 GB
	Error Information Handle: Not Provided
	Number Of Devices: 1

Handle 0x1100, DMI type 17, 34 bytes
Memory Device
	Array Handle: 0x1000
	Error Information Handle: 0x0000
	Total Width: 64 bits
	Data Width: 64 bits
	Size: 1024 MB
	Form Factor: DIMM
	Set: None
	Locator: DIMM 0
	Bank Locator: Not Specified
	Type: RAM
	Type Detail: None
	Speed: Unknown
	Manufacturer: Not Specified
	Serial Number: Not Specified
	Asset Tag: Not Specified
	Part Number: Not Specified
	Rank: Unknown
	Configured Memory Speed: Unknown
  • 여기서는 Physical Memory Array 와 Memory Device 로 나눠서 나오는데 Physical Memory Array 는 NUMA 아키텍처에 따라서 하나의 CPU 소켓에 할당된 로컬 메모리를 말한다. 그리고 Memory Device 는 시스템에 꽂혀있는 메모리들을 말하고. 여기서는 하나의 소켓과 하나의 메모리가 꽂혀져 있어서 Physical Memory Array 와 Memory Device 가 여러개 나오진 않는다.

디스크 정보 확인하기

df -h 명령을 통해서 디스크 정보를 확인하는게 가능하다.

ubuntu@ip-172-31-12-59:~$ df -h
Filesystem      Size  Used Avail Use% Mounted on
/dev/root        30G  3.7G   26G  13% /
devtmpfs        479M     0  479M   0% /dev
tmpfs           485M     0  485M   0% /dev/shm
tmpfs            97M  932K   96M   1% /run
tmpfs           5.0M     0  5.0M   0% /run/lock
tmpfs           485M     0  485M   0% /sys/fs/cgroup
/dev/loop0       25M   25M     0 100% /snap/amazon-ssm-agent/4046
/dev/loop1       56M   56M     0 100% /snap/core18/2253
/dev/loop3       68M   68M     0 100% /snap/lxd/21835
/dev/loop2       62M   62M     0 100% /snap/core20/1242
tmpfs            97M     0   97M   0% /run/user/1000
/dev/loop5       56M   56M     0 100% /snap/core18/2284
/dev/loop6       62M   62M     0 100% /snap/core20/1361
/dev/loop7       44M   44M     0 100% /snap/snapd/14978
/dev/loop8       27M   27M     0 100% /snap/amazon-ssm-agent/5163
/dev/loop9       68M   68M     0 100% /snap/lxd/22526
  • 여기서는 여러개의 파티션들이 마운트 되어 있는 것들을 볼 수 있다. 가장 대표적으로 /dev/root 파일 시스템으로 디스크가 네이밍 되어 있고 총 30G 를 저장할 수 있다고 한다. 그 중 3.7G 를 사용했고 26G 를 더 사용할 수 있다.
  • 여기서는 나오지 않지만 디스크의 Filesystem 영역이 각각 다를 수 있는데 /dev/sda ,/dev/hda/dev/vda 등 다양할 수 있다.

네트워크 정보 확인하기

ethtool eth0 명령을 통해서 연결 상태를 확인하는게 가능하다.

ubuntu@ip-172-31-12-59:~$ ethtool eth0
Settings for eth0:
Cannot get wake-on-lan settings: Operation not permitted
	Link detected: yes
  • 네트워크 연결이 정상적으로 되어 있다는 걸 확인할 수 있다.
  • 원래는 speed 프로퍼티를 통해서 현재 연결되어있는 네트워크 속도를 알 수 있고 네트워크가 보낼 수 있는 속도는 Supoorted link modes
    와 Advertised link modes
    를 통해서 볼 수 있다.

그리고 ethtool -g eth0 명령을 통해 Ring Buffer 의 크기를 확인할 수 있고 최적화를 할 수 있다.

Ring Buffer 는 케이블을 통해서 들어온 패킷이 가장 먼저 복사되는 곳으로 네트워크 카드에 있는 버퍼 공간이다.

이 영역이 작다면 네트워크 성능 저하를 일으킬 수 있다.
ethtool -G eth0 {영역} {값} (ethtool -G eth0 rx 255) 이런 식으로 G 옵션을 통해서 값을 설정할 수 있다.
ethtool -i eth0 옵션을 통해 네트워크 카드가 어떤 커널 드라이버를 사용하는지, 버전이 몇인지를 알 수 있다.

top 을 통해 살펴보는 프로세스 정보들

리눅스에서는 시스템의 상태를 살펴볼 수 있는 다양하 명령들이 있는데 그 중에선 top 이 전반적으로 가장 빠르게 확인할 수 있다.

여기서는 top 으로 시스템의 상태를 전반적으로 파악하는 방법과 특히 프로세스와 관련된 값들의 의미가 어떤게 있는지 알아보겠다.

top 명령을 입력하면 다음과 같은 정보를 볼 수 있다.

옵션 없이 입력하면 주어진 Interval (기본 3초) 간격으로 화면을 갱신하면서 보여준다.

  • 순간의 top 정보를 확인하기 위해서는 -b 옵션을 사용하면 된다.

나오는 정보는 다음과 같다.

top - 15:54:16 up 7 days, 2:01,  1 user,  load average: 0.00, 0.00, 0.00
Tasks: 115 total,   1 running, 114 sleeping,   0 stopped,   0 zombie
%Cpu(s):  0.0 us,  0.0 sy,  0.0 ni, 99.7 id,  0.0 wa,  0.0 hi,  0.0 si,  0.3 st
MiB Mem :    968.9 total,    135.8 free,    371.4 used,    461.8 buff/cache
MiB Swap:      0.0 total,      0.0 free,      0.0 used.    444.3 avail Mem

PID USER      PR  NI    VIRT    RES    SHR S  %CPU  %MEM     TIME+ COMMAND
  1 root      20   0  168808  11184   6776 S   0.0   1.1   0:18.18 systemd
  2 root      20   0       0      0      0 S   0.0   0.0   0:00.00 kthreadd
  • 현재 서버의 시간과 서버가 얼마나 구동되었는지
  • 시스템의 Load Average 는 어느정도 인지 (Load Average 는 이후에 설명하겠다. 간략하게만 말하면 이 수치가 높으면 서버가 많은 일을 하고 있다고 생각하면 된다.)
  • 현재 시스템에서 구동 중인 프로세스의 개수와 상태들
  • CPU, Mem, Swap 의 사용량들
  • 그리고 각 프로세스의 상세한 정보인 PID, 메모리 사용률, 상태, CPU 점유 시간 등의 내용이 나온다.
    • PR : 프로세스의 실행 우선순위.
    • NI : PR 에 부여할 가산점. NI 와 PR 을 더해서 실제 프로세스의 우선순위가 결정된다.
    • VIRT : 프로세스가 사용하는 Virtual Memory 의 전체 용량을 가리킨다.
    • RES : 현재 프로세스가 사용하고 있는 실제 메모리의 양을 가리킨다.
    • SHR : 다른 프로세스와 공유하고 있는 메모리를 나타낸다. 리눅스의 경우에 공통으로 사용하는 라이브러리 같은게 있는데 이게 이 메모리의 영역이 될 수 있다.
    • 여기에 있는 메모리 정보들로 프로세스에 메모리 누수가 발생했는지 알 수 있다.
    • S : 프로세스의 상태를 나타낸다. CPU 를 사용하고 있는 중인지, I/O 를 기다리고 있는지, 아니면 아무 작업도 하지 않는 유휴 상태인지 나타낸다.
  • 프로세스의 상태는 다음과 같다.
    • S: sleeping. S 는 D 와 유사하지만 시그널을 주면 언제든지 실행할 수 있다.
    • D: Uninterruptible sleep. 디스크 혹은 네트워크 I/O 가 걸려있는 상태를 말한다.
    • R: running. 실행 중인 프로세스로 실제로 CPU 를 먹고 있는 상태다.
    • T: traced or stopped. trace 등으로 프로세스의 시스템 콜을 추적하고 있는 상태다.
    • Z: zombie. 좀비 프로세스로 부모 프로세스에 의해서 회수되지 못한 자식 프로세스가 남겨져 있는 상태다. 좀비 프로세스의 문제는 적은 리소스를 메모리에서 계속 가지고 있는 문제와 PID 를 점유하고 있는 문제가 있다.****

VIRT 와 RES 그리고 Memory Commit

malloc() 과 같은 메모리 할당을 호출하는 시스템 콜을 필요로 하는 함수를 호출한다면 RES 가 높아질 것이라고 생각하지만 그렇지 않다. VIRT 만 올라간다.

실제로 메모리에 쓰기 작업이 일어나는 시점에 메모리가 할당되고 RES 가 올라갈 것이다.

가상의 메모리만 처음에 할당 받고 실제로 쓰기 작업을 했을 때 Page Fault 가 일어난다. 그리고 그제서야 메모리를 할당한다. 이 일련의 과정을 Memory Commit 이라고 한다.

  • 이런 정보는 커널 내의 전역변수인 Page Table 에서 모두 관리한다.

Memory Commit 이 필요한 이유는 COW (Copy-On-Write) 라는 기법을 위해서 필요하다.

그리고 VIRT 도 한도 끝도 없이 올라가는게 아니라 실제 물리 메모리와 관련이 있다. 실제로 사용하고 있는 물리 메모리가 없다면 Swap 을 사용하게 되거나 OOM 으로 프로세스를 죽이는 방법으로 메모리를 확보하게 된다.

Load Average 와 시스템 부하

Load Average 의 정의가 뭘까?

이는 man proc 을 통해서 확인할 수 있다.

The first three fields in this file are load average figures giving the number of jobs in the run queue (state R) or waiting for disk I/O (state D) average over 1, 5, and 15 minutes

즉 run queue 에 있는 CPU 를 받기 위해 대기중인 프로세스의 수와 I/O 작업이 끝나기를 기다리고 있는 프로세스의 수를 합한 값을 1분 5분 15분 단위로 나타낸 것을 말한다.

이 값은 프로세스의 수를 세는 것이기 때문에 CPU Core 의 수가 몇 개냐에 따라 각각 의미하는 바가 다르다. 상대적이다.

예로 Load Average 가 2 이고 run queue 에 두 개의 프로세스가 대기중이며 CPU 코어가 하나다. 이 경우에는 한 개의 프로세스는 작업을 처리할 수 없다.

하지만 이 경우에 CPU 코어의 수를 늘린다면 같은 Load Average 값이더라도 모든 프로세스를 다 실행할 수 있다. 이 경우에는 문제가 되지 않는다.

그리고 같은 Load Average 값이더라도 CPU 를 원하는 프로세스인지 I/O 를 원하는 프로세스인지는 알 지 못한다. 두 값을 합한 것이니까.

그렇다면 I/O 를 원하는지 CPU 를 원하는지 알려면 어떻게 해야할까? 이는 vmstat 으로 알 수 있다.

vmstat 을 사용할 때 출력되는 r 값과 b 값에 주목해서 구별하면 된다.

r 은 실행되기를 기다리고 있거나 현재 실행하고 있는 프로세스의 개수륾 말하는 거며 b 는 I/O 를 위해 대기열에 있는 프로세스의 개수를 말한다.

이렇게 CPU 가 병목인지 I/O 가 병목인지 알았다면 이제 각 문제를 해결하면 된다.

CPU 가 병목인 경우

먼저 사용자 프로그램이 병목인지, 시스템 프로그램이 병목인지 확인하자. 이는 top 이나 sar 명령으로 확인이 가능하다.

그리고 ps 명령으로 어떤 프로세스가 CPU 를 얼마나 차지하고 있는지 확인하는게 가능하다.

이렇게 프로세스를 찾은 후에는 좁혀서 분석해야한다. 주로 로그를 심어놨다면 로그를 통해서 확인하는게 가능하다.

또 다른 방법이라면 strace 나 oprofile 로 병목지점을 좁혀볼 수 있다.

  • strace 는 프로세스가 호출한 시스템 콜을 추적하는게 가능하다.
  • oprofile 는 어떤 함수가 cpu 를 많이 사용하는지 추적하는게 가능하다.

I/O 가 병목인 경우

I/O 가 병목인 경우에는 입출력이 많아서 병목인지, 스왑영역을 사용해서 병목인지 알아야 한다.

sar 이나 vmstat 으로 스왑을 사용하는지 살펴보자.

스왑영역을 쓰고 있다면 특정 프로세스가 메모리를 독차지 하고 있을 수 있으므로 ps 명령어로 찾아보자.

메모리를 많이 쓰고 있는 사용자 프로세스가 있다면 메모리 누수가 있는지 확인해봐야 한다. 그렇지 않다면 메모리를 증설해야 할 수도 있다.

입출력이 빈번하게 발생하고 있다면 캐시서버를 통해서 입출력 자체를 줄이거나 알고리즘 개선으로 줄이는 방법이 있을 수 있고 블라킹 되지 않게 리액티브 프로그래밍을 이용하거나 코루틴을 적용해볼 수 있다.

free 명령이 숨기고 있는 것들

메모리가 부족하다면 프로세스는 더 이상 작업을 할 수 없고 이는 시스템 장애나 응답 속도가 느려지는 현상을 일으킬 수 있다.

그렇기 때문에 메모리가 어떻게 사용되고 있는지를 파악하는 것은 CPU 사용률과 Load Average 만큼 중요한 포인트다.

여기서는 메모리 상태를 전체적으로 빠르게 살펴 볼 수 있는 free 명령어와 free 만으로 살펴볼 수 없는 정보는 어떻게 볼 수 있는지 살펴보겠다.

다음은 free -m 명령의 출력 결과다.

ubuntu@ip-172-31-12-59:~$ free -m
              total        used        free      shared  buff/cache   available
Mem:            968         371         135           0         462         443
Swap:             0           0           0
  • -m : 이 옵션을 통해서 출력되는 메모리 양은 MB 단위로 출력한다. -b 를 주면 byte 단위, -k 를 주면 KB 단위 -g 를 주면 GB 단위로 표시된다.
  • total: 현재 시스템에 설치되어있는 전체 메모리양을 의미한다.
  • used: 시스템에서 사용하고 있는 메모리양을 의미한다.
  • free: 시스템에서 아직 사용하고 있지 않은 메모리 양을 의미한다. 그러므로 애플리케이션이 사용할 수도, 커널이 사용할 수도 있다.
  • shared: 프로세스 사이에 공유하고 있는 메모리양이다.
  • buffred: 버퍼 용도로 사용하고 있는 메모리 영역을 말하며 시스템의 성능 향상을 위해서 커널에서 사용하고 있는 영역이다.
  • cached: 페이지 캐시라고 불리는 캐시 영역에 있는 메모리양을 의미한다. 페이지 캐시는 디스크 블록을 캐싱해놓음으로써 I/O 작업의 성능향상을 위해서 사용된다.
  • 그리고 -/+ buffers/cached 가 출력되는 경우도 있는데 이는 메모리 사용량에서 bufferd 와 cached 를 제외하고, 사용하고 있는 영역과 사용하지 않는 영역을 표시해준다.
  • Swap: Swap 의 전체 영역과 실제로 사용하고 있는 영역 그리고 사용하지 않은 영역을 표시해준다.****

Buffers 와 cached 영역

커널이 블록 디바이스라고 불리는 디스크에서 데이터를 읽어올 때는 상당히 느리다. 그래서 이를 통해 시스템 부하가 일어나기도 한다.

그래서 커널은 상대적으로 느린 디스크 영역을 좀 더 빠르게 하기 위해서 캐싱 영역으로 한번 읽은 파일은 Page cache 인 cached 영역에 저장하고 여기서 읽어 오도록 한다.

파일의 내용이 아닌 파일 시스템을 관리하기 위한 메타 데이터 (super block, inode block) 을 읽어올 때는 Buffer 영역을 사용한다.

그리고 이전에 메모리에서 buffer 과 cached 영역을 제외하고 보여주는 부분이 있는데 이 이유는 이 영역의 경우에는 프로세스가 메모리를 더 필요로 하는 경우에 언제든지 해제될 수 있는 영역이기 때문이다.****

/proc/meminfo 읽기

free 명령은 전체 시스템이 사용하고 있는 메모리와 가용 메모리를 빠르게 읽을 수 있지만 시스템의 메모리 전체 사용량을 알려주지는 않는다.

자세하게 보고 싶다면 /proc/meminfo 파일을 읽으면 된다.

ubuntu@ip-172-31-12-59:~$ cat /proc/meminfo
MemTotal:         992204 kB
MemFree:          138264 kB
MemAvailable:     454700 kB
Buffers:           37596 kB
Cached:           384688 kB
SwapCached:            0 kB
Active:           310688 kB
Inactive:         384112 kB
Active(anon):       1868 kB
Inactive(anon):   274412 kB
Active(file):     308820 kB
Inactive(file):   109700 kB
Unevictable:       23064 kB
Mlocked:           18528 kB
SwapTotal:             0 kB
SwapFree:              0 kB
Dirty:                16 kB
Writeback:             0 kB
AnonPages:        295616 kB
Mapped:            68360 kB
Shmem:               956 kB
KReclaimable:      51116 kB
Slab:              94424 kB
SReclaimable:      51116 kB
SUnreclaim:        43308 kB
KernelStack:        3712 kB
PageTables:         3976 kB
NFS_Unstable:          0 kB
Bounce:                0 kB
WritebackTmp:          0 kB
CommitLimit:      496100 kB
Committed_AS:    1668184 kB
VmallocTotal:   34359738367 kB
VmallocUsed:       19556 kB
VmallocChunk:          0 kB
Percpu:            13632 kB
HardwareCorrupted:     0 kB
AnonHugePages:         0 kB
ShmemHugePages:        0 kB
ShmemPmdMapped:        0 kB
FileHugePages:         0 kB
FilePmdMapped:         0 kB
HugePages_Total:       0
HugePages_Free:        0
HugePages_Rsvd:        0
HugePages_Surp:        0
Hugepagesize:       2048 kB
Hugetlb:               0 kB
DirectMap4k:      110592 kB

여기서는 전부 보지말고 중요한 부분만 살펴보자.

  • SwapCached: swap 으로 빠진 메모리 영역 중 다시 메모리로 돌아온 영역을 말한다. swap 으로 한번 메모리가 빠졌어도 메모리가 확보되면 다시 돌아올 수 있다. 그리고 커널은 한번 swap 이 되면 다시 swap 이 될 가능성이 많아서 swap 영역에 있는 메모리는 메모리로 돌아올 때도 삭제되지는 않는다. 이를 통해 I/O 를 조금이나마 줄일 수 있기 떄문에.
  • Active(anon): anon 은 anonymous 로 Page cache 영역을 제외한 메모리 영역을 말한다. active 는 최근까지 메모리를 사용하고 있어서 swap 영역으로 넘어가지 않는 영역을 뜻한다.
  • inactive(anon): swap 영역으로 넘어갈 수 있는 anon 영역을 말한다.
  • Active(file): buffers 와 cached 영역을 포함한 영역이고 active 이므로 최근에 참조해서 swap 영역으로 넘어가지 않는다.
  • inactive(file): swap 영역으로 넘어갈 수 있는 buffers 와 cached 영역을 말한다.
  • Dirty: I/O 성능 향상을 위해 커널이 캐시 목적으로 사용하는 영역으로 그 중 쓰기 작업의 영역을 말한다. 커널은 I/O 작업으로 쓸 때 바로 블록 디바이스로 명령을 내리지 않고 이 영역에 모아서 한 번에 쓴다.

slab 메모리 영역

/proc/meminfo 에서 아직 설명하지 않은 영역이 있는데 slab 영역들이다.

이 영역들은 커널이 내부적으로 사용하는 영역을 뜻한다.

주로 I/O 작업을 더 빠르게 하기 위해서 inode cache, dentry cache 등에 사용하거나 네트워크 소켓을 위한 메모리 영역을 확보하는 작업들을 한다.

inode_cache 는 파일의 inode 에 대한 정보를 지정해두는 캐시라면 dentry 는 디렉터리의 계층 관계를 저장해두는 캐시다.

즉 dentry 는 ls 명령으로 디렉터리를 살펴보기만 해도 값이 증가한다. 만약 파일에 자주 접근하고 디렉터리의 생성/삭제가 빈번한 시스템이라면 Slab 메모리가 늘어날 수 있다.

/proc/meminfo 에 있는 영역 중 slab 과 관련된 영역은 다음과 같다.

  • Slab: 메모리 영역 중 커널이 직접 사용하고 있는 영역을 말한다.
  • SReclaimable: Slab 영역 중 캐시용도로 사용하고 있는 영역이며 메모리 부족 현상이 일어나면 프로세스에게 할당될 수 있는 영역이다.
  • SUnreclaim: 커널이 현재 사용중인 영역을 말하며 해제할 수 없는 영역이다.

그리고 추가로 말하는건데 Slab 메모리는 buffers/cached 영역에 포함되지 않고 free 명령으로 조회했을 때 used 에 포함된다.

swap, 메모리 증설의 포인트

여기서는 메모리가 부족하다는 걸 어떻게 알 수 있는지, 메모리가 부족하면 어떤 일이 일어나는지 그리고 부족할 때 어떻게 커널이 대처하는지 알아보자.

swap 영역

swap 영역은 물리 메모리가 부족한 경우를 대비해서 만들어 놓은 영역이다.

메모리가 모자라기 시작하면 프로세스는 더 이상 연산을 위한 공간을 얻을 수 없으므로 장애를 일으킬 수 있는데

이를 방지하기 위해서 비상용으로 디스크 공간에 확보해놓은 메모리 공간이 swap 영역이다.

swap 영역은 물리 메모리가 아니라 디스크 영역이기 때문에 메모리에 비해서 현저히 접근 속도가 떨어진다.

그래서 swap 영역을 사용하고 있다면 시스템 성능이 급격하게 떨어져있다고 생각하면 된다.

리눅스에서 사용중인 swap 영역은 free 명령을 통해서 볼 수 있다.

ubuntu@ip-172-31-12-59:~$ free -k
              total        used        free      shared  buff/cache   available
Mem:         992204      380928      137760         956      473516      454308
Swap:             0           0           0
  • 여기에 있는 Swap 이 스왑영역을 말한다.

스왑 영역을 볼때는 쓰고 있느냐 안쓰고 있느냐가 중요하다. 그리고 스왑 영역을 사용하고 있다면 어떤 프로세스에서 메모리를 그렇게 많이 사용되고 있는지를 찾아야한다.

만약 서비스 용도의 프로세스가 아니라 관리 용도의 프로세스에서 메모리 누수가 발생해서 swap 이 일어나고 있다면 이를 죽여서 해결할 수 있다. 즉 누가 swap 을 쓰고 있느냐도 중요하다.

해당 프로세스가 swap 을 쓰고 있는지 알아보는 방법은 /proc/{PID} 디렉토리에 있는 smaps 파일을 읽어보면 알 수 있다.

출력해보면 다음과 같은 정보들을 볼 수 있다.

$ cat /proc/19325/smaps 
...
7f68aa146000-7f68aa147000 r--p 00000000 103:01 3454                      /usr/lib/x86_64-linux-gnu/libdl-2.31.so
Size:                  4 kB
KernelPageSize:        4 kB
MMUPageSize:           4 kB
Rss:                   4 kB
Pss:                   0 kB
Shared_Clean:          4 kB
Shared_Dirty:          0 kB
Private_Clean:         0 kB
Private_Dirty:         0 kB
Referenced:            4 kB
Anonymous:             0 kB
LazyFree:              0 kB
AnonHugePages:         0 kB
ShmemPmdMapped:        0 kB
FilePmdMapped:         0 kB
Shared_Hugetlb:        0 kB
Private_Hugetlb:       0 kB
Swap:                  0 kB
SwapPss:               0 kB
Locked:                0 kB

버디 시스템

커널이 메모리를 할당하는 과정을 간단하게 살펴보자.

커널은 버디 시스템을 통해서 프로세스에 메모리를 할당한다.

버디 시스템은 물리 메모리를 연속된 메모리 영역으로 관리하는데 예를 들면 연속 1 개의 페이지 크기별 버디, 연속 2 개의 페이지 크기별 버디, 연속 4 개의 페이지 크기별 버디, 연속 8 개의 페이지 크기별 버디 이런식으로 관리한다.

  • 페이지의 크기는 4 KB 이다.

그러므로 8KB 메모리를 요청하면 연속 1 개 짜리를 두 개 주는게 아니라 연속 2 개 짜리 하나를 준다.

이런 방식을 사용하는 이유는 연속된 메모리를 구분해서 전달하므로 메모리 단편화 현상을 그나마 막아준다.

버디 시스템의 현재 상황은 /proc/buddyinfo 에서 볼 수 있다.

ubuntu@ip-192-168-111-19:~$ cat /proc/buddyinfo
Node 0, zone      DMA      1      0      0      1      2      1      1      1      0      1      3
Node 0, zone    DMA32   1296    838    470    182    133     70     35     14     14      6     42
Node 0, zone   Normal    238    391    186     76     39     10      3      1      3      1      0
  • 각각의 행은 2의 배수이며 연속 1 개, 2 개 , 4 개, 8 개 ... 를 의미한다.
  • DMA32 를 기준으로 보면 4 KB 1 개 + 8 KB 838 개 + 16 KB 470 개 + 32 KB 182 개 ... 를 의미한다.

메모리 재할당 과정

이번엔 커널이 메모리를 해제하고 다시 할당하는 재할당하는 과정을 보자. 이 경우는 크게 두 가지 케이스가 있다.

1) Page cache, Buffer cache, inode cache, dentry cache 같은 캐시 공간을 해제하고 다시 할당하는 것. (커널은 그냥 메모리를 안쓰고 남겨두는 걸 좋아하지 않는다.)

2) Swap 을 위한 재할당. 캐시용도로 사용하고 있는 메모리를 제외하고 프로세스가 사용중인 메모리는 임의로 커널이 해제할 순 없다. 하지만 메모리가 가득 차있는 상황이라면 사용하는 메모리 중 inactive 영역에 있는 메모리는 swap 영역으로 내리고 요청한 메모리를 올리는 과정을 한다.****

메모리 증설 포인트

메모리가 부족해서 swap 영역을 쓰고 있다면 메모리를 증설해야 한다고 생각할 수 있지만, 메모리가 누수되고 있는 문제일 수도 있다.

메모리가 누수되고 있는 경우는 메모리의 사용량이 시간이 지남에 따라 선형적으로 증가하는 경우다.

요청이 끝나면 메모리를 해제해야 하는데 그러지 못해서 메모리가 요청을 받을 때마다 선형적으로 증가해서 이런 추세를 가질 수 있다.

이 경우에는 pmap 등의 명령을 이용해서 해당 프로세스가 사용하는 힙 메모리 영역 변화 과정을 보거나 gdb 같은 도구를 이용해서 디버깅을 해보면 메모리 덤프를 생성해 실제 어떤 데이터들이 메모리에 있는지 확인하고 어떤 로직에서 문제가 있을지 예측할 수 있다.

만약 요청이 폭증해서 이로인한 메모리의 사용량도 폭증해서 swap 을 사용하게 되는 경우도 있는데 이 경우에는 안정적인 서비스를 위해서 해당 트래픽을 처리할 수 있을만큼 메모리를 증설해서 swap 영역을 사용하지 않도록 하자. swap 영역을 사용하는 순간 응답 속도가 많이 느려질 수 있다.

NUMA, 메모리 관리의 새로운 세계

여기서는 NUMA 아키텍처가 뭐고, NUMA 아키텍처가 메모리 할당에 어떤 영향을 주는지 알아보겠다.****

NUMA 아키텍처

NUMA 는 Non-Uniform Memory Access 의 약어다. 번역하자면 불균형 메모리 접근이라는 뜻이며 멀티 프로세서 환경에서 적용되는 메모리 접근 방식을 말한다.

NUMA 아키텍처의 반대는 UMA (Uniform Memory Access) 로 모든 프로세서가 공용 BUS 를 통해서 메모리에 접근하는 방식이다.

UMA 아키텍처의 문제점은 버스를 동시에 이용하지 못하는 단점이 있다. 예로 0 번 소켓에 있는 CPU 가 메모리에 접근하는 동안은 1 번 소켓에 있는 CPU 는 메모리에 접근하지 못한다. 즉 싱글 CPU 에 적합한 구조. (TMI: CPU 안에 코어가 있다.)

NUMA 는 CPU 마다 로컬 메모리가 서로 붙어 있는 관계로 이뤄져있다. 그래서 한 CPU 가 자신의 로컬 메모리에 접근하는 동안 다른 CPU 도 자신에게 붙어 있는 로컬 메모리에 접근이 가능하다.

주의할 점은 Remote 에 있는 메모리에 접근할 땐 성능이 떨어질 수 있어서 로컬 메모리를 최대한으로 쓰도록 하는게 중요하다.****

리눅스에서 NUMA 확인

ubuntu@ip-192-168-111-182:~$ numactl --show
policy: default
preferred node: current
physcpubind: 0 1
cpubind: 0
nodebind: 0
  • 기본 정책은 default 이고 현재 사용중인 프로세스가 포함된 노드 (= CPU + 로컬 메모리) 에서 메모리를 먼저 가져다가 쓰는 방식이다. 이 정책은 별도의 설정을 하지 않는한 모든 프로세스가 해당된다.
  • 두 번째는 bind 정책으로 특정 프로세스를 특정 노드에 바인딩시키는 방식을 취한다. 특정 노드에 할당시켜서 거기에 있는 메모리만 사용하도록 하는 방식이다. 이 경우 메모리의 지역성이 좋아져서 더 빠를수 있지만 해당 로컬 메모리에서 가용 메모리가 부족해진다면 성능이 급격히 나빠질 수 있다.
  • 세 번째는 preferred 정책으로 bind 와 비슷하지만 선호하는 노드를 설정한다.
  • 마지막은 interleaved 정책으로 다수의 노드에서 거의 동일한 비율로 메모리를 받는 방식이다. Round-Robin 정책에 따라 돌아가면서 할당 받는다.

다음은 -H 옵션이다. 이건 노드에 있는 메모리 정보를 확인할 때 사용할 수 있다.

ubuntu@ip-192-168-111-182:~$ numactl -H
available: 1 nodes (0) # (1) 
node 0 cpus: 0 1       # (2) 
node 0 size: 3866 MB
node 0 free: 1759 MB
node distances:        # (3) 
node   0
  0:  10
  • (1) 은 NUMA 노드가 1 개로 구성되어 있음을 알 수 있다.
  • (2) 은 노드 0 번에 cpu 0 과 1 이 붙어 있음을 알 수 있다. 각 노드에 할당된 메모리 크기와 사용 가능한 메모리 크기도 볼 수 있다.
  • (3) 은 메모리에 접근하는데 걸리는 시간이다. 로컬 메모리에 접근할 때 걸리는 시간을 10 이라고 한다면 리모트 메모리에 접근하는 동안은 2 배 정도 차이가 날 수 있다.

다음은 NUMA 환경에서 메모리의 상태를 자세하게 확인할 때 사용하는 명령어인 numastat 이다.

주로 노드의 메모리 균형을 확인하고 한쪽에 메모리가 가득차서 스왑을 하는지 확인하기 위해서 사용한다.

ubuntu@ip-192-168-111-182:~$ numastat -cm

Per-node system memory usage (in MBs):
Token Node not in hash table.
Token Node not in hash table.
Token Node not in hash table.
Token Node not in hash table.
Token Node not in hash table.
                 Node 0 Total
                 ------ -----
MemTotal           3867  3867
MemFree            1761  1761
MemUsed            2106  2106
Active              777   777
Inactive           1074  1074
Active(anon)          1     1
Inactive(anon)       77    77
Active(file)        776   776
Inactive(file)      997   997
Unevictable          22    22
Mlocked              18    18
Dirty                 0     0
Writeback             0     0
FilePages          1779  1779
Mapped              102   102
AnonPages            94    94
Shmem                 1     1
KernelStack           2     2
PageTables            2     2
NFS_Unstable          0     0
Bounce                0     0
WritebackTmp          0     0
Slab                195   195
SReclaimable        148   148
SUnreclaim           46    46
AnonHugePages         0     0
HugePages_Total       0     0
HugePages_Free        0     0
HugePages_Surp        0     0
  • numastat 명령을 통해서 NUMA 아키텍처에서 메모리 불균형 상태를 확인할 수 있다. 어느 한쪽 노드만의 메모리 사용률이 높은 경우에도 swap 을 사용할 수 있기 때문이다. 분명 전체 메모리 기준으로 free 영역이 많다고 하더라도 메모리 정책에 따라서 한쪽 노드에만 메모리를 많이 할당하도록 했다면 swap 을 사용할 수 있게 된다.

이번에는 프로세스가 어떤 메모리 할당 정책으로 실행되었는지를 보자. /proc/{PID}/numa_maps 에서는 현재 동작 중인 프로세스의 메모리 할당 정책과 관련된 정보가 기록된다.

$ sudo cat /proc/92432/numa_maps
558244dbf000 default file=/usr/sbin/sshd mapped=11 mapmax=3 N0=11 kernelpagesize_kB=4
558244dca000 default file=/usr/sbin/sshd mapped=127 mapmax=3 N0=127 kernelpagesize_kB=4
558244e49000 default file=/usr/sbin/sshd mapped=39 mapmax=3 N0=39 kernelpagesize_kB=4
  • 이 프로세스는 default 정책으로 할당되었다.****

numad 를 이용한 메모리 할당 관리

리눅스에선 numad 를 통해서 NUMA 메모리 할당 정책을 직접 설정하지 않고도 메모리 지역성을 높일 수 있는 방법을 제공해준다.

numad 는 백그라운드 데몬과 같은 형태로 시스템에 늘 상주해있으면서 프로세스들의 메모리 할당 과정을 지켜보고 프로세스가 필요로 하는 메모리 크기가 노드보다 작다면 한쪽 노드에서만 메모리를 할당하도록 해서 메모리 지역성을 높여 최적화를 해준다.

다수의 프로세스를 사용하는 경우에 default 정책이라면 메모리가 여러 곳으로 흩어지면서 성능이 다소 떨어질 수 있다. 하지만 numad 를 실행시킨다면 하나의 프로세스가 필요로 하는 메모리를 하나의 노드에서만 할당하도록 해준다.

이 경우에 조심해야 할 것은 하나의 노드에만 집중적으로 하기 때문에 메모리 불균형이 생겨서 스왑을 사용하는 경우다. ****

예를 들면 Process 1 이 Node B 의 메모리를 모두 차지하고 있는데 Process 2 의 경우는 NUMA 정책을 interleaved 으로 해서 스왑이 발생하는 경우.

vm.zone_reclaim_mode 커널 파라미터

numad 말고도 NUMA 아키텍처에서 메모리 할당에 영향을 줄 수 있는 커널 파라미터가 있는데 이건 vm.zone_reclaim_mode 이다.

vm.zone_reclaim_mode 에 대해서 이야기 하기 전에 zone 이 무엇인지 먼저 살펴보자.

커널은 메모리를 사용 용도에 따라 zone 이라 불리는 영역으로 구분해서 관리한다.

zone 에 대한 정보는 /proc/buddyinfo 에서 살펴볼 수 있다. (buddyinfo 는 메모리 할당 과정에서 이전에 살펴봤다.)

ubuntu@ip-192-168-111-182:~$ cat /proc/buddyinfo
Node 0, zone      DMA      1      0      0      1      2      1      1      1      0      1      3
Node 1, zone    DMA32   3428   2965   1761    328    115     13      5      1      4     22    393
Node 0, zone   Normal   1888   1077    510    103     18     17     10      3      6      0      0
  • Node 0 은 3 개의 zone 으로 구별된다. DMA, DMA32, Normal.
  • DMA 는 Direct Memory Access 의 약자로, 주로 오래된 하드웨어의 동작을 위해서 사용하는 메모리 공간이다. 즉 일부 하드웨어를 위한 공간이므로 필요하지 않을 수 있다.
  • Normal 은 커널과 프로세스가 메모리를 필요로 할 때 요청하는 영역이다.

이제 vm.zone_reclaim_mode 에 대해서 보자. 이 값은 총 4 개의 값을 가질 수 있지만 실제적으로 중요한 값은 0 과 1 이다.

  • 0 은 disable 을 의미하며 해당 Zone 안에서 메모리 재할당을 하지 않겠다는 의미다. 즉 메모리가 부족하면 다른 Zone 에서 가져와서 사용하겠다느 뜻이다.
  • 1 은 enable 을 말하며 Zone 안에서 메모리 재할당을 하겠다는 뜻이다. 해당 Zone 에서 메모리가 부족하면 재할당을 하기 위해서 필요없는 메모리를 제거하고 재사용해보고 그래도 부족하다면 다른 Zone 에서 메모리를 할당 받아서 사용한다.

0 을 이용하면 page cache 와 같은 재할당이 가능한 메모리들도 재할당 하지않고 다른 노드에 있는 메모리를 할당 받아서 사용하므로 I/O 가 중요한 프로세스의 경우에는 vm.zone_reclaim_mode 를 0 으로 설정해서 사용하는 것이 더 좋을 수 있다.

반대로 page cache 보다 로컬 메모리의 접근이 더 유리할 때는 vm.zone_reclaim_mode 를 1 로 할당해서 가능한 동일한 노드에서 메모리를 할당 받을 수 있게 해주는 것이 좋다.

NUMA 아키텍처의 메모리 할당 정책과 워크로드

이번에는 지금까지의 내용을 바탕으로 NUMA 의 메모리 할당 정책을 어떻게 사용하는게 최적화를 할 수 있을지를 알아보자.

이것은 정답이 없는 문제이기도 해서 그냥 이런 이유로 사용할 수 있다 정도만을 알아두자.

NUMA 시스템에서 워크로드를 확인할 때 고려해봐야 할 것이 두 개가 있다.

  • 프로세스가 노드의 메모리를 뛰어 넘는지
  • 프로세스가 여러 CPU 가 필요한 멀티 스레드인지, 싱글 스레드인지가 중요하다.

표로 나타내면 다음과 같다.

스레드 개수메모리 크기
싱글 스레드메모리가 노드 하나를 넘지 않음
멀티 스레드메모리가 노드 하나를 넘지 않음
싱글 스레드메모리가 노드 하나를 넘음
멀티 스레드메모리가 노드 하나를 넘음

먼저 싱글 스레드 + 메모리가 노드 하나를 넘지 않는 경우를 보자. 이 경우는 흔하진 않을 건데 하나의 코어만 받으면 되므로 바인딩을 통해서 로컬 메모리 엑세스를 하도록 하는게 좋다. 그리고 vm.zone_reclaim_mode 도 1 로 둬서 가능한 로컬 메모리를 향하도록 하자.

두 번째는 멀티 스레드 + 메모리가 노드 하나를 넘지 않는 경우인데 이 경우에도 cpunodebind 모드를 이용해서 여러 개의 코어에 프로세스를 바인딩 하도록 해서 로컬 메모리 엑세스를 하도록 하자.

이 경우에는 CPU Usage 에 대한 모니터링이 필요한데 특정 노드에 위치함으로써 CPU 를 독차지 할 수 있다. 모니터링 할 땐 그러므로 전체 CPU 가 아닌 개별 CPU 를 봐야한다. vm.zone_reclaim_mode 도 가능한 1 로 둬서 로컬 메모리를 사용하도록 하자.

세 번째는 싱글 스레드이고 메모리가 노드 하나를 넘는 경우인데 이 경우 부터는 어쩔 수 없이 리모트 메모리 엑세스가 일어난다. 하지만 이를 최소화 하기 위해서는 로컬 메모리 사용 비중을 높이기 위해서 동일한 cpu 에 계속해서 바인딩 하도록 하는게 좋다. 그래서 첫 번째와 마찬가지로 cpunodebind 정책을 쓰자. 그리고 어짜피 노드 하나의 메모리를 넘을 것이니 계속해서 재할당 하는 것보다는 그냥 골고루 메모리를 할당 받는게 나을수 있으니 vm.zone_reclaim_mode 는 0 으로 하는게 나을 수 있다.
네 번째는 멀티 스레드에 메모리가 노드 하나를 넘는 경우인데 실제로 이 경우가 가장 많을 수 있다. 어짜피 리모트 메모리 엑세스도 일어나고 한쪽으로 CPU 를 할당하는 것도 그렇게 좋지 않다. 그러므로 그냥 interleave 모드로 골고루 받는게 가장 나을 수 있다. 이 경우에도 vm.zone_reclaim_mode 는 0 으로 하는게 더 나아보인다.

profile
좋은 습관을 가지고 싶은 평범한 개발자입니다.

2개의 댓글

comment-user-thumbnail
2022년 3월 11일

엄청나네요..

1개의 답글