turbopasi
turbopasi

Reputation: 3625

Dynamic iframe src change causes memory-leak

I am testing the dynamic change of the src property of an <iframe> inside a Vue template. In the test I am changing the src once a second. Within a couple of minutes my available memory was used by 88 % , eventually the computer froze in the end. I performed this test on a Windows 10 Machine with 32 GB Memory and Firefox Browser.

However, I first noticed memory problems using a similiar approach on a Raspberry Pi 4 (4GB) using chromium-browser. I continuesly switched through multiple vue components (like slides). Some of them have iframes in them as well. Just like in the test from above, the memory leaked (not as fast but within couple of days), and the chromium-browser tab crashed, showing the he's dead jim smiley face.

Here is the code from the test:

<template>
  <div id="app">
    <iframe :src="src" />
    {{ count }}
    {{ src }}
  </div>
</template>

<script>
export default {
  data() {
    return {
      src : "",
      source : [
        "https://example.com/embeddedcontent/1",
        "https://example.com/embeddedcontent/2",
        "https://example.com/embeddedcontent/3",
        "https://example.com/embeddedcontent/4"
      ],
      count : 0,
      interval : null
    }
  },
  mounted() {
    const interval = setInterval(() => {
      this.src = this.source[ this.count % this.source.length ];
      this.count = this.count + 1
    }, 2000);
    this.interval = interval;
  },
  beforeDestroy() {
    clearInterval(this.interval);
  }
}
</script>

Facts

Any ideas for preventing this ?

So far I only thought about refreshing the browser tab every couple of minutes. This would be kindof a hacky solution, since it is not tackling the source of the problem. Are there any alternatives to using iframes when I want to show another websites content inside my Vue App ? Is there are way to just clean up the whole iframe without anything being left behind ?

Update 2021/02/25

I now tried Edge Browser as well, same result (increasing memory overtime). I also tried Firefox Private mode, had only a very low impact (increasing memory but a bit slower). Compared production and development build of the vue example, no difference. I also tried a vanilla electron app with the following code (no vue):

let interval = null;
let sources = [
  "https://hurtigruten.panomax.com/ms-roald-amundsen",
  "https://hurtigruten.panomax.com/ms-fridtjof-nansen",
  "https://rosenalp.panomax.com/",
  "https://alpbach.panomax.com/galtenberg",
];
let index = 0;
let count = 0;

function startTheInterval() {

  interval = setInterval(() => {
    
    index = count % sources.length;
    count = count + 1;
    document.getElementById('monitor').src = sources[index];

  },2000);

}

function clearTheInterval() {
  clearInterval(interval);
}

startTheInterval();

Same result, increasing memory fast .

Upvotes: 5

Views: 2188

Answers (1)

Michal Lev&#253;
Michal Lev&#253;

Reputation: 37853

First, some theory about how iframe works in the browser - Detached window memory leaks

  1. When you trying to debug memory leaks, always use a "incognito mode" - mode when browser is not using any extensions. Extensions may keep references to a HTML loaded into a iframe and keep that data alive. When I was profiling your example in Chrome, just switching to incognito mode resulted into huge decrease of memory allocation and retention...

  2. Do not use Vue CLI/Webpack dev mode to debug memory leaks. Webpack's hot module reloading (HMR) can affect what is kept in memory. Always use production build for that...

  3. Be aware that JS runtimes (V8 in this case) collect some metadata about the code being executed and keep it in the JS heap. What looks like a memory leak may be just JS virtual machine metadata...

UPDATE: I'v run some tests using your example (with 1s interval instead of 2s) on my dev machine (Ryzen 5 3600, 32G of RAM, Win 10 x64) - production build served by serve-handler loaded into Firefox Developer edition v86.0b9 (64-bit) Private window (so no extensions of any kind)

  1. First with Dev Tools open and Memory profiling turned on (with Record call stacks option turned ON). Recorded one snapshot at the beginning and one more after around 40 minutes. Comparing those snapshots didn't show any JS heap allocation increase. Browser's Private Bytes (using Sysinternals Process Explorer) showed around 60MB increase but that memory was cleared the moment i'v closed the Dev Tools so it's safe to say it was memory used by Dev Tools

  2. Same example, now without opening Dev Tools - running for 40 minutes. Again without any memory increase...

So my conclusion is there is no memory leak tied to an iframe or Vue itself. If you really see something as dramatic as "Within a couple of minutes my available memory was used by 88 %" you should check your own system, especially the extensions installed in the browser....

Upvotes: 3

Related Questions