首页 > 其他分享 >[Memory leak] 3. Garbage collection in Closure

[Memory leak] 3. Garbage collection in Closure

时间:2024-11-04 16:09:54浏览次数:3  
标签:Closure function const dom leak collection increase memory doms

Example code:

function createIncrease() {
  const doms = new Array(100000).fill(0).map((_, i) => {
    const dom = document.createElement('div');
    dom.innerHTML = i;
    return dom;
  });

  function increase() {
    doms.forEach((dom) => {
      dom.innerHTML = Number(dom.innerHTML) + 1;
    });
  }

  return increase;
}

const increase = createIncrease();
const btn = document.querySelector('button');
btn.addEventListener('click', increase);

 

What is garbage?

Is domsvariable a garbage in above code?

No. It's not, because code need to use it. 

 

Then how about this code? nums

<script>
  const nums = [1, 2, 3, 4, 5];
  const sum = nums.reduce((total, num) => total + num, 0);

  console.log(sum);
</script>

It's hard to say, due to you can console.log(nums)in console

What I want to point out is that, only developer know what is garbage we want to collect, the program can not tell in all cases.

 

The only thing program can consider it as garbage is the memory you can no longer access.

For example:

<script>
  let nums = [1, 2, 3, 4, 5];
  nums = [4,5,6,7]
  const sum = nums.reduce((total, num) => total + num, 0);

  console.log(sum);
</script>

Then program knows to cleanup [1, 2, 3, 4, 5]in memory, because there is no way to access this piece of data anymore.

 

What is memory leak?

For those piece of data, developer knows we don't need anymore, but still we are able to access those or we have references to it; then those will cause memory leak.

So the way to resolve this problem is make those piece of data unacessable again.

A simple example:

<script>
  let nums = [1, 2, 3, 4, 5];
  const sum = nums.reduce((total, num) => total + num, 0);

  console.log(sum);
  nums = null
</script>

In this end, we set nums = nullto tell GC to collect those memory.

 

Another example:

function createIncrease() {
  const doms = new Array(100000).fill(0).map((_, i) => {
    const dom = document.createElement('div');
    dom.innerHTML = i;
    return dom;
  });

  function increase() {
    doms.forEach((dom) => {
      dom.innerHTML = Number(dom.innerHTML) + 1;
    });
  }

  return increase;
}

const increase = createIncrease();
const btn = document.querySelector('button');
function handleClick() {
    increase()
    btn.removeEventListener('click', handleClick)
    increase = null
}
btn.addEventListener('click', handleClick);

We set increase = null, in this case, program can no longer access domsvariable. Then it should be collected by GC.

 

Memory leak in Closure

function createIncrease() {
  const doms = new Array(100000).fill(0).map((_, i) => {
    const dom = document.createElement('div');
    dom.innerHTML = i;
    return dom;
  });

  function increase() {
    doms.forEach((dom) => {
      dom.innerHTML = Number(dom.innerHTML) + 1;
    });
  }

  return increase;
}

const increase = createIncrease();
const btn = document.querySelector('button');
function handleClick() {
    increase()
    btn.removeEventListener('click', handleClick)
    increase = null
}
btn.addEventListener('click', handleClick);

This clousure example is hard to detect, normally we don't set increase = null. Due to increaseis just a function, how much memory it can takes anyhow?...

But for this function, it holds on a big chunk of data, then cause the memory leak.

 

Momory is not accessable but meanwhile cannot be GC collected?

This is possible, such as Last focused input/textarea element cause memory leak in Chrome

Another example:

function createIncrease() {
  const doms = new Array(100000).fill(0).map((_, i) => {
    const dom = document.createElement('div');
    dom.innerHTML = i;
    return dom;
  });

  function increase() {
  }
    
  function _temp() {
     doms
  }

  return increase;
}

let increase;
const btn = document.querySelector('button');
function handleClick() {
    increase = createIncrease()
}
btn.addEventListener('click', handleClick);

Now, increaseshas not access to doms, but a new function _tempwhich won't be called anyhow, but it holds on the reference to doms.

If we check the memory profile, we should see that the domswon't be GC collected.

 

Why?

Inside closure, if there is only one function increasewhich access doms, program will optimize syntactic environment to move away doms. In this case, it won't cause memory leak.

Inside closure, increase & _tempthey share the same syntactic environment, in this case, GC won't optimize the domsvariables, and also won't be able to garbage collect it and will cause memory leak.

当多个函数共享词法环境时,会导致词法环境膨胀,从而导致出现无法触达也无法回收的内存空间

 

标签:Closure,function,const,dom,leak,collection,increase,memory,doms
From: https://www.cnblogs.com/Answer1215/p/18525526

相关文章

  • [Memory Leak] 1. console.log cause memory leak
    Examplecode:<template><button@click="handleClick">Hello,Vue-CLI</button></template><script>exportdefault{methods:{handleClick(){constarr=newArray(100000).fill(0);console.log(......
  • Java & Collection/Executor & SynchronousQueue & 总结
    前言 相关系列《Java&Collection&目录》《Java&Executor&目录》《Java&Collection/Executor&SynchronousQueue&源码》《Java&Collection/Executor&SynchronousQueue&总结》《Java&Collection/Executor&SynchronousQueue......
  • C# serialize big collection via NewtonSoft.Json
    System.OutOfMemoryExceptionHResult=0x8007000EMessage=Exceptionoftype'System.OutOfMemoryException'wasthrown.Source=mscorlibStackTrace:atSystem.Text.StringBuilder.ToString()atSystem.IO.StringWriter.ToString()atNewto......
  • ObservableCollection<T>获取索引
    如果是普通类型我们直接可以用indexOf()获取,比如:ObservableCollection<string>oc=newObservableCollection<string>();oc.Add("Item1");oc.Add("Item2");oc.Add("Item3");stringitem="Item2";intindex=oc.IndexOf(ite......
  • 【项目实战】Java中集合Collection 和 Collections入门介绍
    在Java编程语言中,Collection是一个接口,它是集合层次结构中的根接口。Collection接口定义了所有集合类型(如列表、集合和队列)所共有的基本操作方法。而Collections则是一个工具类,它提供了一系列静态方法来操作或返回集合。当你需要存储一组对象并在程序中对其进行操作时,......
  • <collection> 和 <association>的详细用法(附详细代码解析)
    MyBatis中的<association>和<collection>标签在MyBatis中,<association>和<collection>标签用于配置复杂查询的结果集关联映射,主要用于处理实体类之间的嵌套关系。二者的区别在于:<association>标签用于一对一的关系映射,比如实体类A中包含一个实体类B的对象......
  • KMemLeak部署、使用与原理分析
    文章目录前言1、概述2、使用方法3、测试用例4、工作原理4.1、原理介绍4.2、实现细节5、参考文献总结前言  本博客的主要内容为KMemLeak的部署、使用与原理分析。本博文内容较长,因为涵盖了KMemLeak的几乎全部内容,从部署的详细过程到如何使用KMemLeak对Linux内核......
  • A 2-D LiDAR-SLAM Algorithm for Indoor Similar Environment With Deep Visual Loop
      具有深度视觉闭环的室内类似环境的二维LiDAR-SLAM算法A2-DLiDAR-SLAMAlgorithmforIndoorSimilarEnvironmentWithDeepVisualLoopClosure摘要:同步定位与建图(SLAM)是实现机器人智能的关键技术。与摄像头相比,在室内环境下使用光探测和测距(LiDAR)可以实现更高......
  • wpf 数据绑定 列表 ObservableCollection
    #wpf数据绑定列表ObservableCollectionPrismDryIocDemo\PrismDryIocDemo\App.xaml<Applicationx:Class="PrismDryIocDemo.App"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http......