Node.js(V8)에는 ‘AlwaysPreTouch’ 기능이 없으며, JVM에서 Pretouch를 하는 주된 이유는 런타임 중의 페이지 폴트로 인한 지연을 최소화하기 위해서임. Java 애플리케이션처럼 메모리를 크게 잡고 길게 운용하는 시나리오가 아니라면, V8(JavaScript)은 기본적인 메모리 할당 방식을 통해 충분한 효율을 발휘함
- Node.js(V8 엔진)에는 JVM의 AlwaysPreTouch 같은 개념이나 옵션이 존재하지 않음
- Java의 AlwaysPreTouch는 JVM이 큰 힙 메모리를 할당받을 때, 운영체제 레벨에서 페이지를 미리 터치(touch)하여 실제 물리 메모리를 확보해 두는 기능, 이를 통해 런타임 도중에 발생할 수 있는 페이지 폴트(page fault)를 미리 처리함으로써, 애플리케이션 동작 중의 지연(latency)을 줄이는 효과가 있다고 함
- 하지만 Node.js(V8 엔진 기반)에는 AlwaysPreTouch 같은 설정이 없음. 그 이유는 아래와 같음
- JVM
- Java는 JVM 시작 시에 설정된 힙(Heap) 크기만큼 메모리를 예약(Reserve)한 뒤, 옵션에 따라 그 힙 전체를 물리 메모리로 미리 할당할 수 있음
- AlwaysPreTouch를 활성화하면, JVM이 시작할 때 힙의 모든 페이지를 한 번씩 접근해서 실제 물리 메모리에 매핑
- V8(JavaScript 엔진)
- JavaScript 엔진(V8)은 힙을 점진적으로 확장하며, 필요할 때마다 운영체제에 메모리 할당을 요청
- 한 번에 크게 할당해두는 방식이 아니므로, JVM처럼 모든 페이지를 미리 터치할 수 있는 옵션을 제공하지 않음
- 런타임 엔진 특성
- Java 애플리케이션은 한 번 실행하면 오랜 시간 계속 동작하며, 대용량 서버 애플리케이션으로 사용되는 경우가 많음
- 따라서 큰 힙을 잡고, 그 메모리를 효율적으로 관리하기 위해 미리 물리 메모리에 매핑하는 전략이 효과적일 수 있음
- 반면, JavaScript(V8)는 브라우저 환경, 짧은 실행 스크립트, 혹은 Node.js 서버 환경에서 동작하더라도, 상대적으로 더 가볍거나 재시작이 잦은 경우가 많음. 이러한 특성상, 큰 힙을 잡고 모든 페이지를 미리 터치하는 옵션이 일반적으로 필요하지 않은 경우가 많음
- Node.js(V8 엔진)의 플래그
- Node.js에서는
--max-old-space-size,--initial-old-space-size같은 V8 플래그를 통해 힙 최대 크기 등을 설정할 수 있음 - 다만, 이는 어디까지나 힙 크기를 ‘얼마까지 쓸 수 있는지’를 정하는 플래그일 뿐, JVM의 AlwaysPreTouch처럼 힙 전체를 한 번에 물리 메모리에 매핑시키는 기능은 제공하지 않음
- Node.js에서는
- JVM은 왜 AlwaysPreTouch를 할까?
- 자바 애플리케이션, 특히 대규모 서버 애플리케이션이나 긴 배치 작업 같은 경우에는 처음부터 큰 힙을 잡고 장시간 동작하는 시나리오가 많은듯?
- 운영체제는 일반적으로 Lazy Allocation(지연 할당) 전략을 사용하기 때문에, JVM이 큰 힙을 예약했어도 실제 메모리를 언제 할당할지는 아직 모름
- Lazy Allocation
- OS가 페이지를 예약만 해둔 상태에서는, 애플리케이션이 해당 페이지를 실제로 접근하기 전까지 물리 메모리를 배정하지 않습니다(가상 메모리 시스템)
- 즉, 애플리케이션이 페이지를 처음 쓰는 순간에 페이지 폴트(page fault)가 발생하고, 그 시점에 물리 메모리가 매핑
- 런타임 중 지연 감소
- 애플리케이션이 동작 도중에 갑자기 많은 객체를 할당하거나, 특정 시점에 처음으로 힙 일부를 접근하면, 그때서야 대량의 페이지 폴트가 발생할 수 있음
- AlwaysPreTouch로 JVM이 시작할 때 힙 전체를 미리 접근함으로써, 필요한 물리 메모리를 시작 시점에 전부 매핑시켜둠
- 이렇게 해두면, 런타임 도중에는 페이지 폴트를 일으킬 일이 없어지므로, latency가 훨씬 줄어들 수 있음
- 예측 가능성
- 서비스가 시작될 때 한 번의 오버헤드가 발생하지만, 이후에는 일관된 성능을 보임
- 대규모 서비스에서는 예측 불가능한 순간에 발생하는 페이지 폴트가 짧은 순간의 응답 지연을 일으킬 수 있는데, 이를 최대한 피하고 싶을 때 AlwaysPreTouch가 유효한 선택지가 됨
- AlwaysPreTouch를 비활성화한다면,
- 각 페이지에 실제로 접근하는 시점에 물리 메모리가 할당됨
- 일반적으로는 문제가 없을 수도 있지만, 특정 시점에 갑자기 대량의 할당이 일어날 경우 그 때 페이지 폴트들이 연쇄적으로 발생해 일시적인 성능 저하가 생길 수 있음
- 즉, 서버가 거의 사용하지 않다가 트래픽이 몰려 갑자기 객체를 생성해야 하는 상황에서, 페이지 폴트 처리로 인해 지연이 발생할 수 있음
- 궁금증
- 서비스 이용해서 응답 시간 느린게 얼마나 문제가 되는지?
- 페이지 폴트 때문에 발생하는 응답시간 레이턴시가 치명적인가? 서비스 이용에 많은 불편을 주나?
- 자바스크립트(V8)
- 힙이 점진적으로 확장되며, 큰 힙을 미리 통째로 할당해둘 필요가 적어서 JVM의 AlwaysPreTouch와 같은 개념이 제공되지 않음
- JVM(특히 대규모 서버 애플리케이션)
- 한 번에 큰 힙을 잡고 오래 운용하는 경우가 흔하므로, 런타임 중의 대규모 페이지 폴트를 방지하기 위해 -XX:+AlwaysPreTouch 옵션을 사용할 수 있음