1 Mechanically Detect Memory Leaks With Puppeteer
Ewan Smathers edited this page 2025-08-14 16:10:33 +08:00


About half a 12 months ago Bronley Plumb kindly made me conscious of a memory leak in certainly one of my open-source packages. To see this memory leak in motion it was necessary to open a browser and MemoryWave Official its dev instruments to execute some manual steps. On top of that, the memory had to be inspected manually. It was a sophisticated process. Usually I simply add a failing test before I fix a bug. This time it was a bit extra tough. But in the long run I found a means to test the memory consumption mechanically and right here is what I came up with. If you are not involved in the adventurous path which led me to the solution feel free to skip proper to the tip to read on from there. What's a memory leak? Usually a memory leak is the situation wherein a software program holds on to a chunk of Memory Wave which it does not actually need anymore. In JavaScript this almost definitely means that there is a reference to an object somewhere which you totally forgot about.


But for the garbage assortment it is not possible to distinguish between objects that are nonetheless in use and those which have just been forgotten someplace. Traditionally a memory leak was one thing that web developers did not must care about. Each hyperlink on a page triggered a new web page to be loaded which in turn wiped the memory. However memory leaks are normally very shy and only turn into noticeable when a particular program retains operating for a long time. With todays Single Page Applications and Progressive Web Apps the state of affairs has modified. Many websites do behave like apps and are designed to run for a long time and that is particularly true for apps that use the online Audio API. The memory leak in query was present in standardized-audio-context which is a library to achieve cross browser compatibility for that API. Essentially the most easy instance of a memory leak that I may think of is attaching some metadata to an object.


As an example you may have a few objects and also you want to retailer some metadata for each of them. However you don't wish to set a property on those objects because you need to maintain the metadata in a separate place. This can be solved through the use of a Map as shown in the following snippet. It allows to store some metadata, to get it again and to delete it once more. All that is required is a Map which uses an object as the important thing to index its metadata. However what if an object with metadata will not be referenced anywhere else anymore? It still cannot be rubbish collected as a result of the Map still has a reference to it to index the metadata. The next instance is after all contrived but many memory leaks will be reduced to one thing so simple as this. All the created objects do survive every garbage assortment as a result of the Map nonetheless has a reference to them. That is the right use case for a WeakMap.
infoquu.com


The references held by a WeakMap don't prevent any object from being rubbish collected. By replacing the Map with a WeakMap this common cause for a memory leak might be eliminated. The issue that brought about the memory leak in my code was very related though it was not that obvious to identify. Puppeteer is a instrument which can be utilized to remote management Chrome or another Chromium browser. It's a simpler alternative to Selenium and MemoryWave Official WebDriver but it has the downside that it solely works with browsers based on Chromium (for now). It comes with access to some APIs which aren't accessible by Selenium because it tries to interact with a website like an actual consumer. Puppeteer alternatively has access to many APIs which are not accessible to normal users. This works by utilizing the Chrome DevTools Protocol. A type of issues that Puppeteer can do which Selenium cannot is inspecting the memory. And that is of course tremendous helpful when trying to find memory leaks.


At first look there appears to be a operate within the API of Puppeteer which provides all that is required to track the memory usage. It is the web page.metrics() methodology. It does among different issues also return a metric known as JSHeapUsedSize. That is the variety of bytes that V8, the JavaScript engine utilized in Chrome, uses as memory. Sadly getting the dimensions of the Memory Wave just isn't enough. The memory of a JavaScript program is managed by a very autonomous garbage assortment. Not like the garbage assortment in the true world which usually shows up on a really strict and well known schedule the JavaScript garbage collection does its job each time it thinks it's the right time to take action. It might probably usually not be triggered from within the JavaScript code. Nevertheless it is important to ensure it ran before inspecting the memory to ensure that all the trash has been picked up and the memory consumption has been computed based on the most recent adjustments made by the code.