Jak opravit chybu „Hromady nedostatku paměti v JavaScriptu“

JavaScript si udržuje pozici jednoho z nejrozšířenějších programovacích jazyků díky své flexibilitě. Pro spouštění JavaScriptu mimo webový prohlížeč vývojáři využívají Node.js, což je běhové prostředí dostupné pro různé platformy.

Během práce na projektech v Node.js se často setkáváme s chybou nedostatku paměti.

Tento problém s nedostatkem paměti nastává, když standardní množství operační paměti, které systém vyhradil, nestačí pro náročný projekt.

Pokud dojde k této chybě, aplikace se nečekaně ukončí a zobrazí se hláška:

FATÁLNÍ CHYBA: CALL_AND_RETRY_LAST Alokace selhala – nedostatek paměti JavaScriptové haldy

Nebo

Závažná chyba: Neplatná alokace velikosti tabulky selhala – nedostatek paměti JavaScriptové haldy

Důvody výskytu chyby nedostatku paměti v JavaScriptu

  • Práce s rozsáhlými datovými strukturami: Manipulace s velkými datovými strukturami, jako jsou pole nebo matice, může vést k vyčerpání paměti a způsobit tuto chybu.

Níže je příklad rozsáhlé datové struktury s jednou miliardou prvků:

let array = [];

for (let i = 0; i < 1000000000; i++) {

  array.push(i);

}
  • Neefektivní správa paměti: S rozvojem aplikace je klíčové uvolňovat objekty, které již nejsou potřeba.

Následující kód demonstruje situaci, která vede k úniku paměti:

let array = [];

setInterval(function() {

  array.push(new Array(1000000).join("x"));

}, 1000);
  • Nekonečné smyčky: Kód s nekonečnou smyčkou se nikdy nezastaví, protože nedojde k ukončovací podmínce.

Příklad nekonečné smyčky:

while (true) {

    console.log(1);

}

Nekonečné smyčky rychle vyčerpávají paměť, což může způsobit tuto chybu.

  • Rekurzivní funkce: Rekurzivní funkce volá sama sebe (přímo nebo nepřímo) pro opakované provádění instrukcí, dokud není splněna určitá podmínka. Pokud nejsou správně navrženy, mohou vyčerpat paměť.
  • Velký počet objektů: Pokud kód obsahuje mnoho rozsáhlých objektů, jejich celková spotřeba paměti může způsobit přetížení.

Řešení chyby nedostatku paměti v JS

Tato chyba se může objevit v operačních systémech Windows, macOS i Linux, například v Ubuntu. Naštěstí ji lze opravit bez ohledu na použitý operační systém.

#1. Oprava chyby nedostatku paměti v JavaScriptu v systému Windows

Krok 1: Otevřete nabídku Start a vyhledejte „Rozšířená nastavení systému“.

Krok 2: V dolní části okna klikněte na „Proměnné prostředí“.

Krok 3: Klikněte na „Nový…“ v sekci „Uživatelské proměnné“ nebo „Systémové proměnné“. Volba v „Uživatelských proměnných“ ovlivní pouze aktuální uživatelský účet, zatímco „Systémové proměnné“ aplikují změny pro celý systém.

Krok 4: Do názvu proměnné zadejte „NODE_OPTIONS“ a do hodnoty proměnné „-max-old-space-size=4096“. Číslo 4096 alokuje 4GB virtuální paměti pro Node.js. Pro alokaci například 8GB, zadejte „-max-old-space-size=8192“.

Krok 5: Klikněte na „OK“, „Použít“ a nakonec „OK“ pro uložení změn.

Chybu lze také vyřešit pomocí Windows PowerShell. Otevřete terminál a zadejte:

env:NODE_OPTIONS="--max-old-space-size=4096"

Dočasně lze chybu vyřešit spuštěním následujícího příkazu před spuštěním aplikace:

set NODE_OPTIONS=--max-old-space-size=4096

#2. Oprava chyby nedostatku paměti v JavaScriptu v systému Linux

  • Krok 1: Identifikujte příčinu chyby. Prohlédněte si protokoly nebo výstup z konzole, abyste zjistili, které řádky kódu/soubory chybu způsobují.
  • Krok 2: Nastavte proměnnou prostředí definující virtuální paměť alokovanou pro Node.js. Použijte příkaz:
export NODE_OPTIONS=--max-old-space-size=4096

Tyto kroky přidělí 4GB virtuální paměti Node.js. Pokud chyba přetrvává, můžete alokovanou paměť zdvojnásobit.

Pro alokaci například 8GB virtuální paměti, použijte:

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

#3. Oprava chyby nedostatku paměti v JavaScriptu v systému macOS

Chybu nedostatku paměti v JavaScriptu na macOS můžete vyřešit podobně jako na Linuxu. Postupujte podle následujících kroků:

  • Krok 1: Prohlédněte si protokoly nebo výstup z konzole, abyste zjistili, které řádky kódu/soubory chybu způsobují.
  • Krok 2: Nastavte proměnnou prostředí definující virtuální paměť alokovanou pro Node.js. Použijte příkaz:
export NODE_OPTIONS=--max-old-space-size=4096

Tyto kroky přidělí 4GB virtuální paměti Node.js. Pokud chyba přetrvává, můžete alokovanou paměť zdvojnásobit.

Pro alokaci například 8GB virtuální paměti, použijte:

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

Zvýšení paměti při instalaci NPM

Předchozí řešení se zaměřovala na chyby, které se objevují při spuštění aplikace Node.js. Virtuální paměť ale můžete přidělit i při instalaci balíčků JavaScript, abyste se vyhnuli chybě s nedostatkem paměti. Použijte příkaz:

node --max-old-space-size=4096 (which npm) install

Poznámka: Virtuální paměť můžete zvyšovat po 1 GB, 2 GB, 3 GB nebo 4 GB. Velikost paměti je třeba zadat v MB. Nedoporučuje se však alokovat Node.js veškerou paměť počítače, protože by to mohlo způsobit selhání programu. Pokud máte například 16 GB RAM, můžete Node.js přidělit až 8 GB.

Prevence chyb nedostatku paměti v JavaScriptu

Doposud jsme se věnovali řešení chyb s nedostatkem paměti, když už k nim dojde. Naštěstí existují i preventivní opatření, která snižují riziko výskytu této chyby. Mezi nejlepší přístupy patří:

#1. Rozdělení dat na menší části

Pokud máte Node.js program, který importuje velké datové sady z rozsáhlých CSV souborů prostřednictvím procesu ETL (Extract – Transform – Load), může docházet k chybám. Pokud například pracujete s MongoDB, můžete použít příkaz:

split -l 1000000 users.csv

Tento příkaz rozdělí soubor „users.csv“ do několika menších souborů, každý s 1 000 000 uživateli. Parametr „-l“ určuje rozdělení souboru podle počtu řádků.

#2. Sledování využití paměti

Pro detekci úniků paměti můžete použít paměťový profiler. Lze kombinovat vestavěný paměťový modul Node.js s nástroji ChromeDevTools. Společně mohou odhalit problémy a umožnit jejich nápravu.

Dále můžete využít externí nástroje jako Datadog, New Relic a AppDynamics, pro sledování výkonu aplikace a provádění potřebných akcí. Metoda process.memoryUsage() vám pomůže zkontrolovat využití paměti v aplikaci Node.js.

#3. Předcházení únikům paměti

K únikům paměti dochází, když Node.js aplikace uchovává odkazy na objekty, které už nepotřebuje. Pokud se takové objekty nebudou uvolňovat pomocí garbage collection, může časem dojít k nárůstu využití paměti.

Únikům paměti lze předejít například tím, že se vyhneme globálním proměnným, blokování I/O operací a použijeme klíčová slova „let“ a „const“ místo „var“ při deklaraci proměnných.

#4. Procesy s vyvažováním zátěže

Při používání Node.js na zařízeních s omezenou pamětí (například Raspberry Pi) se můžete setkat s chybami nedostatku paměti. Řešením může být použití jednoho hlavního procesu a dalších procesů jako pracovníků. Když hlavní proces zjistí, že systém má málo paměti, ukončí daný proces a předá úkol jinému, který není přetížen.

#5. Aktualizace hardwaru

Pokud nepomáhá zvýšení alokace paměti ani implementace preventivních opatření, zvažte aktualizaci hardwaru. Node.js může běžet na RAM s minimální kapacitou 512 MB, ale s růstem vaší aplikace bude potřeba více paměti.

Zvýšení počtu CPU může také zlepšit alokaci paměti. Ideálně by 2 a více CPU měly umožnit aplikaci využívat pracovní vlákna pro úlohy náročné na procesor, jako je kryptografie a zpracování obrázků.

Časté dotazy

Co způsobuje chybu nedostatku paměti JavaScriptové haldy?

Tuto chybu může způsobit několik faktorů:
1. Úniky paměti
2. Nekonečné smyčky
3. Velký počet objektů v projektu
4. Rozsáhlé datové struktury

Je chyba „JavaScript Heap Out of Memory“ řešitelná?

Ano. Pro vyřešení můžete:
1. Zvýšit alokaci virtuální paměti pro Node.js
2. Odstranit úniky paměti
3. Optimalizovat kód
4. Aktualizovat hardware

Jak lze vyřešit chybu „Heap Out of Memory“ v aplikaci React?

React je populární knihovna JavaScriptu. V souboru package.json v kořenovém adresáři projektu přidejte tyto řádky do sekce „scripts“:

"scripts": {
    "start": "react-scripts --max_old_space_size=4096 start",
    "build": "react-scripts --max_old_space_size=4096 build",
    "test": "react-scripts test",
    "eject": "react-scripts eject"
}

Závěrem

Většina vývojářů je při spouštění Node.js programů zvyklá na chyby v kódu, ale ne na běhové chyby. Nemusíte se ale bát, protože chybu nedostatku paměti lze opravit. Popsali jsme, co tato chyba je, jak ji vyřešit a jak se jí vyhnout ve vašich budoucích projektech Node.js.

Pro další informace si můžete přečíst článek o tom, jak se vyhnout dalším častým chybám JavaScriptu.