lowmem_reserve_ratio Jun 13, 2010

최근 어떤 개발자로부터 memory fragmentation으로 인한 문제를 들은적이 있다.
음. 많은분들이 lowmem_reserve_ratio에 관해 아직은 잘알지 못하고 있는 것 같아
정리한다.

일반적으로 1G 이상의 물리 메모리를 갖는 시스템에서 kernel은 동작의 효율을
위해 high memory 공간을 잘 활용하지 않는다. 왜냐하면 kernel이 highmem공간을
주소로 접근하기 위해서는 kmap/kmap_atomic과 같은 함수를 통해서 page-to-address
변환 작업이 필요하기 때문이다.(user process의 경우에는 문제 되지 않는다.)
그러므로 low memory는 커널이 제일 선호하는 공간이다.

그렇다면 이런 low memory를 application이 사용하게 되면 무슨 일이 벌어질 수 있을까?
사실, kernel은 application들의 사용을 위해 할당하는 메모리는 high memory를 사용하려고
애쓴다.하지만 high memory의 페이지가 부족할 경우, fallback zones 즉,
NORMAL, DMA32, DMA zone을 사용할 수 밖에 없게 된다. 이때 NORMAL zone에서
application을 위한 페이지를 할당하게 됐다고 가정할 경우, application이 해당 page를
mlock해버린다면 또는 임베디드 시스템에서와 같이 swap system을 가지고 있지 않을 경우, heap이나
stack을 위한 페이지를 할당하게 된다면 무슨 일이 발생할까?
이것이 의미하는 것은 kernel은 페이지 회수를 할 수 없게 된다는 것을 의미하고 이는
바로 memory fragmentation 문제로 이어지게 된다.

이러한 현상을 막기 위해 커널은 /proc/sys/vm/lowmem_reserve_ratio 라는 knob을 제공한다.
barrios의 system에서의 lowmem_reserve_ratio는 다음과 같이 출력된다.

#> cat /proc/sys/vm/lowmem_reserve_ratio
256 32 32
라고 출력된다.

이 값은 다음과 같이 사용된다.

1G RAM을 기준으로 DMA(16M), NORMAL(784M), HIGH(224M)를 쓰게 될 경우라고 가정하고
ZONE_DMA의 경우, ZONE_NORMAL의 target의 fallback으로 memory를 할당하게 될 경우,
784/256의 메모리를 reserve한다.
ZONE_DMA의 경우, ZONE_HIGHMEM의 target의 fallback으로 memory를 할당하게 될 경우,
(224 + 784) / 256의 메모리를 reserve하게 된다.
ZONE_NORMAL의 경우, ZONE_HIGHMEM의 target의 fallback으로 memory를 할당하게 될 경우,
224/32 의 메모리를 reserve하게 된다.

이것이 어떻게 사용되는지 살펴보자.
#> dmesg | grep zone
...
Normal zone: 221486 pages, LIFO batch:31
....
HighMem zone: 294356 pages, LIFO batch:31
...

barrios의 system에는 normal zone이 221486개의 page로 이루어져 있고
high zone이 294356의 page로 이루어져 있음을 볼 수 있다.
그러므로 위의 rule을 적용시켜 보면

- NORMAL zone을 대신해서 DMA_ZONE이 사용될 경우)

221486 / 256 = 865

- HIGHMEM zone을 대신해서 DMA_ZONE이 사용될 경우

(221486 + 294356) / 256 = 2015

의 메모리가 reserve된다는 것이다.
실제로 아래의 명령을 통해 확인해보자.

#> cat /proc/zoneinfo | more
...
protection: (0, 865, 2015, 2015)
...

위의 계산과 일치하는 것을 볼 수 있다.
마지막 2015는 ZONE_MOVABLE zone을 위한 것인데 지금은 신경쓰지 말자. (얘기할 기회가 있겠지)

이와 같이 하위 zone은 상위 zone들의 fallback으로 사용될 경우 위와 같은 rule에 의해
page를 reserve하게 된다.

정리하자면, 커널은 메모리 요구가 발생하였을 경우, 호출자가 선호하는 zone에서 page를 할당하기
위해 노력한다. 하지만 그 요구를 만족시키지 못할 경우 어쩔 수 없이 fallback list에서(ex, 하위 zone들)
에서 페이지 할당을 하게 된다. 이는 자원을 효율적으로 사용한다는 측면에서 나쁘지는 않다. 하지만 각 zone들은
원래의 목적이 있기 마련인데 다른 목적을 위해 페이지가 사용될 경우, 원래의 목적에 페이지가 필요한 경우
페이지가 모자라게 되어 심각한 문제가 발생할 수 있다. 이는 order 0 페이지의 경우에는 덜하지만
order가 커지면 커질수록 문제가 발생할 확률이 커지게 된다.

이글이 memory fragmentation으로 인해 문제를 겪는 몇몇 분들에게 도움이 되었으면 한다.

P.S) 한국:그리스 = 2:0 ^O^

1 개의 덧글:

Sean said...

안녕하세요? 언제나 조용히 포스팅하시는 글 잘 읽고 있습니다. 감사합니다. 초면에 죄송하지만, 제가 알고 있는 내용을 확인해 볼 방법이 없어서요. 주변을 찾아봐도 물어볼 전문가가 없네요.ㅠ.ㅠ

제가 공부한 내용이 맞는지 확인부탁드릴께요. 다시한번 감사합니다.
---
리눅스 메모리 관리에 있어서, 여러 zone들이 node를 구성하고 NUMA같은 경우에는 여러 node가 존재하지요.

예를 들어, 각 zone들이 활발하게 사용되어서, 각 node의 normal zone들에 1GB(시스템상 총 4기가- 4 node일 때)씩만 남아 있다고 가정하고, 그 상태에서 사용자가 3G를 allocation 요청하면, 각기 다른 node의 normal zone들에서 1GB씩 받아다(물리적 비연속적 메모리) 사용자에게 할당하는 것이 맞나요? (swap은 off되어 있다고 가정할께요) physical memory 할당쪽을 보면 이게 명확하지 않아서요. vmalloc을 보면 될까요? ^^;

다시한번 감사드리고, 불쑥 질문드려 죄송합니다.