Knowing how your users interact with your web application and how they experience it is crucial to provide the best possible experience. So what do you need to know? Start with metrics such as page load times, HTTP request times, and Core Web Vitals – time to the first byte, first contentful paint. If you use Sematext Experience you’ll see a number of other useful metrics for your web applications and websites there. However, metrics themselves are only a part of the whole picture.
When interacting with your web application users may experience bugs that can affect their experience and make them never want to return. We need to be sure that we are aware of all the issues that affect our users, as soon as they appear in production or, ideally, before production. One such issue is a memory leak.
When it occurs, your application slows down gradually making it unusable at some point. In extreme cases, it can slow down the whole web browser and the computer that runs it in the process, eventually causing browser crashes. Such issues are also hard to track and debug because they may not be quickly visible and occur only when interacting with the web application for a longer time.
Sematext Experience, our real user monitoring tool, though, has a trick up its sleeve and enables you to monitor the memory usage of your web applications. This allows you to quickly and efficiently detect memory leaks and this blog post will demonstrate just how to do that.
If you’re new to RUM, check out our guide where we explain what is real user monitoring, how it works, and share examples of how to use it to reap its benefits.
Now let’s learn how to troubleshoot memory leaks.
What Is a Memory Leak
In computer science, a memory leak is a leak of resources when computer software incorrectly manages memory allocation. A memory leak occurs when your web application assigns memory and keeps using it even though it is no longer needed.
What Causes Memory Leaks: Signs You Should Look Out For
Your web application will create and use various constants, variables, and functions to perform its work. They all require memory. In Javascript and other high-level programming languages, when a resource is no longer needed it will be automatically removed by the automatic memory management system, called garbage collector.
The memory is released when it is no longer assigned in the code. However, there are situations when the memory is not released because it continues to be assigned through the life cycle of the application. There are situations when that is needed, but when we no longer need a given piece of information, and yet we keep it assigned, we can talk of a memory leak.
In frontend applications, there are a few common patterns that can cause memory leaks. Those include:
- closures – inner functions having references to outer functions variables. That way an inner function is preventing the garbage collector from releasing the memory.
- accidental global variables – previously undeclared variables will become global and will not be released.
- unbound collections – array, maps, sets they allow us to store data in a given way, but with buggy code, they can result in a memory leak because of keeping the references forever. We will see such an example later in this blog post.
- detached DOM referenced – an element of Document Object Model that is no longer used, but is still referenced.
- unbound timers – timers running forever and keeping objects assigned may lead to memory leaks.
How to Detect Memory Leaks: Application Example
To test the actual memory leak I created a very simple web application that simulates e-commerce user behavior tracking. The web page tracks products that users interact with when browsing through the shop. So every displayed ad, every product returned from the search, each product added to the cart – all of them are placed in an array. A very simple code that looks like this:
function(product, timestamp, page) { visited.push({product, timestamp, page}) }
The further idea is to store it in the backend by periodically sending the data. However, to create the leak, we “forget” to do one thing – after sending the data to the backend we are not clearing the visited array. That means that the data continues to be referenced from our web application. If the user is not closing the tab, the data will remain and will keep getting added leading to a memory leak.
Let’s now look at how we can easily identify the memory leak occurrence by using Sematext Experience and its ability to measure the memory usage of websites and web applications. Once we’ve identified that the memory leak is there and we see a potential source in our web application our job will be way easier.
Integrating Sematext Experience With Your Web Application
The first step is to configure your web application to use the Sematext Browser SDK to ship data to Sematext Cloud.
To do that we add a script before the closing </head> tag:
<script type="text/javascript"> (function(e,r,n,t,s){var a=[];e[s]=function(){a.push(arguments)};e[s].queue=a; var o=[];var i=[];var c=true;var p=void 0;if(window.PerformanceObserver&& window.PerformanceObserver.supportedEntryTypes&&( PerformanceObserver.supportedEntryTypes.indexOf("longtask")>=0|| PerformanceObserver.supportedEntryTypes.indexOf("element")>=0)){ p=new PerformanceObserver(function(e){e.getEntries().forEach(function(e){ switch(e.entryType){case"element":i.push(e);break;case"longtask":o.push(e);break; default:break}})});p.observe({entryTypes:["longtask","element"]})}e[s+"lt"]={ longTasks:o,timingElements:i,inPageLoad:c,observer:p};if(t){var u=r.createElement(n); u.async=1;u.src=t;var f=r.getElementsByTagName(n)[0];f.parentNode.insertBefore(u,f)}}) (window,document,"script","//cdn.sematext.com/experience.js","strum"); </script>
The second step depends on the type of your web application and the web framework that you are using. It tells the Browser SDK how to configure itself. For example, for a standard, multiple web page deployment you would use something like this before the closing </head> tag:
<script type="text/javascript"> strum('config', { token: '<token>', 'receiverUrl': 'https://rum-receiver.sematext.com' }); </script>
If you are using any of the single-page oriented architecture your Sematext Experience App installation instructions will guide you through all steps that are required to send metrics. If you are curious, here are all integrations.
Identifying a Memory Leak
Knowing what the user is doing we can have a look at the charts in Sematext Experience. Just head to the Memory Usage report in your Experience App and you will see the memory usage for your web application:
If you had a web application with the memory leak like the one we simulated you could see that the memory grows indefinitely. Well, not really indefinitely. Sooner or later it would cause the browser to crash. This is not something that you want to see for your application. Instead, the memory usage chart should be bound between some values. For example, like this:
We can see some spikes and dips but in a longer period, the memory usage stays between the maximum and minimum and doesn’t grow indefinitely. We see that in our hypothetical e-commerce example this is not the case. If we go to a single session view we see a constant memory usage growth, from less than 2MB to 12MB, and no drop during that time. This usually means that we have a memory leak somewhere in our web application. By looking at the given session connected to the potential leak we can see the page loads and HTTP requests:
This screen helps us narrow down the bug by showing us everything a user did during a session, which API calls were made, what parts of the web application were used, which resources were loaded. Now we just have to look into those parts of the code and after further investigation, you’ll be able to find the problematic code fragments. Yes, it is that easy!
Supported Browsers
Sematext Browser SDK memory measurements capabilities rely on an API provided by the browser you are using. The mentioned API used to provide memory browser-related metrics to Sematext Experience is only supported in Chrome. It was under the Chrome Origin Trials for Chrome 82 to 87 and ended on 13th January 2021. It will be fully available starting with Chrome 89. This means that your users will have to use the newest Chrome web browser once the version 89 becomes available to the general public.
Conclusion
With the right tools identifying memory leak issues is simple. That is why we’ve built – and are constantly improving – Sematext Experience, so that we can provide you with a comprehensive, affordable, and easy to use monitoring solution.
Don’t hesitate and give Sematext Experience a try if you don’t have a full observability solution yet or if you are evaluating different options. It comes with a 14-day free trial and doesn’t require a credit card. It is as simple as creating a free account and following the onboarding steps!