Memory leak
In case you are facing critical errors for the server like FATAL ERROR: Ineffective mark-compacts near heap limit Allocation failed - JavaScript heap out of memory than this is probably caused by memory leak in your app.
Local profiling
To find out root cause of the problem you need to analyze memory allocation on server over time.
Start the app
- You may use either startorstart-prodcommand to profile your app, but keep in mind thatstartruns app in dev-environment that leads to higher memory consumption and additional code that may distract you from analyzing core logic of the app. Howeverstartis preferred when you need to make code changes and you do not need to get the exact values of memory usage as for the prod-environment.
- Using @tramvai/cliyou can pass a special flag--debugand pass it either to thestartorstart-prodcommand
- You may pass any additional environment variables when calling cli commands as usual. For example, you may pass flag HTTP_CLIENT_CACHE_DISABLEDto disable http cache.
- To pass additional flags to the running nodejs instance you may use env NODE_OPTIONS. E.g., if you want to limit the heap memory for the running server passNODE_OPTIONS="--max-old-space-size=256"
- If you are profiling using start-prodwith different env values without code changes you can use start-prod command that will reuse previous builds, e.g.tramvai start-prod -t none app --debug
Use the DevTools
After starting the app in debug mode you can open Chrome DevTools to be ready to take some profiling.
You may read more about how to profile memory leaks with Chrome in next links:
- https://medium.com/@basakabhijoy/debugging-and-profiling-memory-leaks-in-nodejs-using-chrome-e8ece4560dba#:~:text=Fire%20up%20the%20chrome%20browser
- https://developer.chrome.com/docs/devtools/memory-problems/#summary
Test requests
Most of the time memory leaks are happens for every request, so you need to do some request.
- Using browser go to the page that is handled by you app
- Use any additional tools to make a bunch of requests, e.g. autocannon
What to look
After you've started the app and took memory snapshots or memory allocations look for the data that stays in memory when it shouldn't.
ChildContainer
In context of the tramvai app look for the ChildContainer first as it is created for every request and contains the whole Request DI instance that consumes a lot of memory. It should be collected by the GC after request end, but sometimes some code may prevent it from collecting.
Summary
- Start the app
- Start the DevTools
- Check memory usage on start and take the initial memory snapshot
- Make some test requests
- Take another memory snapshot
- Compare two snapshots and look for the leaks or unusual memory consumption
Example
- Start app in prod-mode yarn tramvai start-prod travelaviasearch --debug
- Start Chrome DevTools
- Take the memory snapshot
- Execute requests with autocannon -c 20 -d 60 localhost:3000/travel/flights/
- Click the button Collect garbage
- Take another memory snapshot
- Compare two snapshots
- If you want to test app with other envs stop the server and close the DevTools, then run it again with HTTP_CLIENT_CACHE_DISABLED=true MOCKER_ENABLED=true NODE_OPTIONS="--max-old-space-size=256" yarn tramvai start-prod -t none travelaviasearch