ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Node.js 메모리 옵션
    NodeJS 2023. 5. 29. 13:54

    Node.js 메모리 옵션

    테스트 케이스를 로컬에서 돌릴때는 문제 없었는데, 운영에서 실행하니 메모리 부족 오류가 발생했습니다.

    오류 로그

    <--- Last few GCs --->
    
    [1516:0x56a6a70]    93701 ms: Scavenge 1952.6 (2079.2) -> 1939.9 (2079.2) MB, 5.0 / 0.3 ms  (average mu = 0.309, current mu = 0.242) task 
    [1516:0x56a6a70]    93740 ms: Scavenge 1953.1 (2079.2) -> 1940.6 (2079.2) MB, 5.0 / 0.2 ms  (average mu = 0.309, current mu = 0.242) task 
    [1516:0x56a6a70]    93799 ms: Scavenge 1956.1 (2079.2) -> 1941.9 (2079.2) MB, 5.5 / 0.7 ms  (average mu = 0.309, current mu = 0.242) allocation failure 
    
    
    <--- JS stacktrace --->
    
    FATAL ERROR: Ineffective mark-compacts near heap limit Allocation failed - JavaScript heap out of memory
     1: 0xb09c10 node::Abort() [node]
     2: 0xa1c193 node::FatalError(char const*, char const*) [node]
     3: 0xcf8dde v8::Utils::ReportOOMFailure(v8::internal::Isolate*, char const*, bool) [node]
     4: 0xcf9157 v8::internal::V8::FatalProcessOutOfMemory(v8::internal::Isolate*, char const*, bool) [node]
     5: 0xeb09f5  [node]
     6: 0xeb14d6  [node]
     7: 0xebf9fe  [node]
     8: 0xec0440 v8::internal::Heap::CollectGarbage(v8::internal::AllocationSpace, v8::internal::GarbageCollectionReason, v8::GCCallbackFlags) [node]
     9: 0xec33be v8::internal::Heap::AllocateRawWithRetryOrFailSlowPath(int, v8::internal::AllocationType, v8::internal::AllocationOrigin, v8::internal::AllocationAlignment) [node]
    10: 0xe84632 v8::internal::Factory::AllocateRaw(int, v8::internal::AllocationType, v8::internal::AllocationAlignment) [node]
    11: 0xe7ef4c v8::internal::FactoryBase<v8::internal::Factory>::AllocateRawArray(int, v8::internal::AllocationType) [node]
    12: 0xe7f025 v8::internal::FactoryBase<v8::internal::Factory>::NewFixedArrayWithFiller(v8::internal::Handle<v8::internal::Map>, int, v8::internal::Handle<v8::internal::Oddball>, v8::internal::AllocationType) [node]
    13: 0x10e6c5b v8::internal::MaybeHandle<v8::internal::OrderedHashSet> v8::internal::OrderedHashTable<v8::internal::OrderedHashSet, 1>::Allocate<v8::internal::Isolate>(v8::internal::Isolate*, int, v8::internal::AllocationType) [node]
    14: 0x109c878 v8::internal::KeyAccumulator::AddKey(v8::internal::Handle<v8::internal::Object>, v8::internal::AddKeyConversion) [node]
    15: 0x10a14e1 v8::internal::KeyAccumulator::CollectOwnPropertyNames(v8::internal::Handle<v8::internal::JSReceiver>, v8::internal::Handle<v8::internal::JSObject>) [node]
    16: 0x10a1a8f v8::internal::KeyAccumulator::CollectOwnKeys(v8::internal::Handle<v8::internal::JSReceiver>, v8::internal::Handle<v8::internal::JSObject>) [node]
    17: 0x10a1d23 v8::internal::KeyAccumulator::CollectKeys(v8::internal::Handle<v8::internal::JSReceiver>, v8::internal::Handle<v8::internal::JSReceiver>) [node]
    18: 0x10a2733 v8::internal::KeyAccumulator::GetKeys(v8::internal::Handle<v8::internal::JSReceiver>, v8::internal::KeyCollectionMode, v8::internal::PropertyFilter, v8::internal::GetKeysConversion, bool, bool) [node]
    19: 0x10896bc v8::internal::JSReceiver::DefineProperties(v8::internal::Isolate*, v8::internal::Handle<v8::internal::Object>, v8::internal::Handle<v8::internal::Object>) [node]
    20: 0xd7c726 v8::internal::Builtin_ObjectDefineProperties(int, unsigned long*, v8::internal::Isolate*) [node]
    21: 0x15f2199  [node]
    Aborted (core dumped)

    OOM 오류 수정 방법

    OOM 오류를 해결하려면 Node.js 명령줄 옵션을 사용하여 메모리 제한을 명시적으로 구성하기만 하면 됩니다.

    # -max-old-space-size=<size_megabytes>
    
    # 사용 예제 
    $ node --max-old-space-size=2048 index.js #increase to 2GB
    $ node --max-old-space-size=3072 index.js #increase to 3GB
    $ node --max-old-space-size=4096 index.js #increase to 4GB
    $ node --max-old-space-size=5120 index.js #increase to 5GB
    $ node --max-old-space-size=6144 index.js #increase to 6GB
    $ node --max-old-space-size=7168 index.js #increase to 7GB
    $ node --max-old-space-size=8192 index.js #increase to 8GB

    사용 가이드

    메모리 값의 경우 환경, Node.js버젼의 기본값에 의존하는 대신 --max-old-space-size를 항상 명시적으로 설정하는 것이 좋습니다.

    예를 들어 메모리가 2GB인 시스템에서는 이 값을 1536(1.5GB)으로 설정하여 일부 메모리를 다른 용도로 남겨두어 메모리 스와핑을 방지하는 것이 좋습니다.

    또한 작은 컴퓨터(Raspberry Pi 보드 등)에서 Node.js를 사용하여 간단한 웹 서버를 실행하는 경우 Node.js가 소중한 메모리를 너무 많이 사용하지 않도록 128MB 정도의 작은 값으로 --max-old-space-size를 이용해 설정할 수 있습니다.

    gc 등 추가 옵션

    대용량 접속(600k concurrent websocket connections on AWS using Node.js)의 처리를 진행할 경우 gc(garbage collector)로 인해 몇초간 서버가 멈추는 현상이 발생할 수 있습니다.

    gc를 수동으로 전환하기 위해서는 다음 옵션을 사용합니다.

    $ node --trace-gc --expose-gc --nouse-idle-notification --max-new-space-size=2048 --max-old-space-size=8192 index.js
    • --nouse-idle-notification: gc 자동 실행 방지
    • --expose-gc : gc() 함수를 자바스크립트에서 직접 호출
    • --trace-gc : gc 표출 Tracing garbage collection
    • --max-new-space-size : 피크 성능을 줄여버리지만, 멈춤 시간을 짧게 가져가야 한다면 해당 값을 2048(2G) 정도로 작게 가져가면, 100ms 정도로 짧아짐
    • --noincremental-marking : 피크 성능이 중요하고 서버 멈춤을 늘려도 된다면 사용, 1GB 당 1초의 서버 멈춤 가능
    • --max-semi-space-size : 단기 객체용으로 예약된 최대 힙 크기
    • --max-executable-size : 실행 코드용으로 예약된 힙의 최대 크기(적시 컴파일된 JavaScript의 기본 코드 결과)

    참고자료

    'NodeJS' 카테고리의 다른 글

    VSCode에서 Jest Debug 설정  (0) 2023.05.31
    nestjs-pino 로깅 처리  (0) 2023.05.30
    Nodejs 동작 훑어보기  (0) 2023.05.27
    SLACK 봇 알림 처리  (0) 2023.05.26
    npm 모듈 tgz 형식으로 다운로드 받기  (0) 2022.12.20
Designed by Tistory.