공대생 정리노트

커널 - Slab 본문

로드맵/OS

커널 - Slab

woojinger 2022. 11. 13. 12:02

Slab이란?

Slab은 커널 데이터 객체 생성/파괴의 오버헤드로 인한 성능 저하를 줄이기 위해서 자주 사용되는 오브젝트들을 미리 만들어 관리한다.
Slab에 할당된 객체가 release 되더라도 slab은 재사용을 위해서 캐시된 상태로 유지한다.
 
이해를 하기 위해 전체적인 메모리 할당 구조를 한번 보자.
kmalloc() 함수를 통해 커널 내부에서 메모리를 할당받을 때 어떤 일이 일어날까?

 

https://students.mimuw.edu.pl/ZSO/Wyklady/06_memory2/BuddySlabAllocator.pdf
커널은 메모리를 페이지 단위로 관리하고, 커널의 page allocator을 buddy allocator라고 한다.
buddy allocator는 external fragmentation을 줄이기 위해 메모리를 관리한다.

https://students.mimuw.edu.pl/ZSO/Wyklady/06_memory2/BuddySlabAllocator.pdf

(Buddy allocator에 대한 자세한 설명은 다른 글들을 참고하면 좋다)
 
커널은 buddy allocator에 두 가지 메커니즘으로 접근한다
  • slab allocator - physically contiguous한 메모리를 얻는다.
  • vmalloc - virtually contiguous하지만 physically scattered 할 수 있다.
slab allocator는 빠른 특징을 가지고 있고, physical page가 한 개 이하로 필요할 때  주로 사용을 한다.
첫번째 그림을 보면, kmalloc은 이 slab allocator을 사용한다.

https://students.mimuw.edu.pl/ZSO/Wyklady/06_memory2/BuddySlabAllocator.pdf

slab은 slab object들을 가지고 있는데, slab object는 slab이 미리 할당해놓은 메모리 공간이다.

다음의 구조체들을 주로 할당해 가지고 있는다
  • struct task_struct
  • struct inode
  • struct mm_struct
  • kmalloc-512, kmalloc-256, kmalloc-192 ...
즉, kmalloc(54)를 호출하면 커널에서 buddy allocator가 관리하는 최소 페이지 단위인 4k를 할당하는 것이 아닌 kmalloc-64 슬랩 캐시가 작동해 64만큼을 할당해준다.

Slab의 상태

slab은 여러 개 존재하며, 한 slab에 존재하는 object는 모두 같은 종류이다.

https://wiki.amigaos.net/wiki/Exec_Memory_Allocation

Slab은 다음 상태 중 하나로 존재한다
  • empty: slab의 모든 객체가 free로 마킹됨
  • parital: slab의 일부 객체만 used로 마킹됨
  • full: slab의 모든 객체가 used로 마킹 됨
초기에는 시스템은 모든 slab을 empty로 마킹을 한다.
프로세스가 새 커널 객체를 호출했을 때, 시스템은 partial slab에서 해당하는 객체가 있는지 확인한다.
만약 없다면, 시스템은 새로운 slab을 physical page에 할당해 캐시에 배정한다.

Buffer와 Cache

메모리 사용량을 확인하기 위해 free -h 를 쳤을 때 buff/cache는 무엇일까? slab과 어떻게 관련이 있을까?

man free 로 알아보면 다음과 같다
  • buffers: 커널 버퍼에 의해 사용되는 메모리
  • cache: page cache와 slabs (Cached and SReclaimable in /proc/meminfo)

 

https://www.slideserve.com/tara/file-system-structure

buffer는 커널이 I/O 성능 향상을 위해 사용하는 메모리 영역으로,  Super blockinode block에 해당하는 메타데이터를 저장한다.
page cache는 파일의 데이터를 캐싱하는 것이고, slab은 위에서 설명한 바 있다.

Slab 메모리 보는 법

sudo cat /proc/slabinfo
커널에서 자주 사용되는 객체들의 캐시를 보여준다
sudo vmstat -m
slabinfo의 캐시 객체 별로 Num, Total, Size, Pages 를 보여준다
 

SReclaimable, SUnreclaim

cat /proc/meminfo
위 명령어로 메모리를 조회하면 SReclaimable과 SUnreclaim을 확인할 수 있다.
SReclaimable: reclaim이 될 수 있는 slab의 파트
SUnreclaim: Slab이 사용을 하고 있는 영역이므로, 메모리가 꽉 차 더 필요하더라도 release되지 않는다.
 
SUnreclaim이 늘어나는 이유는 커널 컴포넌트가 kamlloc으로 메모리를 할당한 후 release를 안해서 그런 것이다.
이 경우 프로세스를 kill해 죽이더라도, SUnreclaim은 줄어들지 않는다.
 

Shrink

커널의 캐시를 줄이는 방법은 아래와 같다.
To free pagecache: echo 1 > /proc/sys/vm/drop_caches

To free reclaimable slab objects (includes dentries and inodes): echo 2 > /proc/sys/vm/drop_caches

To free slab objects and pagecache: echo 3 > /proc/sys/vm/drop_caches
하지만 위 방법은 SUnreclaim을 줄이지는 못한다.
 
SUnreclaim을 줄이는 방법은 다음과 같다.
sudo bash -c 'echo 1 > /sys/kernel/slab/kmalloc-4096/shrink'
사실 이 명령어는 slab의 kmalloc-4096 오브젝트를 shrink하는 것이다.
더 효과를 보려면 slabinfo를 조회해 다른 kmalloc 오브젝트를 줄이는 것이 도움이 될 수 있다.
 
위 명령어는 위험하지 않을까?
위 글은 2007~2008년 작성된 kernel docs로 shrink에 대한 언급이 있다.
The shrink file is used to reclaim unused slab cache
memory from a cache.  Empty per-cpu or partial slabs
are freed and the partial list is sorted so the slabs
with the fewest available objects are used first.
It only accepts a value of "1" on write for shrinking
the cache. Other input values are considered invalid.
Shrinking slab caches might be expensive and can
adversely impact other running applications.  So it
should be used with care.
다른 실행 중인 어플리케이션에 영향을 미칠 수 있다고 되어 있다. 되도록이면 안 쓰는 것이 좋아보인다.

Reference

Comments