Performance degradation seen after using one list for hot/cold pages Jun 25, 2009

얼마전 보고된 내용이다.

http://marc.info/?l=linux-mm&m=124565003222392&w=4

I/O performance가 degradation되었다는 내용이다.
문제의 원인은 Mel의 PCP 패치때문이었다.
PCP는 원래 hot/cold의 분리된 list로 관리되고 있었지만, Mel은 그 2개의 list를 하나로 합치면서
cold page는 뒤에서부터 할당하고, hot page는 앞에서부터 할당하였다.

그래서 발생한 문제가 cold page에 대해서 기존에는 A-B-C-D의 연속된 페이지의 순서로 할당되었던 PFN들이
이제는 D-C-B-A의 order로 할당될 수 있다는 것이다. 이는 연속된 order의 buffer들을 merge하여 처리할 수 있는
I/O device의 성능 저하를 초래하게 된다.

현재 page allocator는 PCP를 채울때 연속된 페이지의 order를 유지하려고 애쓴다. 이 또한 그러한 I/O device들을 염두에 둔 것이다. 하지만 Mel의 PCP 패치가 이 약속을 깨버린 것이다.

Mel은 이 report에 대해서 이미 알고 있었지만 왜 인지 당시에 patch는 만들지 못하였다.
이번 패치는 이 문제를 해결하기 위해서 PCP에 page를 add할때 cold 페이지의 경우에 역순으로 배치하여,
나중에 연속된 page의 순서대로 할당 가능하게 해준다.

이문제에 대해서 barrios가 이 바쁜 시간(대체 요근래 모하고 사는지를 모르겠다. 내가 정말 엔지니어인지에 대하여 심각하게 고민을 하고 있는 중)을 짬내어 언급하는 이유는 이문제가 국내의 기업이 report한 문제이기 때문이며, report를 했던 이는 이미 이 문제의 원인에 대해서 알고 있었기 때문이다.

국내 기업이 이런 critical한 report를 OpenSource 진영에 하는 것은 사실 처음 봤기 때문이다.
국내 기업의 Open Source에 대한 자세가 긍정적으로 변한 것일까?..
하지만 아쉽게도 올린이가 외국인인 것으로 봐서 해외 연구소의 연구원일 것으로 생각된다.
아마도 국내에서는 쉽게 저런 글을 함부로 report하지 못했을 것이다.
아침부터 쓸쓸하구만.

Common OOM killer Problem in Embedded System Jun 23, 2009

금일 report된 Oops이다.

http://lkml.org/lkml/2009/6/22/604

친절하게 Kame-san이 원인을 잘 설명해주고 있다.

이번 문제는 사실 swap device를 가지고 있지 않은 Embedded System에서는 흔한 문제이다.
문제를 살펴보면,
먼저, 메모리 할당 실패는 order 2, 즉 16K의 연속된 메모리 할당에 있어 실패하였다.

Total : 256M
LRU(active + inactive) : 75M
unevictable : 124M
SLAB : 6M
Free + pagetable : 29M

위의 메모리 상태를 보면 시스템의 Memory leack은 아닐것이라고 추측해 볼 수 있다.
또한 위의 정보를 통해 알 수 있는 내용은
1. unevitable이 저렇게 많이 채워져 있는 이유는 tmpfs를 rootfs로 사용했기 때문이라고 추측할 수 있으며
2. file lru가 거의 비워져 있는 것으로 봐서 이미 memory pressure가 상당했다는 것이다.

다음으로 buddy를 살펴보자.

Normal: 1445*4kB 1781*8kB 15*16kB 2*32kB 1*64kB 0*128kB 0*256kB 0*512kB 0*1024kB 0*2048kB 0*4096kB = 20396kB


16k의 연속된 페이지가 15개나 있다. 또한 64k도 하나 있고..
그럼 왜 OOM이 발생한 것일까?

Kame-san이 친절히 얘기해 준 것처럼 zone_watermark_ok의 zone defensive algorithm 때문이다.
(사실 Kame의 계산은 조금 틀렸다. 하지만 zone_watermark_ok가 fail한 건 사실이니.)

많은 embedded system들이 swap device가 없음으로 인해 anon page들을 회수할 수 없게 되고 그로인해 memory fragmentation 문제가 심각해져 발생하는 문제이다. (갑자기 떠오른 생각을 적어 놓는다. no swap system의 lumpy reclaim은 anon page를 고려해야 한다!)

이를 해결하는 방법은 swap을 사용하거나 app 메모리 사용량을 줄이거나..
또는 아직 검증되진 않았지만 compcache(http://lwn.net/Articles/334649/)와 같은 방법을 사용하거나...

Misleading OOM messages May 17, 2009

http://lkml.org/lkml/2009/5/12/353

Christoph가 최근 android로 인해 이슈가 되고 있는 OOM 메시지에 대한 오해를 화두로 던졌다.

"Out of memory" => 메모리를 다 소비했다는 것이다.

Christoph는 OOM은 대부분 커널 내부의 메모리 회수의 실패이지 실제 메모리가 부족해서 발생하는 문제는 아니라고 말하고 있다. 그런 반면, 많은 user들은 이 잘못된 메시지를 보고 "시스템이 충분한 메모리를 가지고 있지 않구나!" 생각하고 user들이 많은 메모리를 할당할 수 없도록 ulimit 값을 낮추는 경우가 있다고 말하고 있다.
이것은 OOM의 메시지에 대한 오해에서 비롯되는 현상이며 이 오해는 커널에서 출력하는 OOM message에서 기인하는 것이다. 그러므로 Christoph는 OOM message를

"Failure to reclaim memory"
으로 바꾸자고 제안하고 있다.

이에 대해 예전부터 OOM을 작성해왔던 suse의 Pavel Machek은 현재 OOM의 메시지는 이상이 없다고 생각하고 있으며 여러 상황을 예로 들며 실제 메모리를 추가해야 하는 상황을 언급하고 있다. 그러므로 현재 OOM message는 이상이 없다고 주장하고 있다.

또한, IBM의 Dave Hansen은 자신이 만난 OOM message중 단한번도 시스템의 free page가 0이어서 발생한 적은 없다고 말하고 있다. 단지 시스템의 free page가 zone->watermark이하인 상태에서 회수가 더 이상 진행되지 못한 경우에 발생하고 있다고 전하고 있다. 현재 OOM message의 문제점은 전체 스토리를 이야기하지 못하고 마지막 결과만을 이야기 한다는 것이 문제라고 지적하고 있며 다음과 같은 메시지가 좋지 않겠냐고 제안하고 있다.

"Unable to satisfy memory allocation request and not making
progress reclaiming from other sources."

하지만 console에 위와 같은 한두줄의 출력에 큰 의미를 두는 것 보다는 http://linux-mm.org/OOM 와 같이 웹 페이지에 보다 자세한 정보를 담는 것이 좋을 것 같다고 한다.

이에 대해 Andorid의 low memory killer를 담당하고 있는 David Rientjes은 OOM message를 다음과 같이 바꾸자고 제안하고 있다.
"No [available/allowable] memory"

cpuset allocator와 같은 경우도 현재 OOM을 출력하고 있는데 시스템에 물리 메모리가 많은 상태에서 cpuset hardwall로 인해서 메모리 할당이 실패했음에도 불구하고 out of memory를 출력한다는 것이다. 또한 watermark로 인해서 실패하는 것도 out of memory보다는 No available memory리가 보다 make sense하다는 것이다.

No available memory는 out이라는 단어 사용을 하지 않았기 때문에 user들로 하여금 memory를 더 두어야 한다는 사실보다는 swap을 추가하거나, cgroup limit을 바꾸거나, 실제 메모리를 더 추가하거나와 같은 뉘앙스를 줄 수 있게 된다. 그러므로 완벽한 solution은 아니지만 out 이란 단어를 사용하는 것 보다는 훨씬 좋다.

아직까지 어떤 메시지를 출력하는 것이 좋을지에 대해서는 consensus가 만들어지지는 않고 있지만 현재 OOM message의 문제점에 대해서는 대부분 공감하고 있는 것으로 보인다. 그러므로 머지 않아 우리는 친숙한 Out of memory 메시지를 보지 않게 될지도 모르겠다.

Kernel Shared Memory May 7, 2009

현재 barrios가 관심을 가지고 있는 feature는 KSM(kernel shared memory)이다.

http://lkml.org/lkml/2009/5/4/400


기능의 이름만으로는 어떤 역할을 하는 것인지 쉽게 예측하기 어려울 수 있다.
안그래도 Hugh는 이 패치의 이름을 바꿀 것을 제안하였다.

이 기능의 목적은 user level의 shared memory와는 전혀 관련이 없다.
이 패치가 이루고자 하는 목적은 application들의 page중 동일한 데이터를 가지고 있는 page들을
하나의 page로 merge하고 나머지 page들은 free시켜 주자는 것이다.(이것은 user level의 shared memory와는 전혀 관련이 없다)
이것이 user application에게 transparent하게 동작할수 있는 이유는 merge된 하나의 페이지를 COW로 만들기 때문이다.

이 패치는 KVM을 primary target으로 개발되어졌지만 general한 approach로 만들어졌기 때문에
일반 application들도 sysfs의 KSM node에게 ioctl을 사용하여 자신의 address range를 KSM에게 등록할 수 있다.

이 패치를 개발하고 있는 Redhat의 Izik Eidus은 이 기능으로 KVM이 많은 메모리 이득을 본다고 얘기하고 있지만, 아직까지 어떤 benchmark 결과는 내놓지 않고 있다. 하지만 KVM과 같은 virtualization solution들에게 이득이 지될 수 밖에 없는 이유는 VMM 위의 guest들은 host memory를 유사한 kernels, librarys, cache와 같은 데이터로 채우게 될 것이기 때문이다. 또한 Jared Hulbert는 embedded 환경에서도 10% 정도의 memory save를 할 수 있었다고 말하고 있지만, 어떤 test 환경에서 어떤 application들을 테스트 했는지에 대해서 언급이 없기 때문에 사실 얼마나 이득이 될지 예측할 수는 없다.

현재 이 패치는 여러 design issue를 가지고 있다. 그 중 가장 대표적인 것이 user application과의 interface이다. 현재는 sysfs의 ksm node를 통해 ioctl을 통해 application들은 자신의 virtual address range를 등록할 수 있게 되어 있다. 하지만 Rik과 Hugh는 이 interface보다는 madivse와 가은 기존의 system call을 더 선호하고 있다. interface는 결국 madivse로 바뀔 것으로 보이며, 이 기능이 module로 들어갈 것인지 커널에 built-in으로 해서 VM code들의 약간의 수정과 함께 들어가게 될 것인지도 확실지 않다. 또한 rmap의 hooking을 통해 page들을 shared page들을 tracking하게 될지 또한 명확하지 않다.

COW and Direct I/O problem Apr 17, 2009

barrios는 이 문제에 대해서 작년에 살짝 언급한 바 있다.
http://barriosstory.blogspot.com/2008/12/corruption-with-odirect-and-unaligned.html

사안이 사안이니만큼 한번 더 언급하기로 한다.
사실 이것은 리눅스 커널의 전형적인 core bug이다. 그러므로 이 문제를 이해하기 위해서는 kernel core의 page handling과정에 대한 이해가 필요하다.

이 문제를 다시 언급하는 이유는 두가지이다.

1. 이 문제는 아직 리눅스 커널에서 해결되지 못하고 있다.
2. 이 문제를 보고서도 뭐가 문제인지조차 알기 쉽지 않다는 것이다.

1에 대한 comment

해결되지 못하는 이유는 Linus때문이다. 이미 Nick과 Andrea는 이 문제를 풀기위한 solution을 진작에 내놓았었다. 성능을 최대한 떨어뜨리지 않으면서 이 문제를 풀기 위해 code가 다소 복잡하다.
반면 Kosaki가 내놓은 이 패치는 간단하긴 하지만(하지만 아직도 fast gup에 대한 concurrency 문제와 fork에 대한 latency, 특히 이 fork의 문제는 다소 심각해질 것 같다. 오늘 날짜로 보고된 Christoph의 report에 따르면 fork의 overhead가 2.6.22에 비해서 2.6.29는 2배 이하로 커진 것을 알 수 있기 때문이다.) 아직 많은 지적이 있다. 하지만 Linus는 코드수의 변경이 적은 Kosaki의 패치에 손들 들어주었다. Linus는 그때까지만 해도 fork에 대한 overhead는 크지 않다고 봤다. 물론이다. fork와 O_direct가 race condition이 될 확률은 크지 않다. 하지만 direct I/O가 계속해서 발생하게 되면 fork는 starvation 문제를 가질 수도 있으며, 안 그래도 overhead가 심각한 현재 fork의 구조에서 또 다른 lock을 check하는 것은 좋은 생각이 아닐 수도 있다.

2에 대한 comment

이 문제에 관심을 가질수 있는 사람들을 위해 barrios는 최대한 쉽게 설명할 수 있는 그림을 그려 보았다. 여기까지가 barrios가 할 수 있는 최선이다.

아래 그림은 이 패치의 테스트 프로그램이 왜 실패하는지에 대한 설명을 하는 그림이다. 패치의 테스트 프로그램과 함께 이 내용을 보아야 한다.

mm: more likely reclaim MADV_SEQUENTIAL mappings Apr 11, 2009

http://lkml.org/lkml/2008/7/19/130

이번 2.6.29에 패치된 기능중의 하나이다.
Hannes에 의해 추가되었으며, Rik과 Nick간의 다소 격양된 언쟁이 있었던 패치이기도 하다.
어쨌든, Andrew는 이 패치의 유용성에 대해 인정하였으며, 이번 2.6.29에 반영되었다.

Barrios가 2008년 7월에 언급되었던 이 패치를 지금 다시 이야기 하는 나름데로의 이유가 있다.

먼저 이 패치가 이루고자 하는 목표는 Page 회수를 좀더 똑똑하게 하자는 것이며,
리눅스 커널의 Man page의 madvise에 대한 기능을 완수하기 위한 것이기도 하다.

먼저 madvise의 man page를 살펴보면 다음과 같은 언급이 있다.


The madvise() system call advises the kernel about how to handle paging input/output in the address range beginning at address start and with size length bytes.
...
MADV_SEQUENTIAL
Expect page references in sequential order. (Hence, pages in the given range can be aggressively read ahead, and may be freed soon after they are accessed.)

위와 같이 sequential한 access는 첫째, readahead를 보다 공격적으로 하기 시작할 것이다.
둘째, 그리고 그 페이지들을 곧 회수될 수 있다.

리눅스 커널은 현재까지 첫째에 대해서는 충실했었지만 둘째에 대해서는 충실하지 못했다.
이번 패치는 Hannes에 의해 두번째 문제를 충족시켜주기 위한 패치이다.
패치는 정말 간단하다. 페이지를 promotion 시키기 전, vma의 seqential access 체크를 하여
그렇다면 promotion 시키지 않는다는 것이다.
즉, inactive list에 있는 page들을 active list로 옮기기 위한 확률을 줄이는 것이다. 그러므로 page reclaimer는 sequential access 페이지들을 보다 빨리 회수할 수 있게 된다.
이는 결과적으로 시스템의 working set들을 유지하는 데 도움을 주게 되므로 시스템의 전반적인 성능 또한 향상 시킬 수 있다.


많은 시스템 프로그래머들은 데이터 파일을 읽어들여본 경험이 있을 것이다.
물론 random한 offset으로 파일을 읽어들이는 경우도 많지만, 동영상을 재생하는 경우나 파일을 복사하는 경우, 또는 파일을 읽어들여 네트워크로 전송하는 경우와 같이 데이터 파일을 sequential하게 읽어들여야 하는 경우도 많이 있다.

이 블로그를 읽고 있는 사람이라면 너무나도 잘 알듯이 리눅스 커널의 메모리 관리 정책은 파일에 대한 접근을 모두 page cache에 보관하게 된다는 점을 잘 알고 있을 것이다.

위와 같은 스트림 데이터들을 page cache에 보관하면 어떤 이점이 있을까?
없다.

하지만 커널에서는 유저가 스트림 데이터와 같이 한번 접근하고 나서는 불필요한 파일을 접근하는지, 아니면 두고두고 참조할 파일을 정확하게 알 수 있는 방법은 없다. 그래서 나름데로 커널은 readahead 정책을 활용하여 heuristic하게 적용한다.

그러므로 파일의 사용패턴을 그 누구보다 잘 아는 것은 application 그 자신이다.
Application은 자신이 사용할 파일이기 때문에 어떻게 그 파일을 사용할 것인지 이미 알고 있다.
그러므로 이런 Application들이 커널에게 hint를 준다면 얼마나 고마운 일인가 ?

그러면 커널은 그러한 hint가 없다면 무엇을 하는가?

리눅스 커널의 page reclaim 관련 루틴들은 자주 참조되는 페이지와 그렇지 않은 페이지들을 잘 관리해보려고 애쓴다. 애는쓰되 효율적이지 못할 경우도 있다.
커널은 최선을 다할 뿐이지 결과는 장담할 수 없다.

너무 커널이 무책임하다고 생각하는가?

그렇게 커널이 무책임하지는 않다.
그래서 커널이 제공하는 시스템 콜이 mdvise, fadvise, open(O_DIRECT)와 같은 것들이
있는 것이다.

최소한 지각있는 application 개발자라면 커널에게 hint 정도는 줄 수 있는 것 아닌가?

내가 지금부터 이 파일을 sequential하게 읽을거야!
정도는.

응용 프로그램 개발자들은 최소한 커널이 제공하는 수준의 시스템 콜을 잘 이용할 수 있는 의무와 권리가 있다.
이를 이행하지 않으며 모든 것을 커널에게 맡기겠다는 것은 사실 응용 어플리케이션 개발자들의 직무유기이다.

꼬랑지)
Kernel이 applictaion들을 위해 얼마나 많은 것들을 제공해주어야 하는지에 대한 논쟁은 언제나 뜨거운 감자이지만, 새로운 기능을 넣고자 하는 자는 언제나 자신의 기능에 대한 benefit이 기존의 커널에 대한 regression보다 우월하다는 쉽지 않은 증명을 해야만 할 것이다.

Memory Failure Report throuth MCE Apr 9, 2009

http://lkml.org/lkml/2009/4/7/368

Intel의 앞으로 나올 CPU에 background로 memory를 check하여 error를 report해주는 기능이 들어간다고 Andi는 전하고 있다.
Report는 기존의 x86 specific한 Machine Check Exception을 그대로 사용할 것이며, MCE register를 통해 error가 발생한 물리 주소를 얻을 수 있게 된다.

그러므로 OS가 이 기능을 적절히 활용하기 위해서 Andi는 하드웨어가 나오기전 먼저 Linux OS에 대해서 상기 기능을 어떻게 활용할 것인지에 대해 RFC를 내놓았다.

Andi가 이번 패치에서 주 target으로 정한 것은 KVM이다. Host에서 error정보를 전달 받아 그 내용을 KVM guest들에게 전달하기 위한 설비이다. 하지만 이 기능은 KVM에 종속되지 않으며 얼마든지 다른 응용 프로그램들도 사용할 수 있도록 generic하게 설계되었다.

정보를 알리는 방식은 새로운 signal을 사용하는 방식이며, error가 발생한 page의 특성에 따라 다르게 동작한다.

1. slab page
2. reserved page
3. page cache clean page
4. page cache dirty page
5. unknown page
6. free page
7. swap clean page
8. swap dirty page
9. anonymous page
10. unevictable page
11. huge page
12.compound page

하지만 현재는 RFC단계로 위의 모든 type에 대해 구현되어 있지 않은 상태이다.

이 패치의 tricky한 part는 다른 VM 사용자들의 page에 대해 비동기적으로 접근하게 된다는 점이다. 그것은 page 동기화에 대한 rule을 해치는 일이 될 수 있기 때문에 매우 조심해야 한다. Andi가 이 패치에 대해 제일 걱정하는 부분이 바로 이 부분이다. 리눅스 커널의 page관련 lock 처리는 매우 골치아픈 부분이다.

현재, mainline에서 이 패치의 기능에 대해서는 모두 수긍하는 편이며 구현 또한 RFC 단계 치고는 상당히 깖끔하다. 앞으로 남은 주제는 아직 구현되어 있지 않은 page type에 대해 어떻게 처리할 것인가와 함께 비동기적인 page에 대한 접근에서 발생할 수 있는 문제에 대한 coverage등이 될 것으로 보인다.

이 패치는 하드웨어적으로 아직 들어가 있지 않은 구현에 대한 검증을 위해서 소프트웨어적으로 프로세스의 page를 poisoning할 수 있는 별도의 test 기능까지 구현되어 있다.

꼬랑지)
이 패치를 보면 Andi가 속한 Intel의 Open Source Lab이 무엇을 하는지 잘 알 수 있다.
아직 시장에 나오지 않은 기능에 대해 OS community에 선행 학습을 시키며 앞으로 나올 자신들의 하드웨어의 판매전략을 위해 기존 OS에 미리 기능을 구현해 놓겠다는 것인데..

아직까지도 하드웨어에만 목을 매는 우리나라의 몇몇 기업들의 우둔한 전략에 대해 할말이 너무나도 많지만..