Elasticsearch를 설정할 때, 공식문서에 보면 다음과 같은 권고 사항이 존재한다.
왜 이러한 설정이 필요하게 된 것인지 알아보자
JVM은 연산을 위한 데이터들을 저장하기 위한 공간으로 힙 메모리
를 사용한다. 그리고 이때 힙 메모리에 저장되는 데이터들을 오브젝트라고 부르고, 이 오브젝트에 접근하기 위한 메모리상의 주소를 OOP(Ordinary Object Pointer)
라는 구조체에 저장한다.
OOP
는 시스템의 아키텍처에 따라 32비트
혹은 64비트
의 주소 공간을 가르킬 수 있다.
64비트의 경우 32비트보다 더 넓은 주소 공간을 가리키기 위해 더 많은 연산과 더 많은 메모리 공간을 필요로 하기 때문에 성능 측면에서는 32비트보다 떨어질 수 밖에 없다. 그래서 JVM은 시스템 아키텍처가 64비트라고 하더라고 확보해야 할 힙 메모리 영역이 4GB보다 작다면 32비트 기반의 OOP를 사용해서 성능을 확보한다.
문제는 힙 메모리 영역이 4GB보다 클 경우에 발생한다. 32비트의 주소 공간을 사용하는 OOP로는 4GB 이상의 메모리 영역을 가리킬 수 없기 때문
이다. 그렇다고 64비트 기반의 OOP를 사용하게 되면 급작스럽게 성능 저하가 발생할 수 있기 때문에 JVM은 Compressed OOP
를 통해 32비트 기반의 OOP를 사용하되 4GB 이상의 영역을 가리킬 수 있도록 구현했다.
Native OOP
는 1번값을 1번 주소에, 2번값을 2번 주소에 연결하는것과 달리
Compressed OOP
는 1번값을 8의 배수인 8번 주소에, 2번값을 16번 주소에 연결한다.
Compressed OOP
는 Native OOP
에 비해 8배 더 많은 주소 공간을 표시할 수 있게 되고, 이에 따라 기존 4GB에서 32GB까지 힙 메모리 영역이 증가한다. 그렇기 때문에 힙 메모리 할당을 32GB 미만으로 하게 되면 32비트 기반의 OOP를 계속 사용할 수 있게 되고 성능 저하를 피할 수 있게된다.
Compressed OOP로 인하여 최대 32비트이 범위인 4GB에서 32GB까지 증가되었고, 최대한의 성능을 위해서는 32비트를 사용하게 하였으니 32GB보다 큰 값은 의미가 없다.
( 8GB 램을 가지고 32비트 윈도우를 설치한 꼴 )
Elasticsearch는 색인된 데이터를 세그먼트라는 물리적인 파일로 저장한다. 파일로 저장하기 때문에 I/O가 발생할 수 밖에 없는 구조
이다. I/O작업은 시스템 전체로 봤을 때 가장 느린 작업이기 때문에 빈번한 I/O 작업이 발생한다면 시스템 성능이 떨어진다
.
OS
에서는 이런 성능 저하를 막기 위해 파일의 내용을 메모리에 저장해 놓는 페이지 캐시 기법
을 사용한다. 하지만 페이지 캐시는 애플리케이션들이 사용하지 않는 미사용 메모리를 활용해서 동작
하기 때문에 페이지 캐시를 최대한 활용하기 위해서는 애플리케이션이 사용하는 메모리를 줄이는 것이 좋다. 특히 Elasticsearch와 같이 빈번한 I/O 작업이 발생해야 하는 경우 가급적 많은 메모리를 페이지 캐시로 활용해서 I/O작업이 모두 메모리에서 끝날 수 있도록 하는 것이 성능 확보
에 도움이 된다. 이런 이유로 인해 공식 문서에서는 물리 메모리의 절반 정도를 힙 메모리로 할당할 것을 권고한다. 굳이 많은 양의 힙 메모리가 필요하지 않다면 절반 이하로 설정해도 된다.
페이지 캐시를 사용하기 위해서 일정 메모리를 남겨놔야 하는데, 페이지 캐시가 구동중인 Elasticsearch의 힙메모리만큼 증가된다고 보는게 맞을듯 하다.