- 네이티브 메모리와 V8힙의 특성과 이러한 특성이 어떻게 GC 수행에 영향을 미치는가?
- 네이티브 영역에 있는 버퍼가 존재한다면, 다른 어떤 곳에 있는 버퍼가 존재 할 수 있는지와, 그 형식의 차이
- I/O 작업의 완료여부를 하드웨어로부터 전송받은 데이터를 libuv가 어떻게 인지하고 조율하는지
1. 네이티브 메모리와 V8 힙의 특성과 GC(가비지 컬렉션)에 미치는 영향
V8 힙
- 특징:
- V8 엔진은 자바스크립트 객체, 함수, 문자열 등 대부분의 동적 데이터를 관리하기 위해 힙 메모리를 사용합니다.
- 이 힙은 가비지 컬렉터(GC)에 의해 주기적으로 스캔되어, 더 이상 사용되지 않는 객체를 찾아 회수(mark-and-sweep, 혹은 mark-compact 알고리즘 등)를 수행합니다.
- GC에 미치는 영향:
- 힙 내에 많은 객체나 큰 데이터가 존재하면 GC가 해당 영역을 전부 스캔해야 하므로, GC 주기가 길어지고 애플리케이션의 응답 시간이 지연될 수 있습니다.
- GC 과정에서 힙을 잠시 멈추고 작업을 수행하기 때문에, 대규모 데이터가 힙에 존재하면 "stop-the-world" 현상이 더 빈번하게 발생할 수 있습니다.
네이티브 메모리
- 특징:
- Node.js는 Buffer와 같이 대용량 바이너리 데이터를 다루기 위해 V8 힙 외부의 네이티브 메모리(C/C++ 영역)를 사용합니다.
- 이 영역은 V8의 가비지 컬렉터의 영향을 받지 않으므로, 대용량 데이터가 GC 스캔 대상이 되지 않습니다.
- GC에 미치는 영향:
- 네이티브 메모리에 할당된 데이터는 V8 GC의 범위를 벗어나므로, GC가 해당 데이터를 스캔하거나 회수할 필요가 없어집니다.
- 결과적으로, 대용량 Buffer 데이터를 네이티브 메모리에 보관하면 V8 힙의 부하가 줄어들어, GC 주기가 짧아지고 애플리케이션의 반응성이 향상됩니다.
2. 네이티브 영역의 Buffer와 V8 힙 내의 Buffer (또는 유사 데이터 구조)의 형식 차이
네이티브 영역에 할당된 Buffer (Node.js Buffer)
- 구현:
- Node.js의
Buffer
객체는 C/C++로 구현되어 있으며, 실제 바이너리 데이터는 V8 힙이 아닌 네이티브 메모리에 할당됩니다.
- 이 방식은 대용량 데이터를 효율적으로 처리할 수 있도록 도와주며, GC 부담을 줄입니다.
- 특징:
- 직접 할당: 메모리 관리가 C/C++ 레벨에서 이루어지며, V8 GC가 개입하지 않습니다.
- 추가 API 제공: Buffer 클래스는 다양한 인코딩(예: UTF-8, Base64) 변환, 슬라이싱, 복사 등의 유틸리티 메서드를 제공합니다.
V8 힙에 존재하는 유사 Buffer (ArrayBuffer
및 TypedArray
)
- ArrayBuffer와 TypedArray:
- 자바스크립트의
ArrayBuffer
는 바이너리 데이터를 저장할 수 있는 기본 객체이며, 이를 기반으로 하는 Uint8Array
, Float32Array
등의 TypedArray
는 V8 힙에 할당될 수 있습니다.
- 그러나 V8은 내부적으로 외부 메모리 할당을 지원하기도 하여, 필요에 따라
ArrayBuffer
의 데이터 영역을 네이티브 메모리에 할당할 수 있습니다.
- 차이점:
- 일반적으로 Node.js의
Buffer
는 추가 기능과 최적화를 위해 독자적인 네이티브 메모리 할당 방식을 사용합니다.
- 반면, 순수
ArrayBuffer
나 TypedArray
는 자바스크립트 표준에 따른 동작을 보이며, V8 힙 내에서 관리될 수도, 외부 메모리로 할당될 수도 있습니다.
- 형식적으로는
Buffer
는 Uint8Array
를 확장한 형태로 볼 수 있지만, 사용 용도와 API, 메모리 관리 측면에서 차이가 있습니다.
3. I/O 작업 완료 여부 감지 및 libuv의 조율 메커니즘