W Poprzednim blogu zrozumieliśmy zarządzanie pamięcią w Node.js, jak działa Garbage Collector (GC) i jakie są możliwe przyczyny wycieków pamięci, mimo że GC odgrywa kluczową rolę. Na tym blogu przyjrzymy się najlepszym praktykom zapewniającym efektywne wykorzystanie pamięci w Node.js.

ZMNIEJSZ UŻYCIE ZMIENNYCH GLOBALNYCH

Ponieważ zmienne globalne nigdy nie są wyrzucane do śmieci, najlepiej uważać, aby ich nie nadużywać.

Szczególnie w JavaScript należy pamiętać o pewnych aspektach, aby zmniejszyć zmienne globalne

  1. Unikaj przypadkowych globali

W JavaScript, jeśli przypiszesz wartość do niezadeklarowanej zmiennej, JavaScript automatycznie podniesie ją jako zmienną globalną w trybie domyślnym. To samo dotyczy słowa „to” użytego w funkcjach o zasięgu globalnym.

Przykłady:

function apple() {
	red = true; // this red variable gets hoisted in global space
}
function mango() {
// since 'this' in global functions refers to global this varible is hoisted in global space
this.type = "Alphanso";  
}

Rozwiązanie: Pomocne jest pisanie JavaScriptu w trybie ścisłym z adnotacją „użyj ścisłego” na górze pliku JS. W nowszych wersjach Node.js można globalnie włączyć tryb ścisły, przekazując flagę „ — use_strict” podczas uruchamiania polecenia węzła.

'use strict'
function apple() {
	red = true; // this will throw an error
}
function mango() {
// this function will have its own scope for 'this'
this.type = "Alphanso";  
}

Uwaga: Zachowaj jednak ostrożność podczas korzystania z funkcji strzałek, ponieważ nawet w trybie ścisłym „to” w funkcji strzałki będzie znajdować się w przestrzeni globalnej

// This will also become a global variable as arrow functions
const plantation = () => {
    this.coconut = "Brown";
}

rozwiązanie: użyj reguły no-invalid-this z ESLint, aby uniknąć takich przypadków.

Używaj mądrze zasięgu globalnego:

  • W miarę możliwości nie używaj zakresu globalnego, jak najlepiej wykorzystaj zakres lokalny wewnątrz funkcji, ponieważ zostanie to wyrzucone do śmieci i zwolni pamięć.
  • Spróbuj zdefiniować tylko stałe, pamięć podręczną i zmienne wielokrotnego użytku w pliku global. Oznacz zmienne jako null, gdy wartości nie są potrzebne.
  • Nie używaj przestrzeni globalnej jako medium do przekazywania wartości z jednej funkcji do drugiej, zamiast tego użyj parametrów funkcji.
  • Nie przechowuj dużych obiektów w zasięgu globalnym. Jeśli musisz je przechowywać, unieważnij je, gdy nie są potrzebne. Nie pozwól, aby obiekty pamięci podręcznej rosły w nieskończoność, oczyść je raz na jakiś czas.

2. Efektywnie korzystaj z pamięci stosu

Dostęp do stosu jest znacznie szybszy niż dostęp do pamięci sterty, dlatego staraj się używać zmiennych stosu częściej niż ich odpowiedniki. Dzięki temu nie spowodujemy przypadkowo wycieków pamięci. Oczywiście w rzeczywistym świecie nie da się stworzyć użytecznej aplikacji, korzystając wyłącznie z danych statycznych. Możemy jednak zastosować się do kilku sztuczek, aby lepiej wykorzystać stos.

  1. Jeśli to możliwe, unikaj odniesień do obiektów sterty ze zmiennych stosu. Nie przechowuj także nieużywanych zmiennych.
  2. Zniszcz i użyj pól potrzebnych z obiektu lub tablicy, zamiast przekazywać całe obiekty/tablice do funkcji. Pozwala to uniknąć utrzymywania odniesień do obiektów wewnątrz zamknięć.
function outer() {
    const obj = {
        foo: 1,
        bar: "hello",
    };
const closure = () {
        const { foo } = obj;
        myFunc(foo);
    }
}
function myFunc(foo) {}

3. Efektywnie korzystaj z pamięci sterty

W rzeczywistych aplikacjach niemożliwe jest całkowite uniknięcie używania pamięci sterty, ale możemy zwiększyć jej efektywność, stosując się do kilku wskazówek:

  1. kopiuj obiekty zamiast odwoływać się do nich. Przekaż referencję tylko wtedy, gdy obiekt jest ogromny, a operacja kopiowania jest kosztowna.
  2. W miarę możliwości unikaj mutacji obiektów, zamiast tego użyj rozkładu obiektów lub obiektu.przypisz i utwórz kopię.
  3. Unikaj tworzenia wielu odniesień do tego samego obiektu
  4. Unikaj tworzenia ogromnych drzew obiektów, w przeciwnym razie zachowaj je krótkotrwałe

4. Zachowaj ostrożność podczas korzystania z zamknięć, liczników czasu i procedur obsługi zdarzeń

W przypadku timerów zawsze pamiętaj o przekazaniu kopii obiektów, aby uniknąć mutacji i wyczyszczeniu timerów, gdy robisz to za pomocą metod clearTimeout i clearInterval.

Ponadto, wyczyść słuchaczy, gdy praca zostanie wykonana, nie pozwól, aby działały wiecznie. W przypadkach, gdy trzymają się odniesienia do obiektu z zakresu nadrzędnego.

pierwotnie opublikowano na amodshinde.com