v8的內存管理算法---如何管理內存

爲何要關注內存: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)?

  先說一下垃圾回收算法:

    新生代回收算法簡單的說就是複製:

      新生代內存空間,會標記活着的變量,典型的犧牲空間獲取時間的方式
      該內存空間中主要存一些新的變量、存活時間較短的變量,會頻繁的進行垃圾回收

    老生代回收算法就是標記刪除整理:

      老生代標記死了的變量,須要整理磁盤碎片,新生代不須要整理,效率更高
 
2、v8是如何處理變量的
一、如何查看內存使用狀況

  經過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,避免一次性讀取過大的文件(避免一次性超大內存操做)

相關文章
相關標籤/搜索