Cht-core: Memory leak when switching between tabs

Created on 28 Nov 2018  路  11Comments  路  Source: medic/cht-core

This is a script which switches between the messages and contacts tab every 5 seconds.

setInterval(() => $('#messages-tab').click(), 5000);
setTimeout(() => setInterval(() => $('#contacts-tab').click(), 5000), 2000);

I did the following:

  1. Load WebApp
  2. Navigate to all tabs to ensure view warming.
  3. Trigger GC
  4. Measure Heap size and DOM Node Count.
  5. Start the script
  6. Wait some duration
  7. Trigger GC
  8. Measure Heap size and DOM Node Count.

Results after waiting 10 minutes:

Metric | Before | After
-- | -- | --
Heap | 163MB | 195 MB
DOM Nodes | 17,000 | 410,000

A second run for 5 minute without live-list drawing in contacts tab:

Metric | Before | After
-- | -- | --
Heap | 126MB | 327MB
DOM Nodes | 17,000 | 200,000

Measures imply some sort of resource leak. This was on Chrome 70, so could be bogus. Worth investigating further.

1 - High Performance

Most helpful comment

To AT, follow these steps:

  1. Login as a restricted user with a healthy number of docs (they need to have data in all tabs for the test to be valid!) in some incognito browser - this is important as any extensions you may have would possibly interfere with the results
  2. Visit all tabs and let them load completely
  3. Go to Messages tab
  4. Open DevTools and go to Performance tab, _force garbage collection_ and then open Performance monitor (Settings -> More tools -> Performance monitor)
  5. In performance monitor, make sure it registers JS heap size, DOM nodes and JS event listeners. These are the metrics we will follow.
  6. Switch to console and run this script, __closing DevTools__ after it starts:
(() => {
  let i = 0;
  const mInterval = setInterval(() => {
    if (i % 5 === 0) $('#messages-tab').click();
    if (i % 5 === 1) $('#tasks-tab').click();
    if (i % 5 === 2) $('#reports-tab').click();
    if (i % 5 === 3) $('#contacts-tab').click();
    if (i % 5 === 4) $('#analytics-tab').click();
    if (++i > 100) {
      clearInterval(mInterval);
    }
  }, 2500);
})();

(2500ms was enough of a timeout to load any tab completely on my PC, but you can increase this interval if it's too low).

  1. Let the script finish. You should be back to the messages tab now. Repeat from step 4, recording the 3 metrics after every iteration. Repeat as many times as you like, maybe at least 4 times.

  2. Compare metrics across iterations. Slight variations are normal. It's very important to force garbage collection before recording.
    There is also more information/discussions on the PR: https://github.com/medic/medic-webapp/pull/5073#issuecomment-445877319

All 11 comments

@kennsippell were the chrome dev tools open or closed when you did these tests?

@SCdF Open. I haven't attempted to measure precisely, but still appears to be a leak (slower) when closed. You have good reading on the impact of DevTools on this?

@kennsippell definitely not a good reading, but I have noticed that leaving dev tools open overnight in our app (so not changing tabs, just completely idle, and against an idle local DB) can often cause huge amounts of ram usage for the tab and often a lot of cpu usage.

However, I have not put effort into replicating or isolating this-- sometimes I just wake up after working on webapp the day before and my laptop fan goes nuts. I have just always presumed that dev tools === slow + dodginess. That could be a bad presumption though...

I may have a fix for this, or at least a partial one.
I found some leaks that are easily avoidable.

@kennsippell I've pushed some changes to a branch, as an attempt to fix some of these memory leaks.
I've touched Messages, Contacts and Reports.

If you find the time, could you please checkout and re-run the tests with these changes? Thanks in advance!

@dianabarsan Added most recent measures into the PR.
The actual leak is not as severe as reported above. My chrome extensions were interfering.

To AT, follow these steps:

  1. Login as a restricted user with a healthy number of docs (they need to have data in all tabs for the test to be valid!) in some incognito browser - this is important as any extensions you may have would possibly interfere with the results
  2. Visit all tabs and let them load completely
  3. Go to Messages tab
  4. Open DevTools and go to Performance tab, _force garbage collection_ and then open Performance monitor (Settings -> More tools -> Performance monitor)
  5. In performance monitor, make sure it registers JS heap size, DOM nodes and JS event listeners. These are the metrics we will follow.
  6. Switch to console and run this script, __closing DevTools__ after it starts:
(() => {
  let i = 0;
  const mInterval = setInterval(() => {
    if (i % 5 === 0) $('#messages-tab').click();
    if (i % 5 === 1) $('#tasks-tab').click();
    if (i % 5 === 2) $('#reports-tab').click();
    if (i % 5 === 3) $('#contacts-tab').click();
    if (i % 5 === 4) $('#analytics-tab').click();
    if (++i > 100) {
      clearInterval(mInterval);
    }
  }, 2500);
})();

(2500ms was enough of a timeout to load any tab completely on my PC, but you can increase this interval if it's too low).

  1. Let the script finish. You should be back to the messages tab now. Repeat from step 4, recording the 3 metrics after every iteration. Repeat as many times as you like, maybe at least 4 times.

  2. Compare metrics across iterations. Slight variations are normal. It's very important to force garbage collection before recording.
    There is also more information/discussions on the PR: https://github.com/medic/medic-webapp/pull/5073#issuecomment-445877319

There seems to be a linear increase the heap size each run (even after running the garbage collector).... but not a big difference.

image

Run 1
image

Run 2
image

Run 3
image

Run 4
image

Run 5
image

Run 6
image

@ngaruko
Are you sure you are following the steps exactly, including running the tests with a closed dev tools in an incognito browser?
I ran them again, myself, on gamma.dev with a restricted user and these are my results:

mem-no-leak

A total of 6 runs, for the last 2 I included the performance status before clicking on the garbage collect button too.

Can you please tell me how and where you are testing this, so I can try to replicate?

Running the test 4 times on gamma.dev, logged in as the user indicated by @ngaruko

mem-no-leak

LGTM
Thanks @dianabarsan
image

Was this page helpful?
0 / 5 - 0 ratings