- 内存主要就是储存变量等数据的
- 局部变量当程序执行结束,且没有引用的时候就会随着消失(但是!!局部变量在方法调用完之后,可以被回收,但不是用完就立刻回收)
- JS什么时候回收内存?a.内存不够的时候 b.定时回收
- 全局对象会始终存活到程序运行结束。
运行如下的例子,你会明白一些V8的内存回收机制
// 获取内存的使用情况,并打印
function getMemory(){
var mem = process.memoryUsage();
var format = function(bytes){
return (bytes/1024/1024).toFixed(2) + 'MB';
}
//heapTotal 和 heapUsed 代表 V8 的内存使用情况
console.log('heapTotal: ',format(mem.heapTotal)+' heapUsed: ',format(mem.heapUsed));
}
// 模拟创建大内存数据并执行
var num = 1024*1024*20;
function init(){
var arr1 = new Array(num);
var arr2 = new Array(num);
var arr3 = new Array(num);
var arr4 = new Array(num);
var arr5 = new Array(num);
}
init();
for(let i=0;i<13;i++){
//多次重复创建大内存数据,打印内存消耗情况
let arr = new Array(num)
getMemory()
}
node环境打印出来结果:
heapTotal: 834.57MB heapUsed: 801.55MB
heapTotal: 994.57MB heapUsed: 961.88MB
heapTotal: 1154.57MB heapUsed: 1121.84MB
heapTotal: 1314.58MB heapUsed: 1281.87MB
heapTotal: 1474.58MB heapUsed: 1441.84MB
heapTotal: 1634.59MB heapUsed: 1601.87MB
heapTotal: 1794.59MB heapUsed: 1761.84MB
heapTotal: 1954.59MB heapUsed: 1921.87MB //注意这里,即将达到2G内存消耗
heapTotal: 834.57MB heapUsed: 801.75MB //这里之前回收了一次内存
heapTotal: 994.57MB heapUsed: 961.78MB
heapTotal: 1154.57MB heapUsed: 1121.75MB
heapTotal: 1314.58MB heapUsed: 1281.78MB
heapTotal: 1474.58MB heapUsed: 1441.75MB
你会发现,当heapTotal接近2G时,V8引擎回收了一次内存(即init函数中的局部变量),所以可以得出结论:局部变量在方法调用完之后,可以被回收,但不是用完就立刻回收,当内存不够的时候,会回收掉无用的变量。
内存优化技巧:
- 尽量不要定义全局变量
- 全局变量记得销毁掉(不用的时候设置为undefined)
- 用匿名自执行函数变全局为局部
- 尽量避免闭包——但这个结论是错的,因为不是闭包就一定会造成内存溢出!!!
- 尽量避免闭包引用——如果变量引用了闭包返回的值,就要注意内存的溢出 ↓
function getData(){
let size = 20*1024*1024;
var arr = new Array(size);
return arr;
}
var a = getData();
var b = getData();
var c = getData();
var d = getData();
var e = getData();
- 不要滥用V8的缓存(全局变量,不是浏览器缓存),如果有大缓存,可以加锁缓存(先进先出,老的缓存释放掉,再进入新缓存)
- 注意大内存量操作(用流的方式读取,分片处理)
闭包:不是一种固定写法,而是一种思想:变量只允许在内部,只可以以我指定的方式让外部访问,并不是完全暴露给外部,这就是闭包的形式。