Node.js 힙 메모리 부족


247

오늘은 파일 시스템 인덱싱을 위해 스크립트를 실행하여 RAID 파일 인덱스를 새로 고치고 4 시간 후에 다음 오류와 함께 충돌했습니다.

[md5:]  241613/241627 97.5%  
[md5:]  241614/241627 97.5%  
[md5:]  241625/241627 98.1%
Creating missing list... (79570 files missing)
Creating new files list... (241627 new files)

<--- Last few GCs --->

11629672 ms: Mark-sweep 1174.6 (1426.5) -> 1172.4 (1418.3) MB, 659.9 / 0 ms [allocation failure] [GC in old space requested].
11630371 ms: Mark-sweep 1172.4 (1418.3) -> 1172.4 (1411.3) MB, 698.9 / 0 ms [allocation failure] [GC in old space requested].
11631105 ms: Mark-sweep 1172.4 (1411.3) -> 1172.4 (1389.3) MB, 733.5 / 0 ms [last resort gc].
11631778 ms: Mark-sweep 1172.4 (1389.3) -> 1172.4 (1368.3) MB, 673.6 / 0 ms [last resort gc].


<--- JS stacktrace --->

==== JS stack trace =========================================

Security context: 0x3d1d329c9e59 <JS Object>
1: SparseJoinWithSeparatorJS(aka SparseJoinWithSeparatorJS) [native array.js:~84] [pc=0x3629ef689ad0] (this=0x3d1d32904189 <undefined>,w=0x2b690ce91071 <JS Array[241627]>,L=241627,M=0x3d1d329b4a11 <JS Function ConvertToString (SharedFunctionInfo 0x3d1d3294ef79)>,N=0x7c953bf4d49 <String[4]\: ,\n  >)
2: Join(aka Join) [native array.js:143] [pc=0x3629ef616696] (this=0x3d1d32904189 <undefin...

FATAL ERROR: CALL_AND_RETRY_LAST Allocation failed - JavaScript heap out of memory
 1: node::Abort() [/usr/bin/node]
 2: 0xe2c5fc [/usr/bin/node]
 3: v8::Utils::ReportApiFailure(char const*, char const*) [/usr/bin/node]
 4: v8::internal::V8::FatalProcessOutOfMemory(char const*, bool) [/usr/bin/node]
 5: v8::internal::Factory::NewRawTwoByteString(int, v8::internal::PretenureFlag) [/usr/bin/node]
 6: v8::internal::Runtime_SparseJoinWithSeparator(int, v8::internal::Object**, v8::internal::Isolate*) [/usr/bin/node]
 7: 0x3629ef50961b

서버에는 16GB RAM 및 24GB SSD 스왑이 장착되어 있습니다. 스크립트가 36GB의 메모리를 초과 한 것으로 의심됩니다. 적어도 그것은해서는 안됩니다

스크립트는 파일 메타 데이터 (수정 날짜, 권한 등 빅 데이터가 없음)와 함께 객체 배열로 저장된 파일 인덱스를 생성합니다.

전체 스크립트 코드는 다음과 같습니다. http://pastebin.com/mjaD76c3

나는 이미이 스크립트를 사용하여 과거에 이상한 노드 문제를 경험했습니다. String과 같은 큰 파일을 작업 할 때 노드가 고장 나서 인덱스를 여러 파일로 분할합니다. 거대한 데이터 세트로 nodejs 메모리 관리를 개선 할 수있는 방법이 있습니까?

답변:


315

올바르게 기억한다면 수동으로 늘리지 않으면 V8에서 약 1.7GB의 메모리 사용에 대한 엄격한 표준 제한이 있습니다.

우리 제품 중 하나에서 배포 스크립트에서이 솔루션을 따랐습니다.

 node --max-old-space-size=4096 yourFile.js

새로운 공간 명령도 있지만 여기에서 읽은 것처럼 : v8-garbage-collection a-tour-of-v8-garbage-collection 새로운 공간은 새로 작성된 단기 데이터 만 수집하고 이전 공간에는 참조해야하는 모든 데이터 구조가 포함됩니다. 귀하의 경우 최선의 선택입니다.


같은 방식으로이 설정은 프레임 워크에서 독립적으로 nodejs를위한 것입니다. @ Simer
Felix

angular 4로 개발하고 동일한 문제가 발생합니다. 앵귤러 앱의 yourFile.js 파일은 무엇입니까?
Vikram

@VikramSingh 당신 은 Express와 같은 다른 웹 서버에 의해 / dist 폴더 ng serve의 결과를 사용 ng build하고 있습니까? 그러나 Angular 프로젝트가 표준 1.7GB 이상의 메모리를 사용하는 경우 응용 프로그램에 아키텍처 문제가 있습니까? nmp start와 함께 개발 환경을 사용하고있는 것 같습니다. github.com/mgechev/angular-seed/issues/2063
Felix

나는 각 CLI 및 AOT (DIST 폴더)로 겨 빌드를 사용하고
비 크람

2
서버를 시작하는 데 사용하는 index, js 파일 @Techdive
Basit

77

누군가가 노드 속성을 직접 설정할 수없는 환경 에서이 문제가 발생하는 경우 (내 경우에는 빌드 도구) :

NODE_OPTIONS="--max-old-space-size=4096" node ...

명령 행에서 전달할 수없는 환경 변수를 사용하여 노드 옵션을 설정할 수 있습니다.


"... 환경 변수를 사용하여 노드 옵션을 설정하십시오."라고 말할 때의 의미를 설명해 주시겠습니까?
Keselme

6
@Keselme 환경 변수는 모든 프로세스가 데이터를 읽을 수 있도록 서버에 설정된 변수입니다. 서버에 대한 SSH 터미널을 열고 MY_VAR = hello를 입력 한 후 echo $ MY_VAR을 입력하십시오. 터미널에 "hello"가 인쇄되는 것을 볼 수 있습니다. 환경 변수를 설정하고 다시 읽었습니다.
Rob Evans

우분투 18.04에서 작업하고 방금 내 bashrc 파일에 내보내기 명령을 추가했습니다
Rahal Kanishka

76

단일 스크립트뿐만 아니라 노드의 메모리 사용량을 전체적으로 늘리려면 다음과 같이 환경 변수를 내보낼 수 있습니다.
export NODE_OPTIONS=--max_old_space_size=4096

그런 다음과 같은 빌드를 실행할 때 파일로 재생할 필요가 없습니다 npm run build.


1
편의상 bash_profile 또는 zsh 프로파일에 추가하십시오.
Tropicalrambler

24

VSCode로 디버깅하려고 할 때이 문제가 발생했기 때문에 디버그 설정에 인수를 추가하는 방법입니다.

runtimeArgs의 구성 속성에 추가 할 수 있습니다 launch.json.

아래 예를 참조하십시오.

{
"version": "0.2.0",
"configurations": [{
        "type": "node",
        "request": "launch",
        "name": "Launch Program",
        "program": "${workspaceRoot}\\server.js"
    },
    {
        "type": "node",
        "request": "launch",
        "name": "Launch Training Script",
        "program": "${workspaceRoot}\\training-script.js",
        "runtimeArgs": [
            "--max-old-space-size=4096"
        ]
    }
]}

21

다음은 노드 서버를 시작할 때 더 많은 메모리를 허용하는 방법에 대한 추가 정보를 추가하는 플래그 값입니다.

1GB-8GB

#increase to 1gb
node --max-old-space-size=1024 index.js

#increase to 2gb
node --max-old-space-size=2048 index.js 

#increase to 3gb
node --max-old-space-size=3072 index.js

#increase to 4gb
node --max-old-space-size=4096 index.js

#increase to 5gb
node --max-old-space-size=5120 index.js

#increase to 6gb
node --max-old-space-size=6144 index.js

#increase to 7gb
node --max-old-space-size=7168 index.js

#increase to 8gb 
node --max-old-space-size=8192 index.js 

2의 거듭 제곱으로 계속 증가시킬 수 있습니까? 시스템 메모리보다 크게 설정해야합니까? 그렇지 않은 경우 최대 이전 공간 크기 비율에 적합한 시스템 메모리는 무엇입니까?
Harry Moreno

3
@HarryMoreno 실제로 원하는 숫자 값을 입력 할 수 있습니다. 2의 거듭 제곱 일 필요는 없습니다. 그래도 비율은 확실하지 않습니다. 그것은 최대 한도이며 모든 메모리를 사용하지는 않습니다. 필요한만큼 높게 설정 한 다음 필요한 경우 다시 축소합니다.
Nicholas Porter

시스템 램-1GB를 사용해보십시오. 이 vm이이 노드 앱을 실행하기위한 것이라고 가정합니다.
Harry Moreno

2
@HarryMoreno 최대 시스템 용량 대 최대 공간 크기 비율은 시스템에서 실행중인 다른 시스템에 따라 다릅니다. 2의 거듭 제곱으로 늘리거나 원하는 수를 사용할 수 있습니다. 시스템 메모리보다 크게 설정할 수 있지만 스왑 문제가 발생합니다.
Gigimoi

20

--max-old-space-size를 설정 한 후에도이 문제로 고심하고있었습니다.

그런 다음 카르마 스크립트 앞에 --max-old-space-size 옵션을 넣어야한다는 것을 깨달았습니다.

또한 karma에 대한 스크립트 --max-old-space-size 및 --max_old_space_size 구문을 모두 지정하는 것이 가장 좋습니다.

node --max-old-space-size=8192 --optimize-for-size --max-executable-size=8192  --max_old_space_size=8192 --optimize_for_size --max_executable_size=8192 node_modules/karma/bin/karma start --single-run --max_new_space_size=8192   --prod --aot

참조 https://github.com/angular/angular-cli/issues/1652


5
" max-old-space-size 및 --max_old_space_size 구문을 모두 지정하는 것이 가장 좋습니다 "–이를 수행 할 필요는 없습니다. 동의어입니다. 에서 nodejs.org/api/cli.html#cli_options : "(-) 모든 옵션, V8 옵션을 포함하여, 단어를 모두 대시로 구분 될 수 있도록 밑줄 (_)."
ZachB

6
최대 크기의 실행을 제거하고 오차의 단부는 사용시 : github.com/nodejs/node/issues/13341
crashbus

나는 그것을 잘라야했고 --max-old-space-size=8192 --optimize-for-size --max_old_space_size=8192 --optimize_for_size효과가 있었다
Sergey Pleshakov


11

와우, memwatch와 같은 것으로 메모리 호그를 찾고 수정하는 것이 도움이 될 수 있습니다.


10

이 문제를 해결하는 단계 (Windows)-

  1. 명령 프롬프트를 열고 %appdata%Enter를 입력하십시오.
  2. %appdata%> npm 폴더로 이동
  3. ng.cmd좋아하는 편집기에서 열거 나 편집
  4. --max_old_space_size=8192IF 및 ELSE 블록에 추가

귀하의 node.cmd파일은 변경 후 다음과 같습니다 :

@IF EXIST "%~dp0\node.exe" (
  "%~dp0\node.exe" "--max_old_space_size=8192" "%~dp0\node_modules\@angular\cli\bin\ng" %*
) ELSE (
  @SETLOCAL
  @SET PATHEXT=%PATHEXT:;.JS;=;%
  node "--max_old_space_size=8192" "%~dp0\node_modules\@angular\cli\bin\ng" %*
)

이것은 Windows마다 다릅니다. OP는 Windows에 대해 언급하지 않았습니다.
Dan Dascalescu

@DanDascalescu 업데이트 된 답변.
알려

6

다음과 같은 환경 변수를 사용할 수 있습니다.

NODE_OPTIONS= --max-old-space-size=8192 .

또 다른 참고 사항 : console.log()터미널의 메모리도 소비합니다.

터미널에서 console.log ()를 주석하려고했습니다. 메모리도 필요하기 때문입니다.


6
이것은 답변이나 답변입니까? NODE_OPTIONS= --max-old-space-size=somesize
barbsan

5

노드 (윈도우)의 메모리를 전체적으로 변경하려면 고급 시스템 설정-> 환경 변수-> 새 사용자 변수로 이동하십시오.

variable name = NODE_OPTIONS
variable value = --max-old-space-size=4096


4

일부 시스템에서는으로 노드 메모리 제한을 늘리는 것으로 --max-old-space-size충분하지 않으며 다음과 같이 OS 오류가 있습니다.

terminate called after throwing an instance of 'std::bad_alloc'
  what():  std::bad_alloc
Aborted (core dumped)

이 경우 프로세스 당 최대 mmap에 도달했기 때문일 수 있습니다.

다음을 실행하여 max_map_count를 확인할 수 있습니다

sysctl vm.max_map_count

실행하여 증가

sysctl -w vm.max_map_count=655300

이 줄을 추가하여 재부팅 후 재설정되지 않도록 수정하십시오.

vm.max_map_count=655300

에서 /etc/sysctl.conf파일.

자세한 내용은 여기 를 확인 하십시오 .

오류를 분석하는 좋은 방법은 strace

strace node --max-old-space-size=128000 my_memory_consuming_process.js

3

나는 최근 에이 같은 문제에 직면 하여이 스레드를 발견했지만 내 문제는 ReactApp과 관련이 있습니다. node start 명령의 변경 사항으로 인해 내 문제가 해결되었습니다.

통사론

node --max-old-space-size=<size> path-to/fileName.js

node --max-old-space-size=16000 scripts/build.js

왜 공간 크기가 최대 16,000이됩니까?

기본적으로 스레드에 할당 된 메모리와 노드 설정에 따라 다릅니다.

올바른 크기를 확인하고 제공하는 방법?

이것은 기본 적으로 우리 엔진에 남아 v8있습니다. 아래 코드는 로컬 노드 v8 엔진의 힙 크기를 이해하는 데 도움이됩니다.

const v8 = require('v8');
const totalHeapSize = v8.getHeapStatistics().total_available_size;
const totalHeapSizeGb = (totalHeapSize / 1024 / 1024 / 1024).toFixed(2);
console.log('totalHeapSizeGb: ', totalHeapSizeGb);

2

1GB 메모리가있는 EC2 인스턴스 t2.micro와 동일한 문제에 직면했습니다.

URL을 사용하여 스왑 파일을 만들고 다음 환경 변수를 설정 하여 문제를 해결했습니다 .

export NODE_OPTIONS=--max_old_space_size=4096

마침내 문제는 사라졌습니다.

앞으로 도움이 되길 바랍니다.


1

대량 로깅을 생성하는 nodejs 앱을 사용하는 동안이 문제가있는 사람들에게 도움이 될 수 있도록 동료는 표준 출력을 파일로 파이프하여이 문제를 해결했습니다.


1

node예를 들어 자체가 아닌 다른 소프트 를 시작하려는 경우 webpack환경 변수 및 cross-env패키지를 사용할 수 있습니다 .

$ cross-env NODE_OPTIONS='--max-old-space-size=4096' \
  webpack --progress --config build/webpack.config.dev.js

1

각 프로젝트 번들, 나는 한 에 선 아래에 추가pakage.json 에서 파일 스크립트 섹션을 참조하십시오.

"build-prod": "node --max_old_space_size=5120 ./node_modules/@angular/cli/bin/ng build --prod --base-href /"

이제 코드를 번들로 묶는 npm run build-prod대신ng build --requiredFlagsHere

도움이 되었기를 바랍니다!


0

노드를 최신 버전으로 업그레이드하십시오. 나는이 오류로 노드 6.6에 있었고 8.9.4로 업그레이드했고 문제가 사라졌습니다.


0

내 경우에는 npm install이전 버전의 노드에서 실행했지만 언젠가는 노드 버전을 업그레이드하고 npm install몇 가지 모듈을 램 했습니다. 이 후이 오류가 발생했습니다. 이 문제를 해결하기 위해 각 프로젝트에서 node_module 폴더를 삭제하고 npm install다시 실행 했습니다.

이것이 문제를 해결할 수 있기를 바랍니다.

참고 : 이것은 내 로컬 컴퓨터에서 발생했으며 로컬 컴퓨터에서만 수정되었습니다.


0

이 명령은 완벽하게 작동합니다. 랩톱에 8GB 램이 있으므로 size = 8192로 설정합니다. 그것은 램에 관한 것이며 파일 이름을 설정해야합니다. 나는 실행 NPM 실행 빌드 내가 사용 왜 명령 build.js을 .

node --expose-gc --max-old-space-size=8192 node_modules/react-scripts/scripts/build.js

0

필자의 경우 node.js 버전을 최신 버전으로 업그레이드했으며 매력처럼 작동했습니다.


안젤라 안녕하세요 안녕하세요! 향후 독자를 위해 업데이트 한 Node.js의 정확한 버전을 지정할 수 있습니까? 감사!
kant312

나는 최신 LTS 버전으로 업그레이드했다 : 12.18.0
Angela Rana
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.