웹 프론트엔드 JS 튜토리얼 Node.js의 메모리 제한은 정확히 무엇입니까?

Node.js의 메모리 제한은 정확히 무엇입니까?

Dec 25, 2024 am 04:35 AM

What Exactly Is the Memory Limit of Node.js?

Node.js API에 능숙하면 빠르게 작업을 진행할 수 있지만 Node.js 프로그램의 메모리 사용량을 깊이 이해하면 더 많은 작업을 수행할 수 있습니다.

process.memoryUsage()를 사용하여 메모리 사용량을 살펴보고 매초 업데이트하면서 시작하겠습니다.

setInterval(() => { console.log('Memory Usage:', process.memoryUsage()); }, 1000);
로그인 후 복사
로그인 후 복사

출력이 바이트 단위이므로 사용자에게 친숙하지 않습니다. 메모리 사용량을 MB:
로 형식화하여 정리하겠습니다.

function formatMemoryUsageInMB(memUsage) {
    return {
        rss: convertToMB(memUsage.rss),
        heapTotal: convertToMB(memUsage.heapTotal),
        heapUsed: convertToMB(memUsage.heapUsed),
        external: convertToMB(memUsage.external)
    };
}

const convertToMB = value => {
    return (value / 1024 / 1024).toFixed(2) + ' MB';
};

const logInterval = setInterval(() => {
    const memoryUsageMB = formatMemoryUsageInMB(process.memoryUsage());
    console.log(`Memory Usage (MB):`, memoryUsageMB);
}, 1000);
로그인 후 복사
로그인 후 복사

이제 매초 다음 출력을 얻을 수 있습니다.

Memory Usage (MB): {
  rss: '30.96 MB', // The actual OS memory used by the entire program, including code, data, shared libraries, etc.
  heapTotal: '6.13 MB', // The memory area occupied by JS objects, arrays, etc., dynamically allocated by Node.js
                      // V8 divides the heap into young and old generations for different garbage collection strategies
  heapUsed: '5.17 MB',
  external: '0.39 MB'
}

Memory Usage (MB): {
  rss: '31.36 MB',
  heapTotal: '6.13 MB',
  heapUsed: '5.23 MB',
  external: '0.41 MB'
}
로그인 후 복사

V8 엔진의 메모리 사용량은 OS의 메모리 관리 및 리소스 할당 정책뿐만 아니라 자체 설정에 의해서도 제한된다는 사실은 모두가 알고 있습니다.

os.freemem()을 사용하면 OS에 얼마나 많은 여유 메모리가 있는지 확인할 수 있지만 그렇다고 Node.js 프로그램이 모든 메모리를 확보할 수 있다는 의미는 아닙니다.

console.log('Free memory:', os.freemem());
로그인 후 복사

64비트 시스템의 경우 Node.js V8의 기본 최대 이전 공간 크기는 약 1.4GB입니다. 즉, OS에 사용 가능한 메모리가 더 많아도 V8은 자동으로 이 한도 이상을 사용하지 않습니다.

팁: 이 제한은 Node.js를 시작할 때 환경 변수를 설정하거나 매개변수를 지정하여 변경할 수 있습니다. 예를 들어, V8이 더 큰 힙을 사용하도록 하려면 --max-old-space-size 옵션을 사용할 수 있습니다:

node --max-old-space-size=4096 your_script.js
로그인 후 복사

이 값은 실제 상황과 시나리오에 따라 설정되어야 합니다. 예를 들어, 메모리가 많고 독립 실행형으로 배포된 머신이 있고 분산 방식으로 배포된 소형 메모리 머신이 많은 경우 이 값에 대한 설정은 확실히 다릅니다.

메모리가 오버플로될 때까지 배열에 데이터를 무한정 채워서 테스트를 실행하고 언제 발생하는지 살펴보겠습니다.

const array = [];
while (true) {
    for (let i = 0; i < 100000; i++) {
        array.push(i);
    }
    const memoryUsageMB = formatMemoryUsageInMB(process.memoryUsage());
    console.log(`Memory Usage (MB):`, memoryUsageMB);
}
로그인 후 복사

프로그램을 직접 실행하면 나오는 내용입니다. 잠시 동안 데이터를 추가한 후 프로그램이 충돌합니다.

Memory Usage (MB): {
  rss: '2283.64 MB',
  heapTotal: '2279.48 MB',
  heapUsed: '2248.73 MB',
  external: '0.40 MB'
}
Memory Usage (MB): {
  rss: '2283.64 MB',
  heapTotal: '2279.48 MB',
  heapUsed: '2248.74 MB',
  external: '0.40 MB'
}


#
# Fatal error in , line 0
# Fatal JavaScript invalid size error 169220804
#
#
#
#FailureMessage Object: 0x7ff7b0ef8070
로그인 후 복사

혼란스러우신가요? 1.4G 한도 아닌가요? 2G 이상을 사용하는 이유는 무엇입니까? 실제로 Node.js의 1.4GB 제한은 V8 엔진의 역사적 제한이며 초기 V8 버전 및 특정 구성에 적용됩니다. 최신 Node.js 및 V8에서 Node.js는 시스템 리소스를 기반으로 메모리 사용량을 자동으로 조정합니다. 어떤 경우에는 특히 대규모 데이터 세트를 처리하거나 메모리 집약적인 작업을 실행할 때 1.4GB보다 훨씬 더 많은 공간을 사용할 수 있습니다.

메모리 제한을 512M으로 설정하면 RSS가 996MB 정도에 도달하면 오버플로됩니다.

Memory Usage (MB): {
  rss: '996.22 MB',
  heapTotal: '993.22 MB',
  heapUsed: '962.08 MB',
  external: '0.40 MB'
}
Memory Usage (MB): {
  rss: '996.23 MB',
  heapTotal: '993.22 MB',
  heapUsed: '962.09 MB',
  external: '0.40 MB'
}

<--- Last few GCs --->

[22540:0x7fd27684d000]     1680 ms: Mark-sweep 643.0 (674.4) -> 386.8 (419.4) MB, 172.2 / 0.0 ms  (average mu = 0.708, current mu = 0.668) allocation failure; scavenge might not succeed
[22540:0x7fd27684d000]     2448 ms: Mark-sweep 962.1 (993.2) -> 578.1 (610.7) MB, 240.7 / 0.0 ms  (average mu = 0.695, current mu = 0.687) allocation failure; scavenge might not succeed


<--- JS stacktrace --->

FATAL ERROR: Reached heap limit Allocation failed - JavaScript heap out of memory
로그인 후 복사

좀 더 정확하게 정리하면 Node.js의 메모리 제한은 힙 메모리 제한을 의미하는데, 이는 V8에서 할당한 JS 객체, 배열 등이 점유할 수 있는 최대 메모리입니다.

힙 메모리 크기에 따라 Node.js 프로세스가 차지할 수 있는 메모리 양이 결정되나요? 아니요! 계속 읽어보세요.

Node.js 메모리에 3GB 파일을 넣을 수 있나요?

테스트에서 프로그램이 충돌하기 전에 어레이가 2GB를 약간 넘는 용량만 저장할 수 있다는 것을 확인했습니다. 그럼 3GB 파일이 있으면 Node.js 메모리에 한꺼번에 넣을 수는 없을까요?

할 수 있습니다!

우리는 process.memoryUsage()를 통해 Node.js 프로세스에 의해 점유되지만 V8에 의해 할당되지 않는 외부 메모리를 보았습니다. 3GB 파일을 거기에 넣으면 메모리 제한이 없습니다. 어떻게? 버퍼를 사용할 수 있습니다. Buffer는 JS 객체와 데이터가 아닌 C를 이용해 메모리를 할당하는 Node.js의 C 확장 모듈입니다.

데모는 다음과 같습니다.

setInterval(() => { console.log('Memory Usage:', process.memoryUsage()); }, 1000);
로그인 후 복사
로그인 후 복사

3GB의 메모리를 할당하더라도 우리 프로그램은 원활하게 실행되고 있으며, 이 외부 메모리는 Node.js에 의한 제한이 아니라 운영 체제의 할당 메모리 제한에 의해 제한되기 때문에 Node.js 프로그램이 5GB 이상의 메모리를 차지했습니다. 스레드로 전환합니다(그래서 너무 무리해서 사용할 수는 없으며 버퍼에도 메모리가 부족할 수 있습니다. 핵심은 Streams로 대규모 데이터를 처리하는 것입니다).

Node.js에서 Buffer 개체의 수명 주기는 JavaScript 개체에 연결되어 있습니다. Buffer 객체에 대한 JavaScript 참조가 제거되면 V8 가비지 수집기는 객체를 재활용 가능으로 표시하지만 Buffer 객체의 기본 메모리는 즉시 해제되지 않습니다. 일반적으로 C 확장의 소멸자가 호출되면(예: Node.js의 가비지 수집 프로세스 중에) 메모리의 이 부분이 해제됩니다. 그러나 이 프로세스는 V8의 가비지 컬렉션과 완전히 동기화되지 않을 수 있습니다.

function formatMemoryUsageInMB(memUsage) {
    return {
        rss: convertToMB(memUsage.rss),
        heapTotal: convertToMB(memUsage.heapTotal),
        heapUsed: convertToMB(memUsage.heapUsed),
        external: convertToMB(memUsage.external)
    };
}

const convertToMB = value => {
    return (value / 1024 / 1024).toFixed(2) + ' MB';
};

const logInterval = setInterval(() => {
    const memoryUsageMB = formatMemoryUsageInMB(process.memoryUsage());
    console.log(`Memory Usage (MB):`, memoryUsageMB);
}, 1000);
로그인 후 복사
로그인 후 복사

요약하면 Node.js 메모리 사용량은 JS 힙 메모리 사용량(V8의 가비지 컬렉션에 의해 결정됨) C에 의한 메모리 할당으로 구성됩니다.

힙 메모리가 신세대와 구세대로 분리되는 이유는 무엇입니까?

세대별 가비지 수집 전략은 현대 프로그래밍 언어 구현에서 매우 널리 퍼져 있습니다! 세대별 가비지 수집과 같은 유사한 전략은 Ruby, .NET 및 Java에서 찾을 수 있습니다. 가비지 수집이 발생하면 종종 "세계를 중지"하는 상황이 발생하여 프로그램 성능에 필연적으로 영향을 미칩니다. 하지만 이 디자인은 성능 최적화를 염두에 두고 고안되었습니다.

  • 다양한 개체 수명 프로그램 개발 중에 변수의 상당 부분은 일시적이며 특정 로컬 계산 작업을 수행하는 데 사용됩니다. 이러한 변수는 Minor GC, 즉 차세대 GC에 더 적합합니다. 차세대 메모리의 개체는 주로 Scavenge 알고리즘을 통해 가비지 수집 대상이 됩니다. Scavenge 알고리즘은 힙 메모리를 From과 To라는 두 부분으로 이등분합니다(고전적인 공간 대 시간 절충안. 생존 시간이 짧기 때문에 많은 양의 메모리를 소비하지 않음).

메모리 할당은 From 내에서 이루어집니다. 가비지 수집 중에 From의 활성 개체가 검사되어 To로 복사된 후 비활성 개체가 해제됩니다. 후속 수집 라운드에서는 To의 라이브 개체가 From으로 복제되고, 이 시점에서 To는 From으로 변형되고 그 반대의 경우도 마찬가지입니다. 각 가비지 수집 주기마다 From과 To가 교체됩니다. 이 알고리즘은 복사 프로세스 중에 활성 개체만 복제하므로 메모리 조각 생성을 방지합니다.
그렇다면 변수의 활성 여부는 어떻게 결정됩니까? 도달가능성 분석이 시작됩니다. 예를 들어 다음 개체를 고려하십시오.

  • globalObject: 전역 개체입니다.
  • obj1: globalObject가 직접 참조하는 객체입니다.
  • obj2: obj1이 참조하는 객체입니다.
  • obj3: 다른 개체로부터 참조가 없는 격리된 개체입니다.

접근성 분석의 맥락에서:

  • globalObject는 루트 객체이기 때문에 본질적으로 접근 가능합니다.
  • obj1은 globalObject에 의해 참조되므로 접근 가능합니다.
  • obj1이 참조하는 obj2에도 연결할 수 있습니다.
  • 반대로, 루트 개체나 기타 연결 가능한 개체에 대한 참조 경로가 부족한 obj3은 연결 불가능한 것으로 판단되어 재활용할 수 있습니다.

물론 참조 카운팅이 보조 수단으로 사용될 수 있습니다. 그럼에도 불구하고 순환 참조가 있으면 객체의 실제 활성 상태를 정확하게 확인하지 못합니다.

구세대 메모리에서 객체는 일반적으로 덜 활동적입니다. 하지만 Old Generation 메모리가 가득 차면 Mark-Sweep 알고리즘을 통해 Old Generation 메모리(Major GC) 정리를 시작합니다.

Mark-Sweep 알고리즘은 마킹과 스위핑의 두 단계로 구성됩니다. 마킹 단계에서 V8 엔진은 힙의 모든 객체를 탐색하고 활성 객체에 태그를 지정합니다. 스위핑 단계에서는 표시되지 않은 개체만 지워집니다. 이 알고리즘의 장점은 Old Generation에서 죽은 객체의 비율이 상대적으로 적기 때문에 스위핑 단계에서 상대적으로 적은 시간을 소비한다는 것입니다. 하지만 압축하지 않고 클리어만 하기 때문에 불연속적인 메모리 공간이 생길 수 있어 큰 객체에 메모리 할당이 불편하다는 단점이 있습니다.

이러한 단점으로 인해 메모리 조각화가 발생하고 Mark-Compact라는 또 다른 알고리즘을 사용해야 합니다. 이 알고리즘은 모든 활성 개체를 한쪽 끝으로 이동한 다음 경계 오른쪽의 유효하지 않은 메모리 공간을 한 번에 제거하여 완전하고 연속적인 사용 가능한 메모리 공간을 얻습니다. 많은 수의 라이브 개체를 이동하는 데 더 많은 시간이 소요되지만 Mark-Sweep 알고리즘으로 인해 발생할 수 있는 메모리 조각화 문제를 해결합니다.

이 게시물이 유익하셨다면 좋아요를 눌러주세요. :디

위 내용은 Node.js의 메모리 제한은 정확히 무엇입니까?의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.

핫 AI 도구

Undresser.AI Undress

Undresser.AI Undress

사실적인 누드 사진을 만들기 위한 AI 기반 앱

AI Clothes Remover

AI Clothes Remover

사진에서 옷을 제거하는 온라인 AI 도구입니다.

Undress AI Tool

Undress AI Tool

무료로 이미지를 벗다

Clothoff.io

Clothoff.io

AI 옷 제거제

Video Face Swap

Video Face Swap

완전히 무료인 AI 얼굴 교환 도구를 사용하여 모든 비디오의 얼굴을 쉽게 바꾸세요!

뜨거운 도구

메모장++7.3.1

메모장++7.3.1

사용하기 쉬운 무료 코드 편집기

SublimeText3 중국어 버전

SublimeText3 중국어 버전

중국어 버전, 사용하기 매우 쉽습니다.

스튜디오 13.0.1 보내기

스튜디오 13.0.1 보내기

강력한 PHP 통합 개발 환경

드림위버 CS6

드림위버 CS6

시각적 웹 개발 도구

SublimeText3 Mac 버전

SublimeText3 Mac 버전

신 수준의 코드 편집 소프트웨어(SublimeText3)

프론트 엔드 열 용지 영수증에 대한 차량 코드 인쇄를 만나면 어떻게해야합니까? 프론트 엔드 열 용지 영수증에 대한 차량 코드 인쇄를 만나면 어떻게해야합니까? Apr 04, 2025 pm 02:42 PM

프론트 엔드 개발시 프론트 엔드 열지대 티켓 인쇄를위한 자주 묻는 질문과 솔루션, 티켓 인쇄는 일반적인 요구 사항입니다. 그러나 많은 개발자들이 구현하고 있습니다 ...

Demystifying JavaScript : 그것이하는 일과 중요한 이유 Demystifying JavaScript : 그것이하는 일과 중요한 이유 Apr 09, 2025 am 12:07 AM

JavaScript는 현대 웹 개발의 초석이며 주요 기능에는 이벤트 중심 프로그래밍, 동적 컨텐츠 생성 및 비동기 프로그래밍이 포함됩니다. 1) 이벤트 중심 프로그래밍을 사용하면 사용자 작업에 따라 웹 페이지가 동적으로 변경 될 수 있습니다. 2) 동적 컨텐츠 생성을 사용하면 조건에 따라 페이지 컨텐츠를 조정할 수 있습니다. 3) 비동기 프로그래밍은 사용자 인터페이스가 차단되지 않도록합니다. JavaScript는 웹 상호 작용, 단일 페이지 응용 프로그램 및 서버 측 개발에 널리 사용되며 사용자 경험 및 크로스 플랫폼 개발의 유연성을 크게 향상시킵니다.

누가 더 많은 파이썬이나 자바 스크립트를 지불합니까? 누가 더 많은 파이썬이나 자바 스크립트를 지불합니까? Apr 04, 2025 am 12:09 AM

기술 및 산업 요구에 따라 Python 및 JavaScript 개발자에 대한 절대 급여는 없습니다. 1. 파이썬은 데이터 과학 및 기계 학습에서 더 많은 비용을 지불 할 수 있습니다. 2. JavaScript는 프론트 엔드 및 풀 스택 개발에 큰 수요가 있으며 급여도 상당합니다. 3. 영향 요인에는 경험, 지리적 위치, 회사 규모 및 특정 기술이 포함됩니다.

Shiseido의 공식 웹 사이트와 같은 시차 스크롤 및 요소 애니메이션 효과를 달성하는 방법은 무엇입니까?
또는:
Shiseido의 공식 웹 사이트와 같은 페이지 스크롤과 함께 애니메이션 효과를 어떻게 달성 할 수 있습니까? Shiseido의 공식 웹 사이트와 같은 시차 스크롤 및 요소 애니메이션 효과를 달성하는 방법은 무엇입니까? 또는: Shiseido의 공식 웹 사이트와 같은 페이지 스크롤과 함께 애니메이션 효과를 어떻게 달성 할 수 있습니까? Apr 04, 2025 pm 05:36 PM

이 기사에서 시차 스크롤 및 요소 애니메이션 효과 실현에 대한 토론은 Shiseido 공식 웹 사이트 (https://www.shiseido.co.jp/sb/wonderland/)와 유사하게 달성하는 방법을 살펴볼 것입니다.

JavaScript의 진화 : 현재 동향과 미래 전망 JavaScript의 진화 : 현재 동향과 미래 전망 Apr 10, 2025 am 09:33 AM

JavaScript의 최신 트렌드에는 Typescript의 Rise, 현대 프레임 워크 및 라이브러리의 인기 및 WebAssembly의 적용이 포함됩니다. 향후 전망은보다 강력한 유형 시스템, 서버 측 JavaScript 개발, 인공 지능 및 기계 학습의 확장, IoT 및 Edge 컴퓨팅의 잠재력을 포함합니다.

JavaScript는 배우기가 어렵습니까? JavaScript는 배우기가 어렵습니까? Apr 03, 2025 am 12:20 AM

JavaScript를 배우는 것은 어렵지 않지만 어려운 일입니다. 1) 변수, 데이터 유형, 기능 등과 같은 기본 개념을 이해합니다. 2) 마스터 비동기 프로그래밍 및 이벤트 루프를 통해이를 구현하십시오. 3) DOM 운영을 사용하고 비동기 요청을 처리합니다. 4) 일반적인 실수를 피하고 디버깅 기술을 사용하십시오. 5) 성능을 최적화하고 모범 사례를 따르십시오.

JavaScript를 사용하여 동일한 ID와 동일한 ID로 배열 요소를 하나의 객체로 병합하는 방법은 무엇입니까? JavaScript를 사용하여 동일한 ID와 동일한 ID로 배열 요소를 하나의 객체로 병합하는 방법은 무엇입니까? Apr 04, 2025 pm 05:09 PM

동일한 ID로 배열 요소를 JavaScript의 하나의 객체로 병합하는 방법은 무엇입니까? 데이터를 처리 할 때 종종 동일한 ID를 가질 필요가 있습니다 ...

Zustand 비동기 작동 : Usestore가 얻은 최신 상태를 보장하는 방법은 무엇입니까? Zustand 비동기 작동 : Usestore가 얻은 최신 상태를 보장하는 방법은 무엇입니까? Apr 04, 2025 pm 02:09 PM

zustand 비동기 작업의 데이터 업데이트 문제. Zustand State Management Library를 사용할 때는 종종 비동기 작업이시기 적절하게 발생하는 데이터 업데이트 문제가 발생합니다. � ...

See all articles