一、V8原理
1.垃圾回收机制
JS中的内存管理时自动进行的。如果对象不再被引用或无法从根上访问(通过引用或作用域链),则被认为是垃圾。
GC算法介绍
计数算法
通过设置引用数,判断当前引用是否为0。引用关系改变时修改引用数字。
- 优点:最大限度减少程序暂停;发现垃圾及时回收。减少程序卡顿
- 缺点:无法回收循环引用的对象;时间开销大
标记清除算法
通过设置标记清除垃圾,第一次遍历所有对象标记活动的对象,第二次遍历所有对象清除没有标记的对象,回收相应空间
- 优点:可以回收循环引用的对象
- 缺点:回收以后内存空间碎片多
标记整理算法
第一次遍历所有对象标记活动对象添加标记。第二次整理活动的对象再清除没有标记的对象
V8
主流的JS执行引擎,采用即时编译,设置内存大小。64位操作系统内存不超过1.5G。32 位操作系统不超过800M
V8垃圾回收策略
基础数据是由程序语言自身控制,主要回收存放在堆区里的对象数据。
- V8采用分代回收机制,通过存活时间将内存分成新生代和老生代。存活时间短的对象存放于小空间的新生代。
- 新生代垃圾回收策略
将新生代内存分成两个等大的空间。从From空间遍历标记活动对象再遍历拷贝到To空间之后将From空间清空,置换两个空间的状态。一轮GC还存活的对象移动到老生代。当前To空间中的使用率超过25%时也将活动对象移动到老生代。 - 老生代垃圾回收策略
64位操作系统老生代区空间大小1.4G,32位操作系统老生代空间700M。 标记活动对象,清除垃圾对象。会产生空间,新生代中的对象移动到老生代时如果老生代空间不足会触发标记整理空间优化。采用增量标记进行效率优化。
内存问题的外在表现
- 页面出现经常性暂停或者延迟加载(内存泄露)开发中常见的内存泄露
- 页面持续出现糟糕的性能(内存膨胀)
- 页面的性能随着时间加长越来越差(频繁垃圾回收)
监控内存的方式
- 浏览器任务管理器
使用Shift+ESC调出浏览器任务管理器。第一列内存指的是DOM节点占据的内存,JS内存表示JS堆括号中的大小指的是界面中所有可达对象中正在使用的内存大小。只能检测无法定位问题 - Timeline时序图
Chrome调试工具中 - 堆块照查找分离DOM
分离DOM:界面元素存活在DOM树上,没被引用的DOM是垃圾对象,脱离当前DOM树但在js中有引用称为分离状态的DOM节点。分离的DOM存在内存泄露的现象 - 判断是否频繁垃圾回收
GC工作时应用程序时停止的,频繁且过长的GC会导致应用假死。用户使用时有明显的 卡顿。 通过判断Timeline时序图中频繁的上升下降或者任务管理器中数据频繁增加减小
JS性能优化
- 使用Jsperf比较运行效率
- 避免定义全局变量
- 将全局变量缓存到某一作用域使用
- 通过原型对象新增方法
var fn =function(){}
fn.prototype.foo = function(){
console.log('111')
}
- 避开闭包陷阱
在函数外部引用内部成员,使得内部成员无法被垃圾回收释放,造成内存泄露
<button id="btn">add</button>
<script>
function foo(){
var el = document.getElementById('btn')
el.onclick =function(){
console.log(el.id)
}
el = null
}
foo()
</script>
- 避免属性访问方法使用
JS无需属性的访问方法,所有属性外部可见。使用属性访问方法只会增加一层定义,没有具体的访问控制力 - For循环优化
将for循环的次数提前存储。 如果只遍历数据而无操作时执行效率 forEach >for in > for - 文档碎片优化节点添加
节点的添加比然会有回流和重绘。利用文档碎片的容器将节点集中渲染然后一次性添加到DOM之上。能够减少回流和重绘的次数
const flag = document.createDocumentFragment()
for(var i = 0; i< 10;i++){
var op = document.createElement('p')
op.innerHTML = i
flag.append(op)
}
document.body.appendChild(flag)
- 克隆优化节点操作
可以通过克隆的方式创建节点, 再将子节点添加到该节点上
var oldP = document.getElementById('box1')
for(var i = 0; i<3;i++){
var newP = oldP.cloneNode(false)
newP.innerHTML = i
document.body.appendChild(newP)
}
JSBench工具
JSBench工具链接
|