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.