javascript垃圾回收
来源:互联网 发布:java将文字转换成语音 编辑:程序博客网 时间:2024/06/06 09:31
javascript具有自动的垃圾收集机制,可以使开发人员不用再去关心内存使用的问题。
一、标记清除
Javascript中最常用的垃圾收集方式是标记清除(mark-and-sweep)。当变量进入环境(例如,在环境中声明一个变量)时,就将这个变量标记为“进入环境”。从逻辑上讲,永远不能释放进入环境的变量所占用的内存,因为只要执行流进去相应的环境,就可能会用到它们。而当变量离开环境时,则将其标记为“离开环境”。
可以使用任何方式来标记变量。比如,可以通过翻转某个特殊的位来记录一个变量何时进入环境,或者使用一个“进入环境的”变量列表及一个“离开环境的”变量列表来跟踪哪个变量发生了变化。说到底,如何标记变量其实并不重要,关键在于采取什么样的策略。
垃圾收集器在运行的时候会给存储在内存中的所有变量都加上标记(当然,可以使用任何标记方式)。然后,它会去掉环境中的变量以及被环境中的变量引用的变量标记。而在此之后再被加上标记的变量将被视为准备删除的变量,原因是环境中的变量已经无法访问到这些变量了。最后,垃圾收集器完成内存清除工作,销毁那些带标记的值并收回它们所占用的空间。
二、引用计数
另一种不太常见的垃圾收集策略叫做引用计数(reference counting)。引用计数的含义是跟踪记录每一个值被引用的次数。当声明了一个变量并将一个引用类型值赋给另一个变量时,这个值的引用次数就是1。如果同一个值又被赋给另一个变量,则该值得引用次数加1。相反,如果包含对这个值引用的变量又取得了另外一个值,则这个值得引用次数减1。当这个值得引用次数变为0时,说明没有办法再访问这个值了,因而就可以将其战友的内存空间回收回来。这样,当垃圾收集器下次再运行时,它就会释放那些引用次数为0的值所占用的内存。
但是,引用计数有一个很大的问题,其无法解决循环引用。
function problem(){
var objectA = new Object();
var objectB = new Object();
objectA.someOtherObject = objectB;
objectB.anotherObject = objectA;
}
在以上代码中,objectA和objectB通过各自的属性相互引用;也就是说,这两个对象的引用次数都是2,即永远不会为0,它们会在内存中永远存在。加入这个函数被反复调用,就会导致大量内存得不到回收。
三、分代回收
V8引擎中是通过分代回收(generational collection)来实现内存控制的。JavaScript对象是通多堆来进行分配的,在64位操作系统中,堆的大小为1.4G上下,在32位的操作系统中,其大小为0.7G左右。在node也可以通过命令重新设置堆的内存大小。分代回收的核心在于把内存分为新生代与老生代。新生代中的对象为存活时间较短的对象,老生代的对象为存活时间较长或常驻内存的对象。如下图所示。
新生代内存通过Scavenge算法进行垃圾回收,其具体实现是采用Cheney算法。即将新生代内存分为等分的两块,称为semispace(from)和semispace(to)。
在这两个semispace空间中,只有一个空间处在使用状态,另一个处于闲置状态。处在使用状态的空间称为semispace(from)。当为对象分配内存空间时,先是在from空间进行分配。
当进行垃圾回收时,会检查form空间中的存活对象,这些存活对象会被复制到to空间中,而非存活对象的空间将会被释放。完成复制后,from空间与to空间的角色发生调换。其缺点是只用到新生代空间中一半的内存。但是因为新生代中都是些生命周期比较短的对象,恰恰非常适用于这个算法。
当一个对象经过多次复制已然存活时,它将会被认为是生命周期较长的对象。这种较长生命周期的对象随后会被移动到老生代中,采用新的算法进行管理。对象从新生代中移动到老生代中的过程焦作晋升。
晋升有两种情况,如下图。
设置25%这个限制值的原因是当这次Scavenge回收完成后,这个to空间将变成from空间,接下来的内存分配将在这个空间内完成。如果占用比过高,会影响后续的内存分配。
在老生代内存空间中,使用Mark-Sweep&Mark-Compact进行垃圾收集。mark-sweep只清理死亡对象(区别于Scavenge的复制存活对象),但它清理死亡对象,释放其内存空间之后会存在内存空间不连续的情况,这些内存碎片会对后续的内存分配造成问题,如不能分配一个大的对象,这个时候就要提前触发垃圾回收,而这个时候的垃圾回收明显是不必要的。
是故,mark-compact被提了出来,他在清理完死亡对象的时候,将内存进行重新整理,死亡对象的内存往老生代内存空间的一端移动,那么剩下的内存就都将会是连续的,这个时候分配一个大的对象是没有问题的(除非内存已不够)。
- Javascript垃圾回收机制
- JavaScript 垃圾回收
- JavaScript 垃圾回收
- JavaScript垃圾回收机制
- javascript垃圾回收
- JavaScript 垃圾回收
- JavaScript的垃圾回收
- JavaScript垃圾回收机制
- JavaScript中的垃圾回收
- javascript垃圾回收机制
- JavaScript 垃圾回收
- JavaScript 中的垃圾回收
- JavaScript垃圾回收机制
- javascript垃圾回收机制
- Javascript 垃圾回收浅析
- JavaScript垃圾回收机制
- JavaScript 垃圾回收
- JavaScript 垃圾回收
- ORL Face Database 人脸识别数据集
- Android同步类:Mutex和Condition的使用方式
- Servlet的运行过程
- CentOS6网卡静态IP设置
- 2016.5.21初中部模拟赛总结
- javascript垃圾回收
- 提高自行车踏频的训练技巧
- 代理模式
- IDA 调试android 遇到的问题及解决方案
- Ubuntu 下安装 JDK 并配置 Java 编译环境
- oracle查询一个表有几个字段
- Apache HAWQ集群的安装部署
- 室内环境监测系统的设计(一)
- 强制 Google.com 域名使用 HTTPS(SSL)