Sterty Node.js brakuje pamięci


247

Dzisiaj uruchomiłem skrypt do indeksowania systemu plików, aby odświeżyć indeks plików RAID, a po 4 godzinach zawiesił się z następującym błędem:

[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

Serwer jest wyposażony w 16 GB pamięci RAM i 24 GB wymiany SSD. Bardzo wątpię, że mój skrypt przekroczył 36 GB pamięci. Przynajmniej nie powinno

Skrypt tworzy indeks plików przechowywanych jako Array of Objects z metadanymi plików (daty modyfikacji, uprawnienia itp., Brak dużych danych)

Oto pełny kod skryptu: http://pastebin.com/mjaD76c3

W przeszłości eksperymentowałem już z dziwnymi problemami z węzłami za pomocą tego skryptu, co zmusiło mnie np. Do. podział indeksu na wiele plików, ponieważ węzeł glitching podczas pracy na tak dużych plikach jak String. Czy istnieje sposób na ulepszenie zarządzania pamięcią nodejs przy użyciu ogromnych zestawów danych?

Odpowiedzi:


315

Jeśli dobrze pamiętam, istnieje ścisłe standardowe ograniczenie wykorzystania pamięci w wersji V8 około 1,7 GB, jeśli nie zwiększysz go ręcznie.

W jednym z naszych produktów zastosowaliśmy to rozwiązanie w skrypcie wdrażania:

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

Byłoby też nowe polecenie spacji, ale jak czytam tutaj: a-tour-of-v8-garbage-collection nowa przestrzeń zbiera tylko nowo utworzone dane krótkoterminowe, a stara przestrzeń zawiera wszystkie odnośne struktury danych, które powinny znajdować się w Twoja skrzynka to najlepsza opcja.


W ten sam sposób ta konfiguracja jest dla nodejs niezależnie w ramach. @ Simer
Felix

Pracuję z Angular 4 i otrzymuję ten sam problem. Jaki powinien być plik yourFile.js dla aplikacji Angular?
Vikram

@VikramSingh używasz ng servelub rozpowszechniasz wynik ng buildfolderu / dist przez inny serwer WWW, taki jak express? Ale jeśli Twój projekt Angular używa więcej niż standardowej pamięci 1,7 GB, być może będziesz mieć problem architektoniczny w swojej aplikacji? Wygląda na to, że używasz env rozwoju z nmp start Może to jest rozwiązanie dla niego github.com/mgechev/angular-seed/issues/2063
Felix

Korzystam z kompilacji ng z kątowym cli i aot (folder dist)
Vikram

2
indeks, plik js @Techdive, którego używasz do uruchomienia serwera
Basit

77

Na wypadek, gdyby ktoś natrafił na to w środowisku, w którym nie może bezpośrednio ustawić właściwości węzła (w moim przypadku narzędzie do kompilacji):

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

Możesz ustawić opcje węzła za pomocą zmiennej środowiskowej, jeśli nie możesz przekazać ich w wierszu poleceń.


Czy możesz wyjaśnić, co masz na myśli, mówiąc „... ustaw opcje węzła za pomocą zmiennej środowiskowej ..”?
Keselme

6
@Keselme Zmienna środowiskowa to zmienna ustawiona na serwerze, z której wszystkie procesy mogą odczytać dane. Otwórz terminal SSH na swoim serwerze i wpisz: MY_VAR = witaj, a następnie wpisz: echo $ MY_VAR. Zobaczysz, że wypisuje „witaj” w terminalu. Właśnie ustawiłeś zmienną środowiskową i ponownie ją odczytałeś.
Rob Evans

pracował na Ubuntu 18.04, właśnie dodałem polecenie eksportu do mojego pliku bashrc
Rahal Kanishka

76

Jeśli chcesz zwiększyć wykorzystanie pamięci węzła na całym świecie - nie tylko pojedynczy skrypt, możesz wyeksportować zmienną środowiskową, jak poniżej:
export NODE_OPTIONS=--max_old_space_size=4096

Wtedy nie musisz grać z plikami podczas uruchamiania takich kompilacji npm run build.


1
Dla dodatkowej wygody dodaj profil bash_profile lub profil zsh.
Tropicalrambler,

24

Napotkałem ten problem podczas próby debugowania za pomocą VSCode, więc po prostu chciałem dodać, jak można dodać argument do konfiguracji debugowania.

Możesz dodać go do runtimeArgswłaściwości swojej konfiguracji w launch.json.

Zobacz przykład poniżej.

{
"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

Oto kilka wartości flag, aby dodać dodatkowe informacje o tym, jak zezwolić na więcej pamięci podczas uruchamiania serwera węzła.

1 GB - 8 GB

#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 

czy można go zwiększać w potęgach 2? czy należy ustawić na wartość większą niż pamięć systemowa? jeśli nie, to jaka jest dobra pamięć systemowa do stosunku maksymalnej starej przestrzeni do wielkości?
Harry Moreno

3
@HarryMoreno Możesz wprowadzić dowolną wartość liczbową, którą lubisz. Nie musi to być potęga 2. Nie jestem jednak pewien proporcji. To tylko maksymalny limit, nie będzie zużywał całej pamięci. Po prostu ustawiłbym go tak wysoko, jak potrzebujesz, a następnie w razie potrzeby skalowałem.
Nicholas Porter

Dam system ram - 1 GB próby. Zakładając, że ten vm służy tylko do uruchamiania tej aplikacji węzła.
Harry Moreno

2
@HarryMoreno Dobra proporcja pamięci systemowej do maksymalnego rozmiaru starej przestrzeni zależy całkowicie od tego, co jeszcze działa na twoim komputerze. Możesz go zwiększyć w potęgach dwóch - lub możesz użyć dowolnej liczby. Możesz ustawić go na większy niż pamięć systemowa - ale natrafisz na problemy z zamianą.
Gigimoi

20

Walczyłem z tym nawet po ustawieniu - max-old-space-size.

Potem zdałem sobie sprawę, że przed skryptem karmy muszę umieścić opcje - max-old-space-size.

najlepiej też podać obie składnie - max-old-space-size i --max_old_space_size mój skrypt dla karmy:

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

odniesienie https://github.com/angular/angular-cli/issues/1652


5
najlepiej podać obie składnie - max-old-space-size i --max_old_space_size ” - nie musisz tego robić, są one synonimami. From nodejs.org/api/cli.html#cli_options : „Wszystkie opcje, łącznie z opcjami V8, pozwalają na rozdzielenie słów zarówno myślnikami (-) jak i podkreślnikami (_).”
ZachB

6
maksymalny rozmiar pliku wykonywalnego został usunięty i kończy się błędem, gdy jest używany: github.com/nodejs/node/issues/13341
crashbus

Musiałem to wyciąć --max-old-space-size=8192 --optimize-for-size --max_old_space_size=8192 --optimize_for_sizei zadziałało
Siergiej Pleshakov,


11

fwiw, pomocne może być znalezienie i naprawienie pamięci pamięci za pomocą czegoś takiego jak zegarek .


10

Kroki prowadzące do rozwiązania tego problemu (w systemie Windows) -

  1. Otwórz wiersz polecenia i %appdata%naciśnij klawisz Enter
  2. Przejdź do %appdata%> folderu npm
  3. Otwórz lub edytuj ng.cmdw swoim ulubionym edytorze
  4. Dodaj --max_old_space_size=8192do bloku IF i ELSE

Twój node.cmdplik wygląda tak po zmianie:

@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" %*
)

Jest to specyficzne dla systemu Windows. OP nie wspomniał nic o systemie Windows.
Dan Dascalescu,

@DanDascalescu Zaktualizowana odpowiedź. Dzięki za powiadomienie
Umang Patwa

6

Można użyć następującej zmiennej środowiskowej:

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

Kolejna uwaga: console.log()zużywa również pamięć w terminalu.

właśnie próbował skomentować console.log () na terminalu. ponieważ zajmie to również pamięć.


6
Czy to odpowiedź czy komentarz do jakiejś odpowiedzi? Istnieje wiele odpowiedzi zNODE_OPTIONS= --max-old-space-size=somesize
barbsan

5

jeśli chcesz zmienić pamięć globalnie dla węzła (systemu Windows), przejdź do zaawansowanych ustawień systemu -> zmienne środowiskowe -> nowa zmienna użytkownika

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


4

Chcę tylko dodać, że w niektórych systemach, nawet zwiększając limit pamięci węzła --max-old-space-size, to nie wystarczy i występuje taki błąd systemu operacyjnego:

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

W tym przypadku prawdopodobnie dzieje się tak, ponieważ osiągnąłeś maksymalną mmapę na proces.

Możesz sprawdzić max_map_count, uruchamiając

sysctl vm.max_map_count

i zwiększa to, uruchamiając

sysctl -w vm.max_map_count=655300

i napraw go, aby nie był resetowany po ponownym uruchomieniu, dodając ten wiersz

vm.max_map_count=655300

w /etc/sysctl.confpliku

Sprawdź tutaj, aby uzyskać więcej informacji.

Dobrą metodą analizy błędu jest uruchomienie procesu za pomocą strace

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

3

Ostatnio napotkałem ten sam problem i natknąłem się na ten wątek, ale mój problem Reactdotyczył aplikacji. Poniżej zmiany w poleceniu start węzła rozwiązały moje problemy.

Składnia

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

Przykład

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

Dlaczego rozmiar to 16000 w maksymalnej starej przestrzeni?

Zasadniczo różni się w zależności od przydzielonej pamięci dla tego wątku i ustawień węzła.

Jak zweryfikować i podać odpowiedni rozmiar?

Zasadniczo pozostaje to w naszym silniku v8. poniższy kod pomaga zrozumieć rozmiar sterty silnika lokalnego węzła 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

Właśnie napotkałem ten sam problem z moją instancją EC2 t2.micro, która ma 1 GB pamięci.

Rozwiązałem problem, tworząc plik wymiany przy użyciu tego adresu URL i ustawiając następującą zmienną środowiskową.

export NODE_OPTIONS=--max_old_space_size=4096

Wreszcie problem zniknął.

Mam nadzieję, że będzie to pomocne w przyszłości.


1

Na wypadek, gdyby to pomogło osobom mającym ten problem podczas korzystania z aplikacji nodejs, które generują intensywne rejestrowanie, kolega rozwiązał ten problem, przesyłając standardowe dane wyjściowe do pliku.


1

Jeśli próbujesz uruchomić nie nodesam, ale jakiś inny program, na przykład webpackmożesz użyć zmiennej środowiskowej i cross-envpakietu:

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

1

W celu powiązania projektów kątowych dodałem poniższy wiersz do mojego pliku pakage.json w sekcji skryptów .

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

Teraz, aby spakować mój kod, używam npm run build-prodzamiastng build --requiredFlagsHere

mam nadzieję że to pomoże!


0

Zaktualizuj węzeł do najnowszej wersji. Byłem na węźle 6.6 z tym błędem i zaktualizowałem go do wersji 8.9.4 i problem zniknął.


0

W moim przypadku uruchomiłem npm installpoprzednią wersję węzła, po pewnym czasie zaktualizowałem wersję węzła i RAM npm installdla kilku modułów. Po tym otrzymałem ten błąd. Aby rozwiązać ten problem, usunąłem folder node_module z każdego projektu i uruchomiłem npm installponownie.

Mam nadzieję, że to może rozwiązać problem.

Uwaga: Działo się to na moim komputerze lokalnym i zostało naprawione tylko na komputerze lokalnym.


0

To polecenie działa idealnie. Mam 8 GB pamięci RAM w moim laptopie, więc ustawiłem rozmiar = 8192. Chodzi o RAM, a także potrzebujesz ustawić nazwę pliku. Biegnę npm gromadzeniu uruchom polecenie Dlatego użyłem build.js .

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

0

W moim przypadku zaktualizowałem wersję node.js do najnowszej i działało to jak urok.


Witaj Angela i witaj w SO! Czy możesz podać dokładną wersję Node.js, którą zaktualizowałeś dla przyszłych czytelników? Dzięki!
kant312

Zaktualizowałem do najnowszej wersji LTS: 12.18.0
Angela Rana
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.