본문 바로가기
카테고리 없음

[Java] On-heap과 Off-heap

by 왕 달팽이 2020. 8. 10.
반응형

JVM 리소스와 관련된 자료를 찾아보다가 'On-heap'과 'Off-heap'이라는 단어를 발견하게 되었다. 자바 프로그래밍에서 선언된 객체가 힙(Heap) 영역에 관리된다는 내용은 잘 알고 있지만 On-heap과 Off-heap이라는 구체적인 용어는 생소할 수 있다..

On-heap Store

Java 프로그램에서 new 연산 등을 이용해 객체를 생성하면 JVM은 힙(Heap) 메모리 영역에 객체를 생성하여 저장, 관리한다. C/C++과 다르게 Java에서는 명시적으로 할당받은 메모리 영역을 해제하는 등의 조치는 취하지 않아도 된다. GC(Garbage Collection) 알고리즘이 귀찮고 어렵고 문제를 발생시킬 수 있는 메모리 관리를 대신 해주기 때문이다.

Java에서 생성된 객체가 저장되는 힙 영역을 좀 더 자세하게 On-heap store라고 한다.

일반적인 경우라면 On-heap 영역만 인지하고 사용해도 애플리케이션을 작성하는데 문제는 없다. 하지만 언제나 그렇듯 우리는 항상 그냥 동작하는 것보다 좀 더 빠르게 동작하는 것을 찾아야 한다.

On-heap store에 객체를 저장하다보면 GC 오버헤드(특히 Full GC)때문에 애플리케이션의 성능이 저하되는 경험을 하게 된다. 특히 굉장히 큰 사이즈의 데이터를 생성한다던가, 굉장히 많은 숫자의 객체를 생성한다던가하면 GC 대상 객체들의 증가로 애플리케이션이 버벅일 가능성이 높아진다.

특히 실시간에 가까운 데이터 처리를 해야하는 빅데이터 플랫폼의 경우 Off-heap 사용을 고려해봐야 할 수도 있다. Full GC가 실시간성을 저해할 수 있기 때문이다. (Pause 때문)

물론 JVM에서는 좀 더 똑똑한 GC 알고리즘을 제공하고 있긴 하지만 애플리케이션 단에서 메모리 사용시 불필요한 GC를 발생시키지 않도록 하는 방법도 있다.

Off-heap Store

Off-heap store는 '힙 밖에 저장한다'라는 의미를 가지고 있다. 힙 밖에 저장한다는 의미는 GC 대상으로 삼지 않겠다는 의미다.

Java에서는 nio를 통해 Off-heap store의 사용을 제공하고 있다. Direct ByteBuffer를 이용해 할당받은 버퍼 공간은 GC의 대상이 되지 않는 Off-heap store에 저장된다. (다만 GC가 대신해주는 메모리 관리 등을 직접 애플리케이션이 해줘야 하기 때문에 번거롭고 위험할 수 있다. 때문에 EHCache, Terrcotta BigMemory 같은 Off-heap store를 이용한 캐시 라이브러리를 사용하는게 좋다. (걔네들이 잘 관리해준다.)

Off-heap store에 저장되는 객체는 직렬화(Serialize)한 다음 저장해야한다. 이런저런 이유로 Allocation/Deallocation 비용이 일반 버퍼에 비해 높다. 때문에 Off-heap store에 저장되는 객체는 사이즈가 크고(Large) 오랫동안 메모리에 살아있는(Long-lived) 객체이면서 시스템 네이티브 I/O 연산(Memory Mamped I/O 같은..)의 대상이 되는 객체를 사용하는게 좋다.

이처럼 Off-heap을 사용해서 성능 향상이 있는게 보장되는 경우에만 Off-heap을 쓰는게 좋다.

Off-heap으로 객체들을 옮겨 On-heap 사이즈를 줄이게 되면, Full GC로부터 발생할 수 있는 성능 저하 요인이 많이 저감된다.

반응형

댓글