• 前端性能监控


    前端设计


    白屏时间(first Paint Time)——用户从打开页面开始到页面开始有东西呈现为止

    如何获取:

    1、chrome 高版本:

    window.chrome.loadTimes().firstPaintTime loadTimes获取的结果。

    2、其他版本的浏览器

    头部资源加载时间结束时间-首字节时间开始时间

    var firstPaintTime = end_time - performance.timing.navigationStart
    performance.timing.navigationStart首字节时间开始时间是由浏览器提供的函数
    end_time需要我们计算
    <!DOCTYPE HTML>
    <html>
        <head>
            <meta charset="UTF-8"/>
        <script>
          var start_time = +new Date; //测试时间起点,实际统计起点为 DNS 查询
        </script>
        <!-- 3s 后这个 js 才会返回 -->
        <script src="script.php"></script>  
        <script>
          var end_time = +new Date; //时间终点
          var headtime = end_time - start_time; //头部资源加载时间    
          console.log(headtime);
        </script>
        </head> 
        <body>     
        <p>在头部资源加载完之前页面将是白屏</p>
        <p>script.php 被模拟设置 3s 后返回,head 底部内嵌 JS 等待前面 js 返回后才执行</p>
        <p>script.php 替换成一个执行长时间循环的 js 效果也一样</p>  
        </body>
    </html>

    首屏时间——用户浏览器首屏内所有内容都呈现出来所花费的时间

    首屏时间的统计比较复杂,因为涉及图片等多种元素及异步渲染等方式。观察加载视图可发现,影响首屏的主要因素的图片的加载。通过统计首屏内图片的加载时间便可以获取首屏渲染完成的时间。统计流程如下:

      首屏位置调用 API 开始统计 -> 绑定首屏内所有图片的 load 事件 -> 页面加载完后判断图片是否在首屏内,找出加载最慢的一张 -> 首屏时间

      这是同步加载情况下的简单统计逻辑,另外需要注意的几点:

    • 页面存在 iframe 的情况下也需要判断加载时间
    • gif 图片在 IE 上可能重复触发 load 事件需排除
    • 异步渲染的情况下应在异步获取数据插入之后再计算首屏
    • css 重要背景图片可以通过 JS 请求图片 url 来统计(浏览器不会重复加载)
    • 没有图片则以统计 JS 执行时间为首屏,即认为文字出现时间
     
    //IE gif重复onload解决
    var img=new Image(); 
    img.load=function(){ 
    //do something 
    img.load=null;//重新赋值为null 
    } 
    img.src='××.gif';

       

      统计方法1:

      原理:在首屏渲染之前埋上处理逻辑,使用定时器不断的去检测img节点的图片。判断图片是否在首屏和加载完成,找到首屏中加载时间最慢的的图片完成的时间,从而计算出首屏时间。如果首屏有没有图片,如果没图片就用domready时间。

      缺点: 1.浏览器定时器最大精度为55ms 2.背景图片加载没有计算在内 3.不断检测并执行的脚本耗时

    /1,获取首屏基线高度
    //2,计算出基线dom元素之上的所有图片元素
    //3,所有图片onload之后为首屏显示时间
      function getOffsetTop(ele) {
        var offsetTop = ele.offsetTop;
        if (ele.offsetParent !== null) {
          offsetTop += getOffsetTop(ele.offsetParent);
        }
        return offsetTop;
      }
      var firstScreenHeight = win.screen.height;
      var firstScreenImgs = [];
      var isFindLastImg = false;
      var allImgLoaded = false;
      var t = setInterval(function() {
        var i, img;
        if (isFindLastImg) {
          if (firstScreenImgs.length) {
            for (i = 0; i < firstScreenImgs.length; i++) {
              img = firstScreenImgs[i];
              if (!img.complete) {
                allImgLoaded = false;
                break;
              } else {
                allImgLoaded = true;
              }
            }
          } else {
            allImgLoaded = true;
          }
          if (allImgLoaded) {
            collect.add({
              firstScreenLoaded: startTime - Date.now()
            });
            clearInterval(t);
          }
        } else {
          var imgs = body.querySelector('img');
          for (i = 0; i < imgs.length; i++) {
            img = imgs[i];
            var imgOffsetTop = getOffsetTop(img);
            if (imgOffsetTop > firstScreenHeight) {
              isFindLastImg = true;
              break;
            } else if (imgOffsetTop <= firstScreenHeight 
               && !img.hasPushed) {
              img.hasPushed = 1;
              firstScreenImgs.push(img);
            }
          }
        }
      }, 0);
    
      doc.addEventListener('DOMContentLoaded', function() {
        var imgs = body.querySelector('img');
        if (!imgs.length) {
          isFindLastImg = true;
        }
      });
    
      win.addEventListener('load', function() {
        allImgLoaded = true;
        isFindLastImg = true;
        if (t) {
          clearInterval(t);
        }
        collect.log(collect.global);
      });   

      统计方法2:

      原理:对于网页高度小于屏幕的网站来说,只要在页面底部加上脚本打印当前时间即可;或者对于网页高度大于一屏的网页来说,只要在估算接近于一屏幕的元素的位置后,打印一下当前时间。当然这个时间要得把首屏中所有图片的加载时间也算上。

      缺点: 1.需要每个页面手动加入到对应位置 2.背景图片加载没有计算在内

    <!DOCTYPE html>
    <html>
        <head>
            <meta charset="utf-8">
            <meta name="viewport" content="width=device-width,minimum-scale=1.0,maximum-scale=1.0">
            <script type="text/javascript">
                window.logInfo = {};
                window.logInfo.openTime = performance.timing.navigationStart;
            </script>
        </head>
        <body>
            <div>这是第一屏,这是第一屏</div>
            <img src="http://static.oschina.net/uploads/space/2016/0623/152644_6UUC_1177792.png">
            <img src="http://static.oschina.net/uploads/space/2016/0623/152644_6UUC_1177792.png">
            <img src="http://static.oschina.net/uploads/space/2016/0623/152644_6UUC_1177792.png">
            <img src="http://static.oschina.net/uploads/space/2016/0623/152644_6UUC_1177792.png">
            <div>第一屏结尾,第一屏结尾</div>
            <script type="text/javascript">
                (function logFirstScreen() {
                    var images = document.getElementsByTagName('img');
                    var iLen = images.length;
                    var curMax = 0;
                    var inScreenLen = 0;
                    // 图片的加载回调
                    function imageBack() {
                        this.removeEventListener
                        && this.removeEventListener('load', imageBack, !1);
                        if (++curMax === inScreenLen) {
                            // 如果所有在首屏的图片均已加载完成了的话,发送日志
                            log();
                        }   
                    } 
                    // 对于所有的位于指定区域的图片,绑定回调事件
                    for (var s = 0; s < iLen; s++) {
                        var img = images[s];
                        var offset = {
                            top: 0
                        };
                        var curImg = img;
                        while (curImg.offsetParent) {
                            offset.top += curImg.offsetTop;
                            curImg = curImg.offsetParent;
                        }
                        // 判断图片在不在首屏
                        if (document.documentElement.clientHeight < offset.top) {
                            continue;
                        }
                        // 图片还没有加载完成的话
                        if (!img.complete) {
                            inScreenLen++;
                            img.addEventListener('load', imageBack, !1);
                        }
                    }
                    // 如果首屏没有图片的话,直接发送日志
                    if (inScreenLen === 0) {
                        log();
                    }
                    // 发送日志进行统计
                    function log () {
                        window.logInfo.firstScreen = +new Date() - window.logInfo.openTime;
                        console.log('首屏时间:', window.logInfo.firstScreen + 'ms');
                    }
                })();
            </script>
            <img src="http://static.oschina.net/uploads/space/2016/0623/152644_6UUC_1177792.png">
            <img src="http://static.oschina.net/uploads/space/2016/0623/152644_6UUC_1177792.png">
        </body>
    </html>

    用户可操作时间(dom Interactive)——用户可以进行正常的点击、输入等操作,默认可以统计domready时间,因为通常会在这时候绑定事件操作

     用户可操作为所有DOM都解析完毕的时间,默认可以统计domready时间,因为通常会在这时候绑定事件操作。对于使用了模块化异步加载的 JS 可以在代码中去主动标记重要 JS 的加载时间,这也是产品指标的统计方式。

      使用jquery中的$(document).ready()即是此意义 window.performance.timing.domInteractive window.performance.timing.domContentLoadedEventStart

      计算公式:

    performance.timing.domInteractive - performance.timing.navigationStart

    总下载时间——页面所有资源都加载完成并呈现出来所花的时间,即页面 onload 的时间

     默认可以统计onload时间,这样可以统计同步加载的资源全部加载完的耗时。如果页面中存在很多异步渲染,可以将异步渲染全部完成的时间作为总下载时间。

      计算公式:

    performance.timing.loadEventStart- performance.timing.navigationStart

    后端设计


    1、报表展示

    将各项指标展示在PC端浏览器界面上。

    2、图表展示

    可以采用D3.js或者百度的Echart对分析结果进行图表展示。

  • 相关阅读:
    [LeetCode 题解]: Remove Duplicates from Sorted List
    [LeetCode 题解]: Merge k Sorted Lists
    [LeetCode 题解]: Insertion Sort List
    [LeetCode 题解]:Candy
    求任意多边形面积 python实现
    C++飞机大战
    version robot
    python一段代码 感受一下
    微机原理上机第四次实验内容
    初步的百度爬虫
  • 原文地址:https://www.cnblogs.com/sexintercourse/p/5898251.html
Copyright © 2020-2023  润新知