• Facebook
  • Twitter
  • Gplus
  • Github
  • Mail
  • Login
    • Register
  • Blog
StrongLoop
  • Products & Services
    • API Connect
    • LoopBack
    • Support
    • Certification
    • Consulting
    • Training
  • Get Started
  • Pricing
  • Documentation
    • Documentation – IBM API Connect
    • Documentation – LoopBack Framework
  • Developers
    • LoopBack
    • Modules
    • Express
    • Testimonials
    • Performance Tips
    • For Java, Rails, PHP and .NET Developers
    • Node Infographic
    • Events
    • Videos
    • Forums
  • Search

How-to: Heap Snapshots and Handling Node.js Memory Leaks

October 2, 2013/4 Comments/in How-To /by Marc Harter
Share

In the beginning, there were memory leaks in JavaScript
… and we could not have cared less.

Then there was Ajax
… and we started to care.

Then there were these long-running Node processes on our production servers
… and we really cared a lot!

Node memory leaks happen. Usually they occur in production where processes experience the weight of their purpose and a mandate for uptime. Thankfully, the core of Node is becoming more and more resilient to leaks. However, between our code and the modules we include, leaks still happen and it’s good to be prepared to handle them.

A runaway Node process

A runaway Node process

Ben Noordhuis, a core contributor and member of the StrongLoop team, created the heapdump module to provide developers a simple mechanism for producing V8 heap snapshots. In this article, we will talk about:

  1. Instrumenting your app with heapdump
  2. Techniques for collecting snapshots
  3. Resources for snapshot analysis

These may not be the tools you are looking for. If you observed closely at the top output above, you may have noticed I cheated. My app has barely been running; however, it is taking up a lot of memory already. If you have an app where memory leaks can be duplicated, use tools like node-webkit-agent or node-inspector locally to help pinpoint the problem.

Instrumenting your application

First, install heapdump using npm:

1
npm install heapdump

Once installed, you need to load the heapdump module into your application:

1
var heapdump = require('heapdump')

When you’ve done that, you can take snapshots in two different ways. The first way is to use the writeSnapshot method:

1
2
3
var heapdump = require('heapdump')
...
heapdump.writeSnapshot()

The second way is to send a SIGUSR2 signal to the process (UNIX only):

1
kill -USR2 <pid>

Snapshots are written to your current working directory with a timestamp like heapdump-179641052.37605.heapsnapshot. There will also be xxxx.log of the same name written containing stats about the heap when the snapshot was taken.

Setting the current working directory

It is important to make sure that your current working directory (CWD) is writable by the process. If it isn’t, no snapshots will be written. You can set the CWD manually in your application with:

1
process.chdir('/path/to/writeable/dir')

Loading snapshots into Chrome Dev Tools

When you have taken a snapshot, load the xxxx.heapsnapshot file into Chrome Dev Tools by heading to the Profiles tab, right-clicking the Profiles pane and selecting Load:

Right-click Profiles pane in Dev Tools to load a snapshot from disk

Right-click Profiles pane in Dev Tools to load a snapshot from disk

Then, you are able to view the contents using the tools:

Heap snapshot tools in Dev Tools

Heap snapshot tools in Dev Tools

Strategies for taking snapshots

Unfortunately, not all memory leaks are created equal. Some are slow leaks that can take hours or even days to build. Some happen on under-utilized code paths. Some are constant. So when should you take a snapshot? The answer: it depends.

It’s good to have a baseline snapshot to compare memory usage. You may want to generate a snapshot after your application is up and running for a few minutes. If you are running a UNIX server, send a SIGUSR2 to the process to record the snapshot. As you notice the memory usage increase, repeat the process to gather more data for analysis later.

Whenever you take a heap snapshot, V8 will perform a GC prior to taking the snapshot to give you an accurate picture of what is sticking around in your process. So don’t be surprised if you notice your memory usage drop after taking a snapshot.

You could also programmatically take snapshots on an interval that makes sense for the memory growth observed:

1
2
3
4
5
var heapdump = require('heapdump')
...
setInterval(function () {
  heapdump.writeSnapshot()
}, 6000 * 30) <strong>(1)</strong>

  1. Write a snapshot to the current working directory every half hour.

Taking a snapshot is not free. It will peg a CPU until the snapshot is written. The larger the heap, the longer it takes. On UNIX, snapshots are written in a forked process asynchronously (Windows will block).

You could also watch the memory usage growth programmatically and generate snapshots:

1
2
var heapdump = require('heapdump')
var nextMBThreshold = 0 <strong>(1)</strong>

1
2
3
4
5
6
7
setInterval(function () {
  var memMB = process.memoryUsage().rss / 1048576 <strong>(2)</strong>
  if (memMB &gt; nextMBThreshold) { <strong>(3)</strong>
    heapdump.writeSnapshot()
    nextMBThreshold += 100
  }
}, 6000 * 2) <strong>(4)</strong>

  1. Next MB threshold to be breached
  2. Calculate RSS size in MB
  3. Whenever we breach the nextMBThreshold, write a snapshot and increment the threshold by 100 MB.
  4. Run this check every couple minutes

Analyzing snapshot data

Once you have collected two or more snapshots representing the change in memory, it is time to analyze the data. Copy the snapshots to your local machine, load the snapshots into Chrome Dev Tools and start analyzing!

If you haven’t worked with heap snapshot analysis in Dev Tools, here are some valuable links to get you started:

  1. Memory Analysis 101
  2. Taming The Unicorn: Easing JavaScript Memory Profiling In Chrome DevTools

I find the Comparison view helpful. Unfortunately, Comparison hasn’t worked for imported snapshots. However, this bug has recently been fixed (see bug ticket)!

For more detail on the purpose for the Comparison view and the other views, see the heap profiling documentation.

Making heap snapshots more concrete

If you are like me, I hardly care about taking heap snapshots until I really need to. Do yourself a favor and practice using these tools before problems arise. Here is a simple process to practice:

  1. Instrument one of your apps with heapdump
  2. If in production, ensure snapshots are being written to the current working directory
  3. Practice taking snapshots with SIGUSR2 if you are on UNIX
  4. Load snapshots into Chrome and take a peak at what is currently stored in your application. Any surprises?

Summary

Memory leaks can happen and thankfully we don’t have tackle them blindly. In this article, we focused on the heapdump module. We looked at the process of instrumenting our application, taking heap snapshots, loading them into Chrome Dev Tools. We then looked at strategies for getting useful data to analyze. Lastly, we covered some resources for analysis using Dev Tools.

What’s next?

  • What’s in the upcoming Node v0.12 release? Six new features, plus new and breaking APIs.
  • Ready to develop APIs in Node.js and get them connected to your data? Check out the Node.js LoopBack framework. We’ve made it easy to get started either locally or on your favorite cloud, with a simple npm install.
  • Need for Node? Learn more about both the private and open options StrongLoop offers.
Share
Share this entry
  • Share on Facebook
  • Share on Twitter
  • Share on Google+
  • Share on Pinterest
  • Share on Linkedin
  • Share on Tumblr
  • Share on Vk
  • Share on Reddit
  • Share by Mail

< Previous Post

Next Post >

Questions?

Contact us
for training and professional services to see how Node.js can accelerate your mobile, IoT and next-generation web APIs.

Recent Posts

  • Creating a Multi-Tenant Connector Microservice Using LoopBackApril 25, 2017 - 7:00 am
  • Systematic Data Design in JavaScript – Featuring Three Data TypesApril 18, 2017 - 7:35 am
  • Announcing LoopBack.next, the Next Step to Make LoopBack Effortlessly ExtensibleApril 13, 2017 - 8:15 am

Categories

  • API Connect (19)
  • api microgateway (1)
  • API Tip (13)
  • Arc (24)
  • BACN (3)
  • Case Studies (3)
  • Cloud (10)
  • Community (263)
  • Espanol (7)
  • Events (38)
  • Express (21)
  • How-To (164)
  • JavaScript Language (21)
    • ES2015/ES6 (6)
  • LoopBack (133)
  • Mobile (30)
  • News (125)
  • Node core (14)
  • Node DevOps (26)
  • Node.js v0.12 (17)
  • Performance Tip (11)
  • Portuguese (31)
  • Press (14)
  • Product (29)
    • API Gateway (2)
  • Resources (8)
  • StrongNode (7)
  • Uncategorized (2)

Archives

  • April 2017
  • March 2017
  • February 2017
  • January 2017
  • December 2016
  • November 2016
  • October 2016
  • September 2016
  • August 2016
  • July 2016
  • June 2016
  • May 2016
  • April 2016
  • March 2016
  • February 2016
  • January 2016
  • December 2015
  • November 2015
  • October 2015
  • September 2015
  • August 2015
  • July 2015
  • June 2015
  • May 2015
  • April 2015
  • March 2015
  • February 2015
  • January 2015
  • December 2014
  • November 2014
  • October 2014
  • September 2014
  • August 2014
  • July 2014
  • June 2014
  • May 2014
  • April 2014
  • March 2014
  • February 2014
  • January 2014
  • December 2013
  • November 2013
  • October 2013
  • September 2013
  • August 2013
  • July 2013
  • June 2013
  • May 2013
  • April 2013
  • March 2013

Compose APIs, Build, Deploy and Monitor Node

Install API Connect

$ npm install -g apiconnect

Create your API Connect project

$ apic loopback

Launch API Designer

$ cd your-project

$ apic edit

API Designer will run on your local browser

An IBM BlueMix account is required to use the Designer. Register for IBM Bluemix

Click To Get Started

get_started

It’s FREE!

Company

  • Partners
  • Careers
  • Contact us

Products

  • API Connect
  • LoopBack Framework
  • API Connect FAQs

Content & News

  • Blog
  • Newsletter
  • Videos
  • Events
  • Infographic

Contact Us

  • Email
  • Twitter
  • GitHub
  • Facebook
  • Google+

Legal

  • Privacy Policy
  • Terms of Use
  • License
© 2016 - IBM Corporation. All rights reserved.
Node.js and Mobile News Round-up – October 1, 2013 Recipes for LoopBack Models, Part 1 of 5: Open Models
Scroll to top