v8的内存管理算法---如何管理内存
为什么要关注内存:
1、防止页面占用内存过大,引起客户端卡顿,甚至无响应
2、Node使用的也是V8,内存对于后端服务的性能至关重要。因为服务的持久性,够短更容易造成内存溢出。
3、面试装逼神器(哈哈哈)
v8引擎内存回收机制
一、v8引擎内存分配
分为:新生代内存空间,老生代内存空间
内存大小:
和操作系统有关,64位为1.4G,32位为0.7G;64位下新生代的空间为64M,老生代为1400M;32位下新生代为16M,老生代为700M。
为什么是1.4G呢?
1、js最初设计是在浏览器上跑的,浏览器上的js不持久,1.4G安全够用,
2、js回收垃圾的时候,会暂停所有代码的执行,如果内存过大,回收时占用的时间会更多,300mb 回收 0.5秒
为什么新生代内存空间划分成两块呢(一个from,一个to)?
先说一下垃圾回收算法:
新生代回收算法简单的说就是复制:
老生代回收算法就是标记删除整理:
通过node来查看内存使用情况:process.memoryUsage();
{
rss: 22347776, //v8申请到的总占用空间
heapTotal: 9682944, //堆总内存
heapUsed: 5401712, //已经使用了的内存
external: 16901 // node底层是C++,他可以申请到一些C++的内存
}
通过浏览器来查看内存:
F12调试工具查看;performance
控制台输入:window.performance // 可以查看到当前页面的各种内存情况
function getmem(){ var mem = process.memoryUsage(); var format = function(bytes) { return (bytes/1024/1024).toFixed(2) + 'MB'; }; console.log('Process: heapTotal ' + format(mem.heapTotal) + ' heapUsed ' + format(mem.heapUsed) + ' rss ' + format(mem.rss)); };
2、内存处理
内存主要就是存储变量等数据结构的
局部变量当程序执行结束,并且引用的时候就会随着消失
全局对象会始终存货到程序运行结束
// 局部变量没有引用之后会被销毁 // 没有返回值,函数调用完了变量就会被销毁了 var size = 20*1024*1024; function a(){ var arr1 = new Array(size); var arr2 = new Array(size); var arr3 = new Array(size); var arr4 = new Array(size); var arr5 = new Array(size); var arr6 = new Array(size); var arr7 = new Array(size); var arr8 = new Array(size); // var arr9 = new Array(size); // return [arr1,arr2,arr3,arr4,arr5,arr6,arr7,arr8]; } a(); getmem(); // Process: heapTotal 1288.83MB heapUsed 1283.34MB rss 1299.79MB var arr9 = new Array(size); // 有返回值的函数 var size = 20*1024*1024; function a(){ var arr1 = new Array(size); var arr2 = new Array(size); var arr3 = new Array(size); var arr4 = new Array(size); var arr5 = new Array(size); var arr6 = new Array(size); var arr7 = new Array(size); var arr8 = new Array(size); // var arr9 = new Array(size); return [arr1,arr2,arr3,arr4,arr5,arr6,arr7,arr8]; } a(); getmem(); // Process: heapTotal 1288.83MB heapUsed 1283.34MB rss 1299.76MB var arr9 = new Array(size); // 函数只是return 了一个值,最后的执行结果与第一种情况没很大的差别 // 当将返回值赋值给一个变量后,变量保留了这一系列数组的引用,最后崩了 // var c = a();
三、如何注意内存的使用
1、优化内存的技巧:
尽量不要定义全局变量
全局变量要记得销毁掉
用匿名自执行函数变全局为局部
尽量避免闭包 --- 错误的????(闭包不会影响内存了)
// 全是全局变量
// 全局变量记得要销毁:delete arr (不推荐使用,在严格模式下回出现很多问题);
// arr1 =undefined; arr1 = null;
var size = 20*1024*1024; var arr1 = new Array(size); var arr2 = new Array(size); var arr3 = new Array(size); var arr4 = new Array(size); var arr5 = new Array(size); var arr6 = new Array(size); var arr7 = new Array(size); var arr8 = new Array(size);
arr1 = null; // 定义9之前吧1释放掉,也不会报错了
var arr9 = new Array(size);
getmem(); // 运行结果:Process: heapTotal 1288.83MB heapUsed 1283.34MB rss 1299.75MB // 当有9个时,会报内存泄漏错误
var size = 20*1024*1024; // 用匿名自执行函数包裹起来,让整个代码编程局部的 // (function(){ // })(); (function(){var arr1 = new Array(size)})();
// 闭包??? for(var i=10000;i<10100;i++){ setTimeout(function(){ console.log(i); getmem(); }) } // 运行结果: // 10100 // Process: heapTotal 6.73MB heapUsed 4.12MB rss 19.32MB // 10100 // Process: heapTotal 9.73MB heapUsed 3.94MB rss 19.70MB // 10100 for(var i=10000;i<10100;i++){ (function(i){ setTimeout(function(){ console.log(i); getmem(); }) })(i) } // 运行结果: // 10000 // Process: heapTotal 9.73MB heapUsed 3.94MB rss 19.72MB // 10001 // Process: heapTotal 9.73MB heapUsed 3.95MB rss 19.75MB // 10002 // Process: heapTotal 9.73MB heapUsed 3.95MB rss 19.75MB // 两种方式的结果相差无几 // v8引擎,闭包基本不会影响内存了
2、防止内存泄漏
滥用内存
// node 服务是持久化的, var http = require('http'); global.a = []; var size = 20*1024*1024; // 创建一个服务 http.createServer((req,res) => { function getmem(){ var mem = process.memoryUsage(); var format = function(bytes) { return (bytes/1024/1024).toFixed(2) + 'MB'; }; console.log('Process: heapTotal ' + format(mem.heapTotal) + ' heapUsed ' + format(mem.heapUsed) + ' rss ' + format(mem.rss)); }; // 每一次请求服务都会往a里面push一个数组, a.push(new Array(size)); getmem(); res.end('hello world'); }).listen(3000); // 每刷新一次,内存占用情况就会变化一次 // 运行结果: Process: heapTotal 169.75MB heapUsed 164.44MB rss 180.45MB Process: heapTotal 329.76MB heapUsed 324.59MB rss 340.71MB Process: heapTotal 490.27MB heapUsed 484.00MB rss 500.91MB Process: heapTotal 650.28MB heapUsed 644.06MB rss 661.03MB Process: heapTotal 810.29MB heapUsed 804.00MB rss 821.28MB Process: heapTotal 970.30MB heapUsed 964.01MB rss 981.30MB Process: heapTotal 1130.32MB heapUsed 1124.03MB rss 921.40MB Process: heapTotal 1290.33MB heapUsed 1284.02MB rss 1287.71MB 再来一次就宕机了 // 所以后端特别关注内存 // 每一次请求服务都会往a里面push一个数组, // 为了保证内存不泄露,在push之前,可以加一道锁,判断,当a的长度大于4时,就将第一个元素移除 if(a.length > 4){ a.shift(); }
大内存量操作
分片、断点
<input type='file' />
readfile() ,createReadStream,避免一次性读取过大的文件(避免一次性超大内存操作)