zoukankan      html  css  js  c++  java
  • javascript性能优化

    1.垃圾回收(Garbage collection)

    a.对象创建

    初始化赋值:
    
    var n = 123; // allocates memory for a number
    var s = 'abc'; 
    var a = [1, null, 'aaa']; 
    实例化对象
    
    var d = new Date();

    b.javascript垃圾回收,内存出现泄漏一般都发生在回收阶段.

    低级语言,需要手动管理内存的分配和释放,javascript作为一种高级语言,垃圾回收器,当对象创建时会自动分配内存,当对象不再被使用的时候会自动释放内存。 如果一个对象不再被引用,就会被GC回收。

    http://newhtml.net/v8-garbage-collection/

    Mark-and-sweep 算法:

    此算法中,会有roots,Garbage-collector 会定期的从这些roots开始查找,查找所有被roots引用的对象或者被这些对象引用的对象(对象被roots引用或者被其它对象引用,就表示还在使用),所有不可到达的对象(没有找到),会被GC回收。

    https://developer.mozilla.org/en-US/docs/Web/JavaScript/Memory_Management 

    内存分代: 

    脚本中,绝大多数对象的生存期很短,只有某些对象的生存期较长。为利用这一特点,V8将堆进行了分代。对象起初会被分配在新生区(通常很小,只有1-8 MB,具体根据行为来进行启发)。在新生区的内存分配非常容易:我们只需保有一个指向内存区的指针,不断根据新对象的大小对其进行递增即可。当该指针达到了新生区的末尾,就会有一次清理(小周期),清理掉新生区中不活跃的死对象。对于活跃超过2个小周期的对象,则需将其移动至老生区。老生区在标记-清除或标记-紧缩(大周期)的过程中进行回收。大周期进行的并不频繁。一次大周期通常是在移动足够多的对象至老生区后才会发生。至于足够多到底是多少,则根据老生区自身的大小和程序的动向来定。

    2.如何使用诊断工具发现性能问题

    a.任务管理器

    a.timeline

    释放过之后

    b.Take Heap Snapshot:页面中JavaScript对象和dom节点的内存分配。

      Summary

      Comparison

      Containment

      Statistics

    c.Record Javascript CPU Profile:记录每个函数的执行时间,Self Time,Total Time

    d.Record Allocation Timeline:记录堆上构造函数的内存分配,每个构造函数对应的实例数量,浅层大小,保留大小

    e.Record Allocation Profile:记录每个函数的内存使用大小。

     


    举个例子:

    <!DOCTYPE html>
    <html>
    <head lang="en">
      <meta charset="UTF-8" />
      <meta content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0;" name="viewport" >
      <title>index page</title>
        
    </head>
    <body>
    <input type="button" value="buttoon" id="btn" />
    <script type="text/javascript">
    // var btn=document.getElementById("btn");
    // btn.addEventListener("click",function(){
    
                  var ClassA = function(name){
                            this.name = name;
                            this.func = null;
                    };
    
                    var a = new ClassA("a");
                    var b = new ClassA("b");
    
                    b.func = bind(function(){
                            console.log("I am " + this.name);
                    }, a);
    
                    b.func();        //输出 I am a
                    //a = null;        //释放a
    
                    //b = null;        //释放self
    
                    //模拟上下文绑定
                    function bind(func, self){
                            return function(){
                                    return func.apply(self);
                            };
                    };
    
    
    // },false);
    
    
    </script>
    </body>
    </html>
    View Code

    由于,a和b都没有释放,可以看到classA下面有两个实例。a 实例的引用关系可以在Retainers 窗口中看到。a是通过self这个形参传入的,返回是个函数,又被func引用,func又是b的属性。

    释放a之后的内存:a虽然已经是null,但是a仍然被b引用,所以不会释放。

     正确做法:a和b都是null,才会释放。

    3.常见的性能问题

     a.局部变量意外变成全局变量

     b.闭包,用过没有释放

     c.setTimeout 没有释放

     d.事件绑定之后,不再需要时,没有移除

    学习资料:

    profile使用:

    https://www.2cto.com/kf/201402/281855.html

    https://blog.csdn.net/taoerchun/article/details/51480949

    原理及总体分析:

    http://www.ayqy.net/blog/js%E5%86%85%E5%AD%98%E6%B3%84%E6%BC%8F%E6%8E%92%E6%9F%A5%E6%96%B9%E6%B3%95/

    内存泄漏排查步骤:

    1.timeline 查看实时内存,是否不断上升(手动GC)。如果不断上升,说明可能存在内存泄露。

    2.记录开始对快照,隔段时间的对快照,compare一下,找出内存泄漏的点。

    3.如果明确知道某些操作会导致卡顿或者页面挂掉,可以在操作前后各记录一次对快照,进行对比。找出内存泄漏点。

  • 相关阅读:
    [原创]存储过程,insert,case when then,处理性别问题 Virus
    [原创]c#,数据结构,栈 Virus
    [原创]软件自动化测试和.NET中的反射 Virus
    [原创]反射,.NET,委托 Virus
    《博客园精华集--NET3.x分册》第三轮结果
    (翻译)《Expert .NET 2.0 IL Assembler》 详要目录 更新到第8章
    MSIL翻译中的问题贴
    (翻译)《Expert .NET 2.0 IL Assembler》 第一章 简单示例 1.2 简单示例(二)
    (翻译)《Expert .NET 2.0 IL Assembler》 第一章 简单示例 1.2 简单示例(一)
    第三轮进度汇总
  • 原文地址:https://www.cnblogs.com/bg57/p/6760512.html
Copyright © 2011-2022 走看看