Running tests with mocha results in memory leak and large string structures

1.4k views Asked by At

I am trying to set up an environment for detecting memory leaks in my application.

App setup: Angular + Electron
Simulating app use with: Mocha + Spectron + Webdriverio

I have tests for different user scenarios that I run on freshly setup app and periodically collect memory usage of each process.

When the app is in idle, memory usage is as expected. But I have run into a problem with other test cases. It seems that when running tests with mocha, I get unexpected and unknown structures in memory. That results in a memory leak.


I have attached a screenshot below (Memory tab on dev tools), that best describes my confusion.

  • Snapshot 1: Taken after the app is set up (81.8 MB)
  • Snapshot 2: Taken after a group of tests have completed (~ 10 minutes of normal use) and the app has returned to starting state (109 MB)
  • Snapshot 3: Taken after I have forced GC (via "Collect Garbage" button) (108 MB)

Comparing snapshot 1 and 2, I can see where most of the memory is (~19 MB): in strings.

Inspection of retainers tells me that those strings are linked to (Global handlers)>(GC roots), selecting one of the strings and executing $0 in console results in the same output for all strings: <body>...</body>. When I hover the element, it is linked to a body of my app (for every string).

"Expanding string structure" gives me a feeling, that this is caused by some module being loaded multiple times and its references never being destroyed (my guess is that is is loaded via Module() in internal/modules/cjs/loader.js:136)?

Expanding string structure

When examining memory with "Allocation timelines", I don't find this "large string objects" under unreleased memory for same action that results in new "large string object" under "heap snapshot > comparison"

When I simulate a test scenario by hand or I simulate clicks via function in console, there is no memory leak.

All of that makes me think, I am doing or using something wrong (regarding mocha).


My questions:

  1. Is mocha not suitable for this kind of setup (i.e. it holds some references until the app is closed)?
  2. If a structure is retained only by (Global handlers)>(GC roots), when will it be released? I read here, that they are not something you need to worry about but in my case, they are :/
  3. How are there multiple strings (multiple references?) that, when called via $0, all reference same DOM element (<body>)?
  4. How come this string objects are not visible in "Allocation timelines"?
  5. What can be the cause of this type of memory leak?
1

There are 1 answers

2
Xotabu4 On
  1. No, i don't think it is mocha related thing.

Trick is that mocha runs at nodejs side, and controls browser thru chromiumdriver using webdriver protocol (HTTP):

enter image description here

What i can see from strings in your snapshot it is actually some code that is send from chromedriver into your app.

I believe this is some issue of chromedriver.

  1. This might be some injections into page when chromedriver tries to execute some commands.

You can try to cleanup cookies, local and session storage between tests, or hard reload with https://webdriver.io/docs/api/browser/reloadSession.html - but reload is pretty slow thing...

Or reload just current context with https://webdriver.io/docs/api/webdriver.html#refresh

Also you can try to manually execute some clenup js code on app side with https://webdriver.io/docs/api/browser/execute.html