爲何要關注內存:javascript
一、防止頁面佔用內存過大,引發客戶端卡頓,甚至無響應java
二、Node使用的也是V8,內存對於後端服務的性能相當重要。由於服務的持久性,夠短更容易形成內存溢出。node
三、面試裝逼神器(哈哈哈)面試
v8引擎內存回收機制算法
1、v8引擎內存分配編程
分爲:新生代內存空間,老生代內存空間後端
內存大小:數組
和操做系統有關,64位爲1.4G,32位爲0.7G;64位下新生代的空間爲64M,老生代爲1400M;32位下新生代爲16M,老生代爲700M。瀏覽器
爲何是1.4G呢?安全
一、js最初設計是在瀏覽器上跑的,瀏覽器上的js不持久,1.4G安全夠用,
二、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)); };
二、內存處理
內存主要就是存儲變量等數據結構的
局部變量當程序執行結束,而且引用的時候就會隨着消失
全局對象會始終存貨到程序運行結束
// 局部變量沒有引用以後會被銷燬 // 沒有返回值,函數調用完了變量就會被銷燬了 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();
3、如何注意內存的使用
一、優化內存的技巧:
儘可能不要定義全局變量
全局變量要記得銷燬掉
用匿名自執行函數變全局爲局部
儘可能避免閉包 --- 錯誤的????(閉包不會影響內存了)
// 全是全局變量
// 全局變量記得要銷燬: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引擎,閉包基本不會影響內存了
二、防止內存泄漏
濫用內存
// 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,避免一次性讀取過大的文件(避免一次性超大內存操做)