Tuesday, February 7, 2023
Learning Code
  • Home
  • JavaScript
  • Java
  • Python
  • Swift
  • C++
  • C#
No Result
View All Result
  • Home
  • JavaScript
  • Java
  • Python
  • Swift
  • C++
  • C#
No Result
View All Result
Learning Code
No Result
View All Result
Home JavaScript

An open source framework for finding JavaScript memory leaks

learningcode_x1mckf by learningcode_x1mckf
September 13, 2022
in JavaScript
0
An open source framework for finding JavaScript memory leaks
74
SHARES
1.2k
VIEWS
Share on FacebookShare on Twitter


You might also like

An Introduction to Lodash and Its Benefits for JavaScript Developers – MUO – MakeUseOf

Mimic Javascript actions on identical element? – JavaScript – SitePoint

How To Hire a Professional JavaScript Developer and Find the Best … – Intelligent Living

  • We’ve open-sourced MemLab, a JavaScript reminiscence testing framework that automates reminiscence leak detection.
  • Finding and addressing the basis reason behind reminiscence leaks is vital for delivering a top quality person expertise on net functions.
  • MemLab has helped engineers and builders at Meta enhance person expertise and make important enhancements in reminiscence optimization. We hope it’ll do the identical for the bigger JavaScript neighborhood as properly.

In 2020, we redesigned Facebook.com as a single-page software (SPA) that does most of its rendering and navigation utilizing client-side JavaScript. We used an identical structure to construct most of Meta’s different in style net apps, together with Instagram and Office. And whereas this structure permits us to offer quicker person interactions, a greater developer expertise, and a extra app-like really feel, sustaining the net app state on the shopper makes successfully managing client-side reminiscence extra complicated.

Folks utilizing our net apps will usually discover efficiency and practical correctness points instantly. A reminiscence leak, nonetheless, is a unique story. It isn’t instantly perceivable, as a result of it eats up a bit of reminiscence at a time — affecting the whole net session and making subsequent interactions slower and fewer responsive.

To assist our builders deal with this, we constructed MemLab, a JavaScript reminiscence testing framework that automates leak detection and makes it simpler to root-cause reminiscence leaks. We’ve used MemLab at Meta to efficiently include unsustainable reminiscence will increase and determine reminiscence leaks and reminiscence optimization alternatives throughout our merchandise and infra.

We’ve already open-sourced MemLab on GitHub, and we’re excited to work with the JavaScript neighborhood and have builders begin utilizing MemLab in the present day.

Why we developed MemLab

Traditionally, we spent a number of time measuring, optimizing, and controlling page load and interaction time, in addition to JavaScript code measurement. We constructed automated techniques that alerted us when there have been regressions in these metrics — each earlier than and after code landed in manufacturing — in order that we may act rapidly to repair these points and forestall the modifications from ever touchdown in manufacturing.

Comparatively, we hadn’t executed a lot work for managing net in-browser reminiscence. And once we analyzed the brand new Fb.com’s reminiscence utilization, we discovered that each reminiscence utilization and the variety of out-of-memory (OOM) crashes on the shopper aspect had been climbing.

Excessive reminiscence utilization has a statistically important and adverse influence on:

  • Web page load and interplay efficiency (how a lot time it takes to load a web page or carry out an interplay)
  • Consumer engagement metrics (energetic customers, time spent on web site, variety of actions carried out)

What causes excessive reminiscence utilization in net functions?

As a result of reminiscence leaks aren’t normally apparent, they seldom get caught in code evaluate, are arduous to identify throughout growth, and are sometimes tough to root-cause in manufacturing. However mainstream JavaScript runtimes all have rubbish collectors, so how is reminiscence leaking within the first place?

JavaScript code can expertise reminiscence leaks by retaining hidden references to things. Hidden references may cause reminiscence leaks in lots of sudden methods.

For instance:

var obj = ;
console.log(obj);
obj = null;

In Chrome, this code leaks obj regardless that we set the reference to null. This occurs as a result of Chrome must hold an inner reference to the printed object in order that it may be inspected within the net console later (even when the net console shouldn’t be opened).

There will also be circumstances the place reminiscence shouldn’t be technically leaked however grows linearly and unbounded throughout a person session. The most typical causes of this are client-side caches that don’t have any eviction logic inbuilt and infinite scroll lists that don’t have any virtualization to take away earlier objects from the record as new content material is added.

We additionally didn’t have automated techniques and processes in place to manage reminiscence, so the one protection in opposition to regressions was consultants periodically digging into reminiscence leaks by way of Chrome DevTools, which was not scalable contemplating we’re transport a nontrivial variety of modifications day-after-day.

How MemLab works

In a nutshell, MemLab finds reminiscence leaks by working a headless browser by way of predefined take a look at eventualities and diffing and analyzing the JavaScript heap snapshots.

This course of occurs in six steps:

1. Browser interplay

To seek out leaked objects on a goal web page (B). MemLab automates a browser utilizing Puppeteer and visits the take a look at pages within the following order:

  1. Navigate to a unique tab (A) and get heap SA.
  2. Navigate to the goal web page (B) and get heap SB.
  3. Come again to the earlier web page (A’) and get heap SA’.

2. Diffing the heap 

Once we navigate to a web page after which navigate away from it, we’d anticipate a lot of the reminiscence allotted by that web page to even be freed — if not, it’s extremely suggestive of a reminiscence leak. MemLab finds potential reminiscence leaks by diffing the JavaScript heap and recording the set of objects allotted on web page B that weren’t allotted on Web page A however are nonetheless current when Web page A is reloaded. Or, extra formally, the superset of objects leaked from the goal web page will be derived as (SB SA) ∩ SA’ ).

3. Refining the record of reminiscence leaks

The leak detector additional incorporates framework-specific data to refine the record of leaked objects. For instance, Fiber nodes allotted by React (an interior knowledge construction React makes use of for rendering the digital DOM) must be launched once we clear up after visiting a number of tabs.

4. Producing retainer traces

MemLab traverses the heap and generates retainer traces for every leaked object. A retainer hint is an object reference chain from the GC roots (the entry objects in a heap graph from which rubbish collectors traverse the heap) to a leaked object. The hint exhibits why and the way a leaked object is stored alive in reminiscence. Breaking the reference chain means the leaked object will now not be reachable from the GC root and subsequently will be rubbish collected. By following the retainer hint one step at a time, yow will discover the reference that must be set to null (however wasn’t, resulting from a bug).

5. Clustering retainer traces

Typically sure interactions can set off 1000’s of leaked objects. It will be overwhelming to indicate all of the retainer traces on this case. MemLab clusters all retainer traces and exhibits one hint for every cluster of leaked objects that share related retainer traces. The hint additionally consists of debug info, equivalent to dominator nodes and retained sizes.

6. Reporting the leaks

We run MemLab at common intervals all through the day to get a steady sign on reminiscence regressions. Any new regressions are added to an inner dashboard, the place clustered retainer traces of all reminiscence leaks detected are gathered and categorized. Builders can then click on and think about the properties of objects on the retainer hint of every reminiscence leak.

(Word: This dashboard shouldn’t be a part of the open supply launch of MemLab, however one thing related might be added to any CI/CD pipeline.)

MemLab’s options

Reminiscence leak detection

For in-browser reminiscence leak detection, the one enter MemLab requires from builders is a test scenario file that defines how to interact with the webpage by overriding three callbacks with the Puppeteer API and CSS selectors. MemLab robotically diffs the JavaScript heap, refines reminiscence leaks, and aggregates outcomes.

Graph-view API of JavaScript heap

MemLab helps a self-defined leak detector as a filter callback that’s utilized to every leak candidate object allotted by the goal interplay however by no means launched afterwards. The leak filter callback can traverse the heap and determine which objects are reminiscence leaks. For instance, our built-in leak detector follows the return chain of a React Fiber node and checks if the Fiber node is indifferent from the React Fiber tree.

MemLab

To permit the context of every candidate leak to be analyzed, MemLab offers a memory-efficient graph view of the JavaScript heap. This permits querying and traversing the JavaScript heap with out having any area data about V8’s heap snapshot file construction.

Within the graph view, every JavaScript object or native object within the heap is a graph node, and every JavaScript reference within the heap is a graph edge. The heap measurement of an actual software is commonly giant, so the graph view must be memory-efficient whereas offering an intuitive object-oriented heap-traversal API. Due to this fact, the graph nodes are designed to be digital and never interconnected by way of JavaScript references. When the evaluation code traverses the heap, the digital graph view partially constructs the touched part of the graph just-in-time. Any a part of the graph will be simply deallocated since these digital nodes don’t have JavaScript references to one another.

The heap graph view will be loaded from JavaScript heap snapshots taken from Chromium-based browsers, Node.js, Electron, and Hermes. This permits for complicated patterns to be analyzed and solutions questions equivalent to, “What number of React Fiber nodes are alternate Fiber nodes, that are utilized in  incomplete concurrent renders?” or “What’s the complete retained measurement of unmounted react elements?”.

import getHeapFromFile from '@memlab/heap-analysis';
const heapGraph = await getHeapFromFile(heapFile);
heapGraph.nodes.forEach(node => {
  // heap node traversal
  node.sort
  node.references
);

Reminiscence assertions

A Node.js program or Jest take a look at may use the graph-view API to get a heap graph view of its personal state, to do self-memory checking, and write all kinds of memory assertions.

import sort IHeapSnapshot from '@memlab/core';
import config, takeNodeMinimalHeap, tagObject from '@memlab/core';

take a look at('reminiscence take a look at', async () => 
  config.muteConsole = true;
  const o1 = ;
  let o2 = ;

  // tag o1 with marker: "memlab-mark-1", doesn't modify o1 in any manner
  tagObject(o1, 'memlab-mark-1');
  // tag o2 with marker: "memlab-mark-2", doesn't modify o2 in any manner
  tagObject(o2, 'memlab-mark-2');

  o2 = null;

  const heap: IHeapSnapshot = await takeNodeMinimalHeap();

  // anticipate object with marker "memlab-mark-1" exists
  anticipate(heap.hasObjectWithTag('memlab-mark-1')).toBe(true);

  // anticipate object with marker "memlab-mark-2" will be GCed
  anticipate(heap.hasObjectWithTag('memlab-mark-2')).toBe(false);

, 30000);

Reminiscence toolbox

Along with reminiscence leak detection, MemLab features a set of built-in CLI commands and APIs for locating reminiscence optimization alternatives:

  • Break down heap by object shapes (e.g., arguments, postRun, preRun, fairly, thisProgram, …) as an alternative of classifying objects based mostly on constructor names (e.g., Object). That is helpful to rapidly detect and root-cause important reminiscence utilized by object literals.
  • Detect continuous individual object growth or object shape growth. MemLab can take a collection of heap snapshots as enter and discover which object or class of objects retains rising in measurement over time.
  • Find duplicate string instances. V8 doesn’t at all times do string interning optimization, which implies two JavaScript string primitives with the identical worth might be represented by two completely different native objects in V8’s heap.
Inner UI for looking reminiscence leaks. (mockup, for illustration functions solely)
MemLab
Inner UI for diagnosing reminiscence leak traces. (mockup, for illustration functions solely)

Utilizing MemLab at Meta: Case research 

Over the previous few years, we’ve used MemLab to detect and diagnose reminiscence leaks and have gathered insights which have helped us optimize reminiscence, considerably enhance reminiscence and reliability (lowering OOM crashes), and enhance person expertise.

MemLab OOM crashes reduction
We decreased OOM crashes on Fb.com by 50 p.c within the first half of 2021.

React Fiber node cleanup

For rendered elements, React builds a Fiber tree — an interior knowledge construction React makes use of for rendering the digital DOM. Though the Fiber tree appears like a tree, it’s a bidirectional graph that strongly connects all Fiber nodes, React part situations, and the related HTML DOM parts. Ideally, React maintains references to the basis of the part’s Fiber tree and retains the Fiber tree from being rubbish collected. When a part is unmounted, React breaks the connection between the host root of the part and the remainder of the Fiber tree, which may then be rubbish collected.

The draw back of getting a strongly related graph is that if there may be any exterior reference pointing to any a part of the graph, the entire graph can’t be rubbish collected. For instance, the next export assertion caches React elements on the module scope degree, so the related Fiber tree and indifferent DOM parts are by no means launched.

export const Element = (( 
  <Listing> ... </Listing> 
): React.Component<typeof Listing>);

It’s additionally not simply the React knowledge buildings that may be stored alive. Hooks and their closures may hold alive every kind of different objects. Because of this a single React part leak may trigger the leak of a major a part of a web page’s objects, main to large reminiscence leaks.

To forestall the cascading impact of reminiscence leaks within the Fiber tree, we added a full traversal of a tree that does aggressive cleanup when a part is unmounted in React 18 (because of Benoit Girard and the React group). This permits the rubbish collector to do a greater job at cleansing up an unmounted tree. Any unintended reminiscence leak is bounded to a smaller leak measurement. This repair decreased common reminiscence utilization on Fb by virtually 25 p.c, and we noticed giant enhancements throughout different websites utilizing React once they upgraded. We had been anxious that this aggressive cleanup may decelerate unmounting in React, however surprisingly, we noticed a major efficiency win due to reminiscence reductions.

Relay string interning

By leveraging the heap evaluation APIs in MemLab, we discovered that strings occupied 70 p.c of the heap, and half of these strings had at the very least one duplicated occasion. (V8 doesn’t at all times do string interning, which is an optimization that deduplicates string situations with the identical worth.)

Once we additional queried duplicated string patterns and clustering retainer traces we discovered that a good portion of string reminiscence is consumed by cached key strings in Relay. Relay generates cached keys for fragments by doing duplication, serialization, and concatenation. The string keys are additional copied and concatenated for cached keys of different sources (e.g., fragments) in Relay. By collaborating with the Relay and React Apps groups, we optimized Relay cache key strings by interning and shortening overlong string keys on the shopper aspect.

This optimization enabled Relay to cache extra knowledge, permitting the location to indicate extra content material to customers, particularly when there may be restricted RAM on the shopper aspect. We noticed a 20 p.c discount in reminiscence p99 in addition to OOM crashes, quicker web page rendering, improved person expertise, and income wins.

Attempt MemLab in the present day

We’re excited to open-source MemLab and have builders begin utilizing it. We’re particularly taken with seeing which use circumstances the neighborhood finds helpful.

You’ll be able to set up MemLab by way of npm or construct it from the GitHub repo:

npm i -g memlab

We even have a quick start guide to assist builders get began.

In the event you’ve tried MemLab out by yourself venture, please reach out and tell us the way it labored for you!

Acknowledgements

We’d prefer to thank Tulga Narmandakh and the remainder of the Core Well being Expertise group for his or her contributions towards serving to open-source MemLab.





Source link

Share30Tweet19
learningcode_x1mckf

learningcode_x1mckf

Recommended For You

An Introduction to Lodash and Its Benefits for JavaScript Developers – MUO – MakeUseOf

by learningcode_x1mckf
February 6, 2023
0
Google expands open source bounties, will soon support Javascript fuzzing too – ZDNet

An Introduction to Lodash and Its Benefits for JavaScript Developers  MUO - MakeUseOf Source link

Read more

Mimic Javascript actions on identical element? – JavaScript – SitePoint

by learningcode_x1mckf
February 6, 2023
0
Google expands open source bounties, will soon support Javascript fuzzing too – ZDNet

Mimic Javascript actions on identical element? - JavaScript  SitePoint Source link

Read more

How To Hire a Professional JavaScript Developer and Find the Best … – Intelligent Living

by learningcode_x1mckf
February 6, 2023
0
Google expands open source bounties, will soon support Javascript fuzzing too – ZDNet

How To Hire a Professional JavaScript Developer and Find the Best ...  Clever Residing Source link

Read more

How to Use Regular Expressions in JavaScript – MUO – MakeUseOf

by learningcode_x1mckf
February 6, 2023
0
Google expands open source bounties, will soon support Javascript fuzzing too – ZDNet

How to Use Regular Expressions in JavaScript  MUO - MakeUseOf Source link

Read more

Web Development & JavaScript Trends in 2023 – Electronicsmedia

by learningcode_x1mckf
February 6, 2023
0
Google expands open source bounties, will soon support Javascript fuzzing too – ZDNet

Web Development & JavaScript Trends in 2023  Electronicsmedia Source link

Read more
Next Post
Learn How to Join Strings in Java

Learn How to Join Strings in Java

Leave a Reply Cancel reply

Your email address will not be published. Required fields are marked *

Related News

East Java wins two Energy Council awards for energy transition

East Java wins two Energy Council awards for energy transition

October 26, 2022
Functions and Loops – Real Python

Functions and Loops – Real Python

September 4, 2022
“Please, for the love of all things holy, find a different color than orange” – Hacking with Swift

“Please, for the love of all things holy, find a different color than orange” – Hacking with Swift

September 7, 2022

Browse by Category

  • C#
  • C++
  • Java
  • JavaScript
  • Python
  • Swift

RECENT POSTS

  • C++ Is TIOBE's Language Of The Year – iProgrammer
  • JobRunr, the Java Scheduler Library, Released Version 6.0 – InfoQ.com
  • An Introduction to Lodash and Its Benefits for JavaScript Developers – MUO – MakeUseOf

CATEGORIES

  • C#
  • C++
  • Java
  • JavaScript
  • Python
  • Swift

© 2022 Copyright Learning Code

No Result
View All Result
  • Home
  • JavaScript
  • Java
  • Python
  • Swift
  • C++
  • C#

© 2022 Copyright Learning Code

Are you sure want to unlock this post?
Unlock left : 0
Are you sure want to cancel subscription?