zoukankan      html  css  js  c++  java
  • 垃圾收集机制

    JavaScript具有自动垃圾收集机制,执行环境会负责管理代码执行过程中使用的内存。而C,C++之类的语言则会麻烦一些,需要手动跟踪内存的使用情况。
    但是在编写JavaScript代码的时候,大部分的时候,就不用再关心内存的问题,因为所需内存的分配以及无用内存的回收完全实现自动管理。
    这种垃圾回收机制的原理:找到不再继续使用的变量,然后释放它们占用的内存。所以,垃圾收集器会按照固定的时间间隔(或代码执行中预定的收集时间),周期性地执行这一操作。

    局部变量的正常生命周期

    局部变量只会在函数执行过程中存在,在这个过程中,会为局部变量再栈或者堆内存上分配相应的空间,以便存储它们的值。然后在函数中使用这些变量,直至函数执行结束。
    这种情况比较好判断变量的存在必要性,但在某些情况下就不容易判断,垃圾收集器必须跟踪哪个变量有用哪个变量没用,对于不再有用的变量打上标记,以备将来收回其占用内存。用于标识无用变量的策略可能会因实现而异,但具体到浏览器中的实现,则通常有两个策略。

    一、标记清除(常用)

    1.标记清除就是给变量做标记。当变量进入环境的时候,就将这个变量标记为“进入环境”。当变量离开环境的时候,将其标记为离开环境。
    可以用任何方式来标记变量,比如:

    • 可以通过翻转某个特殊的位来记录一个变量何时进入环境
    • 使用一个“进入环境的”变量列表
    • 使用一个“离开环境的”变量列表
      ....
      可以使用上述方法来跟踪那个变量发生了变化。有时候标记变量的方式不太重要,重要的是采取什么策略

    2.原理
    垃圾收集器在运行的时候会给存储在内存中的所有变量都加上标记,可以使用任何方式进行标记。然后它会去掉环境中的变量以及被环境中变量引用的变量的标记。在此之后再被加上标记的变量将被作为准备删除的变量。最后垃圾收集器会完成内存清除工作,即销毁那些带标记的值并回收它们所占用的内存空间。

    二、引用计数(不太常见)

    含义:跟踪记录每个值被引用的次数。
    当声明了一个变量并将一个引用类型值赋值给该变量,则这个值的引用次数加1,如果同一个值又被赋值给另一个变量,则该值的引用次数加1.相反,如果包含对这个值引用的变量又取得了另外一个值,则这个值的引用次数减1.当这个值的引用次数减为0的时候,就没有办法再访问它了,当垃圾收集器,下次运行的时候,就会释放那些引用次数为0的值所占用的内存。
    Netscape Navigator 3.0最早使用引用计数策略的浏览器,但遇到了一个严重的问题:循环引用

    • 定义:

    对象A中包含一个指向对象B的指针,对象B中也包含一个指向对象A的引用。

    • 举例
    function problem(){
        var objectA = new Object();
        var objectB = new Object();
    
        objectA.someOtherObject = objectB;
        objectB.anOtherObject = objectA; //objectA和objectB这两个对象的引用次数都为2.
    }
    

    上述如果使用标记清除就没有问题,引用计数就会出现循环引用的问题。
    后来Netscape Navigator 4.0放弃了引用计数清除策略,但是还是存在问题。

    BOM和DOM中的对象问题
    IE中有一部分对象并不是原生JavaScript对象。其BOM和DOM中的对象就是使用C++以COM(组件对象模型)对象的形式实现的,而COM对象的垃圾收集机制采用的就是引用计数策略。
    即使IE的JavaScript引擎是使用标记清除策略来实现的,但是JavaScript访问的COM对象依然是基于引用计数策略的,只要在IE中涉及COM对象,就会存在循环引用的问题。

    var element = document.getElementById("some_element");
    var myObject = new Object();
    myObject.element = element;
    element.someObject = myObject;
    //上面也出现 了循环引用的问题,为了避免这个问题,最好在不使用它们的时候手工断开原生JavaScript对象和DOM元素之间的连接。
    myObject.element = null;
    element.someObject = null;
    //这样就切断变量和它之前引用的值之间的连接。当垃圾收集器下次运行时就会删除这些值并回收它们占用的内存。
    

    但是为了解决这个问题,IE9把BOM和DOM对象都转换成了真正的JavaScript对象,这样避免了两种垃圾收集算法并存导致的问题,也消除了常见的内存泄漏的问题。

    性能问题

    垃圾收集器是周期运行的,确定垃圾收集器的时间间隔是一个非常重要的问题。之前IE的垃圾收集器是根据内存分配量运行的,具体一点:可以是256个变量、4096个对象字面量等等,只要达到上面任何一个临界值,垃圾收集器就会运行。
    存在的问题
    如果一个脚本中包含变量很多,那么脚本在它的生命周期中都一直保存这么多变量。这样的话,垃圾收集器就会不断地运行。结果,由此引发的严重性能问题导致IE7重写了垃圾收集例程。IE7中新的垃圾收集例程:当垃圾收集例程回收的内存分配量低于15%,那么变量、字面量等等的临界值就加倍,如果回收的内存分配量达到了85%,那么临界值重置会默认值。这样简单的设置,极大地提升了IE在运行时包含大量JavaScript的页面时的性能。

    管理内存

    分配给Web浏览器的可用内存数量通常比桌面应用程序的少,因为出于安全的考虑,目的防止运行JavaScript的网页耗尽全部系统内存而导致系统崩溃。优化内存占用的最佳方式,为执行中的代码只保留必要的数据,一旦数据不再有用,则将其值设置为null来释放其应用,即解除引用。这一做法大多适用于大多数全局变量和全局对象的属性。

  • 相关阅读:
    【NOIP2016练习】T3 subset (分块,状压DP)
    【CF173B】Chamber of Secrets(二分图,最短路)
    【CF721C】Journey(拓扑排序,最短路,DP)
    【BZOJ1040】骑士(基环树,树形DP)
    【CF725D】Contest Balloons(贪心,堆)
    【CF675E】Trains and Statistic(贪心,DP,线段树优化)
    【HDOJ2196】Computer(树的直径,树形DP)
    js继承
    原型模式
    创建对象
  • 原文地址:https://www.cnblogs.com/sminocence/p/8411156.html
Copyright © 2011-2022 走看看