Closed vigneshsf3992 closed 6 days ago
Here is the test scenario from my attempt to reproduce this issue:
// test.js
function url() {
return 'file:///path/to/test.html';
}
async function action(page) {
await page.click('button[id="render"]');
}
async function back(page) {
await page.click('button[id="destroy"]');
}
module.exports = { action, back, url };
Running command memlab run --scenario ./test.js
got this output:
page-load[12.1MB](baseline)[s1] > action-on-page[13.3MB](target)[s2] > revert[13.3MB](final)[s3]
total time: 50s
Memory usage across all steps:
15.3 _________
13.5 _________
11.7 ___ _ _
9.9 _ _ _
8.1 _ _ _
6.4 _ _ _
4.6 _ _ _
2.8 _ _ _
1.0 _ _ _
1 2 3
MemLab found 2 leak(s)
Number of clusters loaded: 0
--Similar leaks in this run: 30--
--Retained size of leaked objects: 6KB--
[Window] (native) @113239 [3.3KB]
--3 (element)---> [HTMLDocument] (native) @113237 [6.3KB]
--__eventList (property)---> [Object] (object) @828343 [144 bytes]
--events (property)---> [Array] (object) @848663 [116 bytes]
--0 (element)---> [Object] (object) @848665 [24 bytes]
--debounce (property)---> [native_bind] (closure) @819147 [24 bytes]
--bound_this (internal)---> [MXe] (object) @848077 [2.9KB]
--serviceLocator (property)---> [s9e] (object) @828955 [12.2KB]
--services (property)---> [Object] (object) @848267 [12KB]
--cellRendererFactory (property)---> [i9e] (object) @848269 [11.5KB]
--cellRenderMap (property)---> [Object] (object) @848275 [11.4KB]
--RowDragIcon (property)---> [Y7e] (object) @847085 [772 bytes]
--element (property)---> [Detached HTMLTableCellElement] (native) @819269 [120 bytes]
--Similar leaks in this run: 1--
--Retained size of leaked objects: 120 bytes--
[<synthetic>] (synthetic) @1 [13.7MB]
--2 (shortcut)---> [Window / file://] (object) @6395 [1MB]
--__eventList (property)---> [Object] (object) @828319 [192 bytes]
--events (property)---> [Array] (object) @847535 [164 bytes]
--0 (element)---> [Object] (object) @847537 [24 bytes]
--debounce (property)---> [native_bind] (closure) @818691 [24 bytes]
--bound_this (internal)---> [g] (object) @829009 [32.2KB]
--groupModule (property)---> [_Xe] (object) @847747 [1.9KB]
--visualElement (property)---> [Detached HTMLDivElement] (native) @819155 [120 bytes]
However, when I manually take heap snapshots in Chrome, the final snapshot shows no detached DOM elements, which is puzzling. If the browser, for some reason, still considers the DOM elements created during the action
step as attached to the DOM tree, MemLab will not report this as a memory leak by default.
MemLab should detect and report any memory leaks if they occur.
By default, this is not the case; any detection tool can be evaluated by precision and recall when viewed as classifiers. To achieve high precision, MemLab employs heuristics, such as detecting DOM elements detached from the DOM tree, to identify objects allocated during the action
step but not released during the back
step as memory leaks. These heuristics effectively filter out high-confidence memory leaks but may miss leaks not included in the allowlist, therefore sacrificing recall.
To get 100% recall and bypass the heuristic filtering, you can use the --trace-all-objects
CLI flag to capture and dump the clustered traces of all objects that were allocated in action
but not released after back
. However, this will result in noisier data that can be more challenging to read (i.e., low precision).
To get both high precision and high recall for your particular use case, you can utilize the --leak-filter
flag and API provided by MemLab to create custom rules for filtering out memory leaks for that Syncfusion library.
In the below grid sample, a memory leak issue occurs, but MemLab shows no leaks found. Below is the HTML and JavaScript code used in the sample for reproducing the issue:
Report:
Expected Behavior: MemLab should detect and report any memory leaks if they occur.
Actual Behavior: No leaks are reported by MemLab despite the presence of a memory leak issue.