{"id":955,"date":"2015-08-14T21:08:13","date_gmt":"2015-08-14T15:08:13","guid":{"rendered":"http:\/\/promincproductions.com\/blog\/?p=955"},"modified":"2015-12-08T10:34:15","modified_gmt":"2015-12-08T04:34:15","slug":"nodejs-handling-memory-issues-enomem-garbage-collection","status":"publish","type":"post","link":"https:\/\/promincproductions.com\/blog\/nodejs-handling-memory-issues-enomem-garbage-collection\/","title":{"rendered":"NodeJS Handling Memory Issues &#8211; ENOMEM and Garbage Collection"},"content":{"rendered":"<p>I&#8217;ve been running a NodeJS server for a web application for over a year now, and while NodeJS has some strengths, I&#8217;m finding it has a weakness in the realm of memory management. \u00a0I&#8217;ve never had an Apache or Nginx server run out of memory quite like NodeJS does.<\/p>\n<p>There&#8217;s nothing worse than coming into work and seeing in my NodeJS logs the dreaded ENOMEM error&#8230; \u00a0I believe ENOMEM\u00a0simply stands for &#8220;Error &#8211; No Memory&#8221;.<\/p>\n<figure id=\"attachment_956\" aria-describedby=\"caption-attachment-956\" style=\"width: 500px\" class=\"wp-caption aligncenter\"><a href=\"https:\/\/promincproductions.com\/blog\/wp-content\/uploads\/2015\/08\/nodejs-enomem-error-message.jpg\" rel=\"attachment wp-att-956\" data-lasso-id=\"427\" data-rel=\"lightbox-gallery-Tic5srey\" data-rl_title=\"\" data-rl_caption=\"\" title=\"\"><img decoding=\"async\" class=\"size-medium wp-image-956\" src=\"https:\/\/promincproductions.com\/blog\/wp-content\/uploads\/2015\/08\/nodejs-enomem-error-message-500x175.jpg\" alt=\"NodeJS ENOMEM error messgae\" width=\"500\" height=\"175\" srcset=\"https:\/\/promincproductions.com\/blog\/wp-content\/uploads\/2015\/08\/nodejs-enomem-error-message-500x175.jpg 500w, https:\/\/promincproductions.com\/blog\/wp-content\/uploads\/2015\/08\/nodejs-enomem-error-message-150x52.jpg 150w, https:\/\/promincproductions.com\/blog\/wp-content\/uploads\/2015\/08\/nodejs-enomem-error-message.jpg 532w\" sizes=\"(max-width: 500px) 100vw, 500px\" \/><\/a><figcaption id=\"caption-attachment-956\" class=\"wp-caption-text\">If you&#8217;ve seen this ENOMEM error messge I&#8217;m sure you&#8217;re just as frustrated as I have been<\/figcaption><\/figure>\n<p>Once upon a time\u00a0my NodeJS server was on a shared server as another web server and such, and thus I figured there was just a conflict for resources. \u00a0However I&#8217;m now running on a dedicated Ubuntu server. \u00a0It only has 2GB of RAM, but really this should be sufficient for the web application.<\/p>\n<h2>Tracking Down a Memory Leak<\/h2>\n<p>The first step to solving a problem is identifying the problem. \u00a0For that, you need to have some insight though as to what is happening in your code. \u00a0So to look at memory usage, you can simply add this to your scripts to log out the memory usage.<\/p>\n<pre><code>console<span class=\"sh_symbol\">.<\/span><span class=\"sh_function\">log<\/span><span class=\"sh_symbol\">(<\/span>util<span class=\"sh_symbol\">.<\/span><span class=\"sh_function\">inspect<\/span><span class=\"sh_symbol\">(<\/span>process<span class=\"sh_symbol\">.<\/span><span class=\"sh_function\">memoryUsage<\/span><span class=\"sh_symbol\">()));<\/span>\r\n<\/code><\/pre>\n<p>This will output a message that looks something like:<\/p>\n<pre><code>{ rss: 51998720, heapTotal: 47029936, heapUsed: 29999680 }<\/code><\/pre>\n<p>These three numbers relate to your memory usage:<\/p>\n<ul>\n<li>rss\n<ul>\n<li><a href=\"https:\/\/en.wikipedia.org\/wiki\/Resident_set_size\" target=\"_blank\" rel=\"nofollow noopener\" data-lasso-id=\"428\">Resident Set Size<\/a><\/li>\n<li>This is the number you should be most interested in.<\/li>\n<li>This is how much memory your NodeJS application is currently using.<\/li>\n<\/ul>\n<\/li>\n<li>\u00a0heapTotal\n<ul>\n<li>Refers to\u00a0v8&#8217;s (JavasScript Engine) underlying storage<\/li>\n<li>It&#8217;s my understanding that this number is the amount of RAM allocated to your NodeJS server.<\/li>\n<\/ul>\n<\/li>\n<li>heapUsed\n<ul>\n<li>Refers to\u00a0v8&#8217;s (JavasScript Engine) underlying storage<\/li>\n<li>It&#8217;s my understanding that this is the amount of the heapTotal being used currently<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<p>I like to throw this logging message all over my script &#8211; particularly before and after variable or processes that I know should be large and would assumingly take up a lot of memory. \u00a0Restart your NodeJS server, run the application a bit and monitor the rss number. \u00a0In my case, the rss\u00a0was continuing to go up but never come down. \u00a0As you can assume, once you use up too much memory, the server will run out and you will find your friend the ENOMEM soon enough.<\/p>\n<p>I like to copy down the numbers I&#8217;m seeing here so that as I go through and try to do some cleanup I can notice the difference. \u00a0I write down the initial rss number as well as a number after running the application a say three times or so. \u00a0This becomes my benchmark and my standard testing procedure for future tests.<\/p>\n<h2>Clear Your Variable<\/h2>\n<p>A good programming practice and something that may help in this scenario is to clear your variables when you are done with them. \u00a0In other-words, put your dishes in the dishwasher when you are done eating and you won&#8217;t have a messy kitchen. \u00a0(sorry for the weird reference to one of my other passions &#8211; food) \u00a0So if you have this:<\/p>\n<pre><code>var reallyLargeVariable = \"an extreeeeeeeeeeeemly long string....... and more data here..... and even more here...\";\r\n<\/code><\/pre>\n<p>and at some point you no longer need that variable, like when your process has completed, then you should follow it with something like this:<\/p>\n<pre><code>reallyLargeVariable = \"\";  OR reallyLargeVariable = NULL;\r\n<\/code><\/pre>\n<p>Try doing this, add the memory logger mentioned above, re-start NodeJS and re-run your application and see if this made a difference. \u00a0If all goes well you should see something of a difference from your first tests in that your rss numbers should stay lower than before.<\/p>\n<h2>Forcing Garbage Collection<\/h2>\n<p>In my experience, clearing my variables still didn&#8217;t seem to be the magic bullet. \u00a0So I went one step further.<\/p>\n<p>Like other programming languages, NodeJS and v8 do have a garbage collection process that should run from time to time to clear unused memory. \u00a0However as you may have found in your research, this is a weakness of the NodeJS and v8 combination. \u00a0For whatever reason garbage collection doesn&#8217;t seem to run often enough.<\/p>\n<p>It is possible in NodeJS to force garbage collection to run, but it takes a few steps. \u00a0The most important step is to run\u00a0your NodeJS server with garbage collection exposed. \u00a0To do that, you need to add the expose garbage collection flag when you start NodeJS.<\/p>\n<pre><code>node --expose-gc myServer.js<\/code><\/pre>\n<p>I personally use <a href=\"https:\/\/www.npmjs.com\/package\/forever\" target=\"_blank\" data-lasso-id=\"429\" rel=\"noopener\">forever<\/a> to ensure that the server stays up if it were to crash. \u00a0If you use that as well, you would instead use the command. \u00a0Subsequent restarts will respect the expose garbage collection command.<\/p>\n<pre><code>forever start -c \"node --expose-gc\" myServer.js<\/code><\/pre>\n<p>Now that we are up and running with manual garbage collection enabled, you just need to call it in your scripts. \u00a0To do that, simply call:<\/p>\n<pre><code>global.gc();<\/code><\/pre>\n<h3>Run Garbage Collection Function<\/h3>\n<p>I personally use this function to trigger garbage collection.<\/p>\n<pre><code>function runGC() {\r\n if( typeof global.gc != \"undefined\" ){\r\n \/\/ console.log(\"Mem Usage Pre-GC \"+util.inspect(process.memoryUsage()));\r\n global.gc();\r\n \/\/ console.log(\"Mem Usage Post-GC \"+util.inspect(process.memoryUsage()));\r\n }\r\n}<\/code><\/pre>\n<p>This function also checks to see that your server is running with garbage collection exposed, thus preventing issues if you don&#8217;t start that way. \u00a0Also, I&#8217;ve built the memory logging into this function that I un-comment when I need to do further testing and debugging.<\/p>\n<p>Calling this in your code, simply use:<\/p>\n<pre><code>runGC();\r\n<\/code><\/pre>\n<h2>Summary<\/h2>\n<p>While NodeJS and v8 are powerful tools, they seem to be lacking in memory management and at times require some manual effort to ensure that your server doesn&#8217;t crash due to running out of memory (ENOMEM). \u00a0Clearing unused variables and manually running garbage collection are two great methods to accomplish this task.<\/p>\n<h2>Update &#8211; Finding More Memory Leaks<\/h2>\n<p>After writing this post I continued to monitor my server and found that there were still further memory leaks. \u00a0After digging through the code more, I did find another deeper issue &#8211; you can read all about on this article. \u00a0<a href=\"https:\/\/promincproductions.com\/blog\/node-js-fabric-js-memory-leaks-prevent-enomem\/\" data-lasso-id=\"430\">Node JS Fabric JS Memory Leaks &#8211; Prevent ENOMEM<\/a><\/p>","protected":false},"excerpt":{"rendered":"<p>I&#8217;ve been running a NodeJS server for a web application for over a year now, and while NodeJS [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":956,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"wprm-recipe-roundup-name":"","wprm-recipe-roundup-description":"","_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_feature_clip_id":0,"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_post_was_ever_published":false},"categories":[12,52,5],"tags":[],"class_list":["post-955","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-javascript-jquery","category-nodejs","category-website-development"],"jetpack_featured_media_url":"https:\/\/promincproductions.com\/blog\/wp-content\/uploads\/2015\/08\/nodejs-enomem-error-message.jpg","jetpack_shortlink":"https:\/\/wp.me\/p4BbcR-fp","jetpack_sharing_enabled":true,"amp_enabled":true,"_links":{"self":[{"href":"https:\/\/promincproductions.com\/blog\/wp-json\/wp\/v2\/posts\/955","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/promincproductions.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/promincproductions.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/promincproductions.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/promincproductions.com\/blog\/wp-json\/wp\/v2\/comments?post=955"}],"version-history":[{"count":3,"href":"https:\/\/promincproductions.com\/blog\/wp-json\/wp\/v2\/posts\/955\/revisions"}],"predecessor-version":[{"id":1210,"href":"https:\/\/promincproductions.com\/blog\/wp-json\/wp\/v2\/posts\/955\/revisions\/1210"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/promincproductions.com\/blog\/wp-json\/wp\/v2\/media\/956"}],"wp:attachment":[{"href":"https:\/\/promincproductions.com\/blog\/wp-json\/wp\/v2\/media?parent=955"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/promincproductions.com\/blog\/wp-json\/wp\/v2\/categories?post=955"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/promincproductions.com\/blog\/wp-json\/wp\/v2\/tags?post=955"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}