Memory Leaks are Web Performance Killers

javascript-memory-leaks-performance-killers

Developers know memory leaks are bad news and eventually cause an application to crash. Today languages like C# effectively shield developers from memory management. The art of memory management that was common in the Assembly, C and C++ days (I know C++ is still popular) are long gone and for good reason. However the modern web reintroduces our nemesis.

Today's web applications are JavaScript heavy, single page applications. This means the user stays on a page much longer, does more interactions and creates a much larger memory footprint than the classic web. Single Page Applications are in particular different from the classic web site model.

A SPA, especially a line of business application, is designed to stay resident in the browser much longer than a web page. These days I tend to develop and architect enterprise line of business applications and have seen the effects of poor memory management first hand. line of business applications are tools used by an end user at least 8 hours a day, often by thousands of end users at the same time. Memory leaks gradually build pressure as the end user goes about their daily routine. At some point the pressure causes the browser to crash.

The first real modern SPA application I architected had to work across mobile platforms, where resources are more constrained than the familiar desktop. After about 4 years of focus on modern, mobile first applications I can say without hesitation if you are not accounting for mobile you are building an application that is doomed to die soon. That first mobile spa application contained several hundred views, forcing me to invent and research new techniques and methodologies. There were no frameworks available to just plug in, I had to do it on my own. This process proved to be very influential on my philosophies today, but more importantly it taught me to be the master of my domain.

A problem I encountered rather quickly with mobile Safari and Android WebKit was the browser crashing after a few minutes. The cause was too much memory allocated to my application. For the record native applications suffer from the same issue, but I focus on web development, so this is an examination of how memory issue pertain to modern web applications.

There were two things directly contributing to these browser crashes. The SPA architecture meant, or at least I assumed, I needed to download all the markup and templates for all the views in the initial request and keep the markup in the DOM. These assumptions turned out to be false. I wont dive into the solution, you can read about that in my latest book, High Performance Single Page Web Applications. This did lead me to leverage localStorage and deferred content loading.

The second issue was not obvious at the time because tooling did not exist, but memory leaks were a big problem. A memory leak is where memory is allocated to a variable, but not properly dereferenced by the code when no longer needed. The most common reason is poor event binding or event virtualization plaguing many popular JavaScript frameworks. Because the variable has not been released the garbage collector cannot purge it. The memory remains allocated and there is no real way to remove it.

Crashing ChromeCrashing Internet Explorer

Over time these memory leaks add up to a very large memory footprint. If the browser does not crash it grows more and more sluggish. Eventually even desktop browsers crash. Chrome, FireFox, Internet Explorer, Opera and Safari all behave the same. The memory boundaries may vary by browser, operating system and hardware. I have crashed them all with my apps and other applications. Just last night I had a page opened for several hours and it caused Chrome to crash 3 times before I finally closed the culprit. I was not even active on the page, it had a timer routinely removing nodes and replacing them with new content.

It is easy to identify memory leaks using today's development tools. Chrome and Internet Explorer both offer ways to identify these issues. I find Internet Explorer much easier to identify leaks using the memory snapshot tool. When the snapshot tool identifies memory leaks it list the number in a blue circle in the snapshot's tile. Opening the snapshot lets you navigate variables and functions to find the offending code.

My research shows common memory leak causes are improper closure use and event virtualization. Unfortunately for many developers god frameworks like Angular, Backbone Knockout are the cause of memory leaks. Despite these libraries open source nature the average developer does not have the time or resources to optimize these frameworks, much less get a pull request merged into the main branch. They are at the mercy of the team running the project.

A few weeks ago I took the time to evaluate some live web applications, some using some known god frameworks, others just because I was visiting them. I was not surprised to find memory leaks just about across the board. hats off to Southwest.com for having 0 memory leaks when I profiled them. Most have some small leaks, but small leaks add up over time. Others are just a sieve, leaking stuff everywhere. These snapshots were taken after the application's initial load, so it should be 'fresh' and clean of any affects of long term usage.

Southwest with 0 Memory LeaksNY Times Memory LeaksSilver Reader Memory LeaksBiztalk 360 Memory LeaksEmber JS Home Page Memory LeaksAngular Home Page Memory LeaksAzure Dashboard Memory Leaks

Am I alone? Well know, but I do make the effort to test my applications for leaks. Here is a screen shot of me working through the memory leak process for the book's sample application. You can see as I navigate through the application's views I eventually trigger a leak. That leak was in my SPA library and added a new leak every view swap. Over the course of the day this would be catastrophic. Fortunately tools like the Internet Explorer memory profiler let me see the cause and correct it before it was shipped to production.

Tracking Down a Memory Leak

Conclusion

I am not saying stop using these god frameworks, but you should be cautious. Despite their popularity they come with baggage that builds up over time. My advice is to avoid using their event virtualization functionality and possibly anything using timers where content is added and removed. addEventListener is not hard to use and gives you the control you need to avoid many common memory leak scenarios. And just because you are not using any 3rd party library does not release you from the memory leak problem, you need to be diligent with your code. It is the code you own and have full control over and is the easiest to correct.

Use the developer tools available in the modern browsers. They are designed to help you track down web application memory leaks. Learn to use browser storage and deferred content loading to shrink your memory footprints. Avoid keeping large amounts of data in memory. Even though SPAs are dynamic does not mean you need to keep the entire application's data model in memory. Again learn to persist the data in browser storage. All modern browsers support localStorage. All but Safari support IndexDB, a queryable browser data store.

Be the master of your domain. Don't let little memory drips ruin your application. Memory leaks are a sign a framework is not ready for broad use. In all honesty it is one of the primary reasons I have chosen and recommend not using any of the god frameworks for modern web applications.

Share This Article With Your Friends!