swapping의 목적은, 자주 사용되는 디스크 블럭의 디스크 캐쉬와 자주 사용되는 애플리케이션 메모리를, 자주 사용되지 않는 애플리케이션 메모리로부터 확보해, 메모리의 사용률을 높히고, 결과적으로 전체적인 시스템의 성능을 높히는데 있다.
디스크 캐쉬가 필요로 하는 메모리의 크기는 사용하는 디스크 블럭의 크기와 같다. 디스크를 전혀 읽지 않는다면, 페이지 캐쉬는 필요없고, 디스크의 대부분을 사용한다면, 최대한 많은 메모리를 디스크 캐쉬로 이용하고 싶을 것이다.
결국, (애플리케이션이 할당한 메모리의 크기) + (사용하는 디스크 블럭의 크기)를 한정된 메모리 크기 내에서 가장 효율적으로 사용하기 위한 방법이 swapping이다. 이를 뒤집어 말하면, 모든 데이터들을 담을만큼 메모리가 크다면, swapping을 할 필요는 없다는 얘기가 된다.
커널은 페이지 별로 사용 빈도를 알고 있기 때문에, 애플리케이션이 할당한 메모리의 페이지들과 디스크 캐쉬의 페이지들 가운데 어느 것이 덜 사용되는 지를 판단할 수 있으며, 기본적으로 애플리케이션이 할당한 메모리 페이지의 빈도가 낮다면 swapping을 할 것이고, 디스크 캐쉬 페이지의 사용 빈도가 낮다면 이를 해제하고 애플리케이션 메모리로 활용할 것이다.
쓸데없이 메모리만 할당해놓고 전체 디스크를 긁어대는 애플리케이션이나, 메모리 상의 대용량 데이터를 이용한 계산을 하면서 장시간동안 로그를 기록하는 애플리케이션을 상상해보면, 그리 어렵지 않게 잘 동작할 것이라고 추측할 수 있다.
하지만, 문제는 실제로 사용하는 메모리도 많으면서 사용하는 디스크 블럭도 많은 경우 – 대용량 데이터 처리를 수행하는 디스크 바운드 애플리케이션이다. 이 때, 애플리케이션이 할당한 메모리를 swap하게 되면, 다시 필요할 때, 디스크에서 읽어오기 위해 애플리케이션이 느려진다. (Thrashing) 대신 디스크 캐쉬를 줄이면, 역시 디스크의 반응속도도 느려진다. 게다가 swapping은 디스크 I/O도 느리게 만든다. 당연하게도 이러한 애플리케이션이 느려지지 않기를 원한다면, 충분한 메모리를 확보하는 수 밖에는 없다.
Swappiness에 관한 글에서 언급했듯이 리눅스 2.6 커널은 80% 이상의 메모리가 사용 중일 때, swapping을 하기 시작한다. 이러한 동작은 (특히 데스크탑에서의) responsiveness를 보장하기 위해서 이루어지는 것으로 보인다. 부수적으로 페이지 캐쉬의 크기를 보장하는 효과도 있으리라고 보인다. 1GB의 메모리를 가진 머신에서, 20% 즉, 200MB의 페이지 캐쉬를 확보하기 위한 노력이라고 보면 당연해 보이지만, 32GB의 메모리를 가진 머신에서, 위와 같은 애플리케이션을 동작시킨다면, 6.4GB의 페이지 캐쉬를 확보하기 위해 swapping을 하는 것은 비정상적일 수도 있다. 6.4GB의 페이지 캐쉬가 적절한 정도인가는 사용되는 디스크 블럭의 크기와 사용 빈도에 따라 달라질 수 있는 판단이고, swapping이 애플리케이션의 성능에 도움이 되리라는 보장은 없는 것이다. 80%가 디폴트 동작인 것은 중요만 의미가 있는 것은 아닐 듯하고, 메모리의 크기가 커질 수록 더욱 그 의미가 이상해진다.
swapping이 애플리케이션에 해를 끼치는 경우는 극단적으로 애플리케이션이 자체적으로 디스크 캐싱을 하는 경우다. MySQL이 대표적인 경우인데, 자체 캐쉬를 줄이고, 리눅스의 디스크 캐쉬를 활용할 수도 있지만, 자체 캐쉬를 사용할 경우 좀 더 효율적인 메모리 관리를 기대할 수 있다. 그렇다면, MySQL이 자체 캐쉬를 사용할 경우에, 페이지 캐쉬의 크기를 20% 정도로 유지하는 것이 의미가 있을까? 32GB 머신에서 6.4GB를 페이지 캐쉬로 확보해둔 상태에서 swap을 해야할까? (물론 MySQL이 페이지 캐쉬를 사용하지 않도록 설정해도 마찬가지다.)
이러한 경우에 Swappiness를 튜닝할 필요성이 발생하는 것 같다. 실제로 많은 MySQL 튜닝 가이드라인은 Swappiness를 0으로 만들 것을 권장하고 있다. 개인적인 생각으로는 Swappiness를 30-50 정도만 하더라도 애플리케이션이 메모리를 모두 사용하더라도 swap_tendency가 100을 넘지 않아 swap을 시작하지 않으므로 괜찮으리라 생각되지만, distress 등의 변수를 생각하면 실제 상황에서의 실험이 필요할 듯 하다. VM에 관련된 커널 동작은 커널 버전, 심지어는 2.6 내에서도 크게 달라지는 것으로 보인다. /proc/sys/vm/*의 파라미터들도 2.6 내에서 생겼다가 사라지기도 하고, 각각의 동작을 정확하게 정의하기도 어려우며, 그 파라미터들이 어울려서 어떤 동작이 나올 것인가를 예측하기란 더욱 어렵다.
결론: 대용량 데이터 처리를 수행하는 디스크 바운드 애플리케이션을 대용량 메모리 상에서 수행할 경우 Swappiness 튜닝에 신경 쓰도록 하자.