NodeJs(NestJs) memory leak

Salut,
Am facut un app in NestJs si ajunge cu usurinta sa consume mai mult de 2gb ram si apoi se reseteaza appul.
Cum pot sa fac memory profiling?
Am gasit ceva pe google dar nu sunt foarte happy.
Ma astept sa gsesc ceva ca la console.time si console.timeEnd sau un fel de profiling si sa vad fiecare functie cam cata memorie consuma

2 Likes

Interesant, dar folosesc vscode. Caut ceva similar pe vscode.

1 Like

nașpa… eu am un app care stă la 46MB, dar e făcut în Go

1 Like

Foarte simplu, faci attach la procesul de node cu Chrome/Edge si ai tab-urile de Performance si Memory.

@Cornel Spring in Java consuma 1Gb cu Hello World returnat de un endpoint, totusi lumea il foloseste… Go e fain, dar nu poti sa faci smecheria sa autogenerezi toata componenta de API pe front-end de pe backend. E.g. https://blitzjs.com face asa ceva.

1 Like

Am pornit un fel de proxy facut in spring boot pt un api si sta la sub 50 de mb si cpu usage nu a trecut de 5% :grin:

Problema pt acel memory leak este ori in codul lui @mangusta86 sau in codul framework-ului. Si daca este in codul framework-ului, este cam imposibil sa nu fi tipat nimeni pana acum pe Github, Twitter etc :slight_smile:

1 Like

Cel mai peobabil e in codul meu. Dar trebuie sa imi dau seama unde.
Cumva daca am un for in care sunt niste variabile definite incarca memoria ca GC sa curete la sfarsitul din for?

La ce m-as uita eu din prima:

  1. Instantierea claselor fără singleton
  2. Procesezi string-uri cu ceva map care face o copie la tot obiectul de fiecare dată când rulează.
1 Like

Folosesti RXJS?

Am patit ceva de genul asta in Nest.js. Cum spunea si @isti37 mai sus, la punctul 1, e foarte probabil sa fie de la faptul ca se creeaza prea multe instante de clasa, ci nu se foloseste singleton.
Mai exact, daca folosesti

@Injectable({ scope: Scope.REQUEST })

sau

@Injectable({ scope: Scope.TRANSIENT })

ajungi in situatia asta. Acesta fusese si cazul meu.


Dupa cum spune si in documentatia lor oficiala:

Using request-scoped providers will have an impact on application performance. While Nest tries to cache as much metadata as possible, it will still have to create an instance of your class on each request. Hence, it will slow down your average response time and overall benchmarking result. Unless a provider must be request-scoped, it is strongly recommended that you use the default singleton scope.


Revenind la intrebarea ta de profiling. Am dat, la un moment dat, pentru un package de profiling/tracing pentru Nest.js.

Aici e un demo:

2 Likes
2 Likes

ClinicJS pare cel mai misto de pama acum pe care l-am incercat. Din pacate mai are probleme. De exemplu partea de memory profiling nu mi-a mers.
Inca mai caut o problema si nu am reusit sa scap de problema.
Azi am reusit sa aloc mai mult timp problemei asteia.
La aplciatia NestJS din container memoria ajungea cu usurinta in cateva minute la 2gb si apoi se restarta si o lua de la 0. Nu am inteles de ce pe placa de retea aveam trafic de 500 In si 300 Out. In primul rand nu fac out la nimic.
Foarte ciudat.

Ce se intampla in acele cateva minute? Se fac request-uri catre API? Se ruleaza multe query-uri SQL? Se ruleaza ceva CRON-uri? Ce activitate exista?

Incearca sa izolezi problema (folsoind principiul divide et impera). Comenteaza/dezactviteaza module/parti intregi din aplicatie si vezi cand incepe sa apara o diferenta. Dupa care, repeta principiul pana cand ajungi sa izolezi fisierul si linia.

Acum m-a lovit idea cu memoria uriass ocupata.
Am functii la care le trimit niste obiecte string destul de mari. Aceste obievte le convertesc in json, deci memoria se dubleaza.
Cum pot masura memoria in interioruo unei functii nodejs?
Cum pot sa vad car ocupa o variabila in memorie?

Folosesti: node --inspect server.js
Dupa care deschizi in chrome: chrome://inpect.

O sa obtii niste rapoarte de genul:

Dar ca sa-ti dai seama exact daca de acolo se intampla, Fa un test in care acele functii nu sunt apelate si vezi ce se intampla. Adica asta poti face si fara debugger/profiler.

EDIT: Mai poti folosi si node --trace_gc server.js.
O sa vezi ceva de genul asta:

Articles:

@mangusta86

O solutie de inceput sau complementara (cele recomandate mai sus de GarryOne find mai ok) este sa afisezi tu memory usage-ul aplicatiei folosind o functie, vezi tutorialul de aici: Node.js process.memoryUsage() Method - GeeksforGeeks

Sfatul meu ar fi sa faci lucrul asta cu un setInterval, si sa faci un alt script care sa determine acel memory usage mare pe care il suspectezi. De exemplu scriptul tau sa faca N request-uri la serverul tau la acel URL care determina conversia in JSON. Dupa ce rulezi scriptul vezi cum se modifica memoria in timp.

Alte detalii despre memorie le poti gasi in raspunsul acceptat de aici: v8 - What do the return values of node.js process.memoryUsage() stand for? - Stack Overflow

Am mai sapat la problema.
In primul rand aveam o eroare in cod la modul:
Am un cron care pune niste taskuri intr-o lista. Dupa ce le-a pus cheama workerul sa le proceseze.
Am scris cod ca daca sunt in lista takurile alea sa nu le mai dubleze dar nu scrisesem si un mecanism de locking la taskuri si se intampla ca atunci cand durata functiei era mai mare decat distanta intre 2 cronuri sa vina al 2lea worker, sa ia acelasi task dar primuk deja tinea resursele ocupate.
In experienta asta am folosit:

  • process.memoryUsage() - nu sunt deplin multumit pt ca sunt mai multe threaduri si iti dai seama greu spre imposibil daca se scurge memorie intr-o functie
  • clinijs - Fain tool. Nu am reusit sa fac snapshoturi de memorie din el dar in partea de doctor mi-am dat seama de threadurile care se incaleca
  • heapdump - dump la memorie si incarcat in chrome. Misto dar inca nu stiu sa citesc pe acolo datele calumea si sa imi dau seamea exacr de toate problemele dupa baza raportului ala.

Ce mi-ar placea:

  • sa reusesc sa masor cata memorie se consuma intr-o functie.

Ce am mai gasit:
Cu ocazia asta am dat peste opentelemetry si cu toolul nestjs-otel am reusit in o ora sa pun in picioare pe baza exemplului lor o grafana care primeste date de la aplicatie si iti afiseaza. E ceva super tare. As vrea sa o implementez si in productie cu un switch de genul vreau nu vrea. Trebuie sa invat oleaca de grafana ca sa fiu capabil sa imi fac eu dashbordurile. Mai mult de atat e fain ca pot poti sa conectezi si alte chestii la el cum ar fi typeorm sau sql si sa vezi de pe grafice cand aplicatia incepe sa aiba probleme. Evindent…sa pui si alerte din grafana pe diverse metrice.

Posteaza un screenshot cu graficele/rapoartele de la nestjs-otel.