zoukankan      html  css  js  c++  java
  • 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)?

      先说一下垃圾回收算法:

        新生代回收算法简单的说就是复制:

          新生代内存空间,会标记活着的变量,典型的牺牲空间获取时间的方式
          该内存空间中主要存一些新的变量、存活时间较短的变量,会频繁的进行垃圾回收

        老生代回收算法就是标记删除整理:

          老生代标记死了的变量,需要整理磁盘碎片,新生代不需要整理,效率更高
     
    二、v8是如何处理变量的
    1、如何查看内存使用情况

      通过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,避免一次性读取过大的文件(避免一次性超大内存操作)

  • 相关阅读:
    【InfoPath2007】The form has been closed
    深入浅出Nintex——调用子流程
    深入浅出Nintex——使用查询XML动作
    深入浅出Nintex——使用Call WebService来查询Item ID
    深入浅出Nintex——获得某群组的用户集合
    深入浅出SharePoint2007——Webpart开发
    深入浅出Nintex——获得指定用户的角色
    深入浅出Nintex——使用构建动态字符串动作
    Lucene.net 实现全文搜索
    DotLucene源码浅读笔记(1)补遗:编写简单中文分词器ChineseAnalyzer
  • 原文地址:https://www.cnblogs.com/1220x/p/11705141.html
Copyright © 2011-2022 走看看