티스토리 뷰

728x90
반응형

DevOps와 SE를 위한 리눅스 커널 이야기 - 단단한 서버 구축을 위한 12가지 키워드라는 책 스터디를 진행 했었는데 저는 4장 free 명령이 숨기고 있는 것들에 대해서 정리하고 발표 했었습니다. 이 단원의 내용을 블로깅 해둡니다.

cpu는 프로세스의 연산 과정에 필요한 리소스
메모리는 프로세스가 연산할 수 있는 공간을 제공해 주는 리소스

cpu가 사람의 뇌
메모리는 사람이 들어 갈 수 있는 공간

프로세스?
프로세스는 메모리라는 공간에 자신이 필요한 함수를 넣어 두거나 변수에 값을 저장하거나 하는 방식으로 연산을 위한 공간을 확보하고 작업을 진행

메모리 부족
연산을 위한 공간을 확보할 수 없고, 시스템 응답 불가 현상, 큰 성능 저하

메모리 사용량 확인하기

free 명령어
전체 메모리 용량, 사용 중인 용량, 캐싱 영역의 용량(buffers, cached)

image

buffers
버퍼 용도로 사용하고 있는 메모리 양. 시스템 성능 향상을 위해서 커널에서 사용하고 있는 영역

cache
페이지 캐시라고 불리는 캐시 영역에 있는 메모리 양을 의미 I/O 관련 작업을 더 빠르게 진행하기 위해 커널에서 사용하고 있는 영역.

image

used
버퍼와 캐시를 제외하고 사용하고 있는 영역
(shared 메모리도 제외지만, 너무 작음)

free
아직 사용하지 않는 메모리 양

avaliable
버퍼와 캐시를 제외하고 사용하지 않는 영역

왜 free, avaliable을 나눠서 보여줄까?

buffers cached 영역

커널은 블록 디바이스라고 부르는 디스크로부터 데이터를 읽거나 사용자의 데이터를 디스크에 저장

디스크는 다른 장치들에 비해 매우 느리기 때문에 디스크에 대한 요청을 기다리는 시간이 상당히 많이 소요되고, 이로 인해 시스템에 부하가 일어남.

커널은 이렇게 상대적으로 느린 디스크에 대한 요청을 좀 더 빠르게 하기 위해 메모리의 일부를 디스크 요청에 대한 캐싱 영역으로 할당해서 사용함

한번 읽은 디스크의 내용을 메모리에 저장해 두어서, 동일한 내용을 읽고자 하면 디스크로 요청하지 않고 메모리로 요청하게 된다. 이런 캐싱 기능을 통해서 커널은 다수의 디스크 요청을 좀 더 빠르게 처리할 수 있다.

이때 사용되는 캐싱 영역을 buffers, cached라고 부름

buffers, cached 차이점

image

커널이 블록 디바이스에서 데이터를 읽을 때 데이터가 위치한 특정 블록의 주소를 넘겨주고, 블록 디바이스는 해당 블록 주소의 데이터를 커널에 전달한다.

커널이 읽어야 할 데이터가 파일의 내용이라면 커널은 bio 구조체를 만들고 해당 구조체에 Page cache 용도로 할당한 메모리 영역을 연결해준다. 그리고 bio 구조체는 디바이스 드라이버와 통신해서 디스크로부터 데이터를 읽어서 Page Cache에 파일의 내용을 채운다.

super block, inodek block처럼 파일의 내용이 아닌 파일 시스템을 관리하기 위한 메타 데이터를 읽어올 때는 bio 구조체를 사용하지 않고 _get _blk()와 같은 내부 함수를 통해 블록 디바이스와 직접 통신한다. 이때 가져온 블록 디바이스의 특정 블록 내용을 buffer cache 영역에 저장해 둔다.

Page Cache는 파일의 내용을 저장하고 있는 캐시, Buffer Cache는 파일 시스템의 메타 데이터를 담고 있는 블록을 저장하고 있는 캐시라고 할 수 있다.

image

시간이 지나면 커널은 가용 영역 중 일부를 Cache 영역으로 사용하게 된다.

시간이 흐를수록 애플리케이션에서 사용하게 되는 영역이 점점 넓어짐. 어느 순간까지는 가용영역의 메모리를 계속 가져다 씀

사용 영역이 점점 더 커져서 일정 수준 이상이 되면 커널은 Cache 영역으로 사용하던 영역으로 사용하던 영역을 애플리케이션이 사용할 수 있도록 메모리 관리 시스템에 반환함

더 이상 반환할 메모리도 없고 가용할 메모리가 없는 순간이 발생하게 되는데, 시스템은 이떄부터 swap이라는 영역을 사용하게 되고 시스템의 성능이 줄어든다.

buffers, cached 영역은 시스템의 I/O 성능 향상을 위해서 커널이 사용하는 영역. 메모리가 부족한 상황이 되면 커널은 해당 영역을 자동으로 반환하기 떄문에 free 명령에서도 해당 영역을 제외한 영역을 실제 사용 가능한 영역을 계산하게 됨

/proc/meminfo 읽기

좀 더 자세하게 메모리의 사용 현황을 알 수 있는 방법

image

SwapCached
swap으로 빠진 메모리 영역 중 다시 메모리로 돌아온 영역

image

시스템에 메모리가 부족하면 커널은 프로세스의 주소 공간 중 swap 영역으로 이동시킬 수 있는 메모리를 선택해서 swap 영역으로 이동시킴. 이 과정에서 I/O가 일어나기 때문에 성능 저하가 발생

그 후 메모리가 다시 확보되어 swap 영역으로 빠졌던 영역이 다시 메모리로 돌아가게 되더라도 커널은 swap 영역에서 해당 메모리 내용을 삭제하지 않음

이후에 또 메모리 부족 현상이 일어날 경우 이전에 참고한 메모리 영역을 삭제하지 않고 그대로 다시 활용(I/O를 줄일 수 있음)

Active(anon): 특정 파일의 내용을 저장하고 있는 Page Cache 영역을 제외한 메모리 영역. 주로 프로세스들이 사용하는 메모리 영역을 지칭

Inactive(anon): 비교적 참조된지 오래되어 Swap 영역으로 이동될 수 있는 메모리 영역을 의미

Active(file): 커널이 I/O 성능 향상을 위해 사용하는 영역을 의미. buffers, cached 영역. 비교적 최근까지 메모리 영역이 참조되어 Swap 영역으로 이동되지 않을 메모리 영역

Inactive(file): 비교적 참조된 지 오래되어 Swap 영역으로 이동될 수 있는 메모리 영역

Dirty: I/O 성능 향상을 위해 커널이 캐시 목적으로 사용하는 영역 중 쓰기 작업이 이루어져서 실제 블록 디바이스의 블록에 씌어져야 할 영역을 의미. 커널은 기본적으로 I/O 쓰기 요청이 발생했을 때 바로 블록 디바이스로 명령을 내리지 않고 일정량이 될 때까지 모았다가 한 번에 쓰는 일종의 지연 쓰기 작업을 한다. 이 과정에서 사용되는 메모리 영역

Active, Inactive 영역을 구분하는 방법
커널이 직접 사용하는 메모리 영역을 제외하고 대부분의 메모리는 프로세스가 사용하거나 캐시 영역으로 사용된다.

참고: https://github.com/torvalds/linux/blob/master/fs/proc/meminfo.c (코드에서 active, inactive 검색)

image

anon, file 영역의 메모리는 LRU 기반의 리스트로 관리되고, 이 리스트는 다시 Active, Inactive 두개의 리스트로 나뉘게된다. 결과적으로는 자주 사용되는 메모리 영역이 Active 리스트에 남게 되고 자주 사용되지 않는 영역은 Inactive 리스트에 남게 된다.

가장 최근에 참조한 메모리가 Active List에, 그리고 참조 시기가 오래될수록 Inactive 영역으로 이동하고 이후 free 영역으로 이동

Active 리스트와 Inactive 리스트 사이의 이동
기본적으로 프로세스가 메모리 할당을 요청하면 해당 메모리의 페이지가 Active 리스트에 연결
그 후 메모리 할당이 실패하거나 메모리가 부족하게되면 kswapd 혹은 커널 내부에서 try_to_free_pages() 함수를 통해서 LRU 리스트에 있던 페이지가 Inactive 리스트로 옮겨가거나 Inactive 리스트에 있던 페이지가 해제되어 다른 프로세스에게 할당되는 작업이 이루어짐

간단한 메모리 할당 코드로 테스트

image

단순히 시간이 지난다고 해서 Active 메모리가 Inactive로 이동하지는 않음

메모리 부족 현상이 발생해서 해제해야 할 메모리를 찾아야하는 순간이 와야 커널이 LRU 리스트를 살펴봄. vm.min_free_kbytes라는 파라미터(시스템에서 유지해야 하는 최소한의 free 메모리 양) 값을 높게 설정

image

image

active(anon) 영역이 내려감

free 영역이 vm.min_free_kbytes에 설정한 값 이상으로 올라감

메모리들이 대부분 Swap 영역으로 빠짐

slab 메모리 영역

buffers, cached
캐싱 메모리 영역

anon
프로세스의 메모리 영역

slab
커널이 내부적으로 사용하는 메모리 영역

image

Slab: 메모리 영역 중 커널이 직접 사용하는 영역
SReclaimable: Slab 영역 중 재사용될 수 있는 영역. 캐시 용도
SUnreclai: Slab 영역 중 재사용될 수 없는 영역. 현재 커널이 사용 중인 영역

slabtop -o
현재 시스템에서 사용 중인 Slab의 정보

모든 프로세스는 작업을 하기 위해 메모리가 필요하고 이는 커널도 예외가 아니다. I/O 작업을 조금이라도 더 빠르게 하기 위해 inode cache, dentry cache 등을 사용하거나, 네트워크 소켓을 위한 메모리 영역을 확보하거나 하는 작업들은 커널이하게 되는데 이 과정에서 메모리가 필요하다.

하지만 메모리를 할당해주는 버디 시스템은 4KB 페이지 단위로 메모리를 할당한다. 근데 사실 커널 입장에서는 이렇게 큰 영역을 할당 받을 필요가 없다. 영역이 크다면 실제 사용하는 영역과 할당 받은 영역의 차이가 커지면서 메모리 단편화 현상도 발생할 수 있다.

그렇기 때문에 커널이 사용하려는 메모리 영역은 좀 더 작고 효율적으로 사용할 수 있어야 한다. 이를 충족시키기 위해서 커널은 Slab 할당자를 통해서 원하는 메모리 영역을 확보한다.

Slab 할당자는 각각의 목적에 맞는 캐시별로 영역을 할당 받아 사용한다. dentry cache, inode cache 등이 목적별로 나뉘어 있다. 이렇게 버디 시스템을 통해서 페이지 크기인 기본 4KB의 영역을 할당 받은 후에 각각의 캐시 크기에 맞게 영역을 나눠서 사용한다.

image

가장 많이 사용되는 캐시가 dentry, inode_cached
디렉터리의 계층 관계를 저장해 두는 캐시, 파일의 inode에 대한 정보를 저장해두는 캐시
cd, ls 명령으로 디렉터리를 살펴보는 것만으로도 dentry 값이 증가

Slab 할당자는 free 명령에서 used로 계산된다. 커널이 사용하는 캐시 영역이기 때문에 buffers/cached 영역에 포함될 것이라고 생각할 수 있지만 used영역으로 계산

Case Study

운영하던 서버에서 지속적으로 메모리의 사용량이 증가하는 이슈
프로세스 메모리 사용량의 합 10GB
Used 35 ~ 40GB

원인은? Slab 메모리 영역이 무려 27GB 사용중이었다
dentry cache가 26GB

echo 2 > /proc/sys/vm/drop_caches
drop cache를 이용한 캐시 영역 강제 플러싱

일정 시간 후 똑같이 메모리 릭이 발생했다..!

slabtop 기록을 바탕으로 dentry cache의 값이 일정한 간격을 두고 증가함.
crontab 스크립트 상에서 버그가 있음을 알 수 있었다..!!

crontab 스크립트를 수정함으로서 해결

요약

free 명령으로 볼 수 있는 buffers는 파일 시스템의 메타 데이터 등을 저장하고 있는 블록 디바이스의 블록을 위한 캐시이다.

free 명령으로 볼 수 있는 cached는 I/O 작업의 효율성을 위하여 한번 읽은 파일의 내용을 저장하는 데 사용하는 캐시 영역이다.

buffers와 cached는 미사용 중인 메모리 영역을 시스템의 효율성을 위해서 커널이 사용하는 용도이며, 프로세스가 필요로 할 때는 언제든지 해당 영역을 해제하여 프로세스에게 전달해 준다.

/proc/meminfo에서 보이는 anon 영역은 프로세스에서 사용하는 영역이고, file 영역은 위에서 언급한 I/O 성능 향상을 위해 커널이 캐싱 용도로 사용하는 영역이다.

anon과 file 영역은 각각 Active, Inactive라 불리는 LRU List를 통해 관리되고 있으며 각각은 시스템에 해당 메모리 영역에 얼마나 최근에 접근했는지를 기준으로 관리된다.

Slab 영역은 커널이 사용하는 캐싱 영역을 의미하며 dentry cache, inode cache, buffer_head 등 다양한 캐싱 용도로 사용된다.




출처: DevOps와 SE를 위한 리눅스 커널 이야기 - 단단한 서버 구축을 위한 12가지 키워드(김진우 지음, 프로그래밍인사이트 출판사)

image

728x90
반응형
댓글
반응형
250x250
글 보관함
최근에 달린 댓글
«   2024/04   »
1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30
Total
Today
Yesterday
링크