文档章节

前端性能优化(一) 前端性能分析

ouven
 ouven
发布于 01/03 20:42
字数 2668
阅读 1090
收藏 12
点赞 0
评论 0

  前端性能优化是一个很宽泛的概念,本书前面的部分也多多少少提到一些前端优化方法,这也是我们一直在关注的一件重要事情。配合各种方式、手段、辅助系统,前端优化的最终目的都是提升用户体验,改善页面性能,我们常常竭尽全力进行前端页面优化,但却忽略了这样做的效果和意义。先不急于探究前端优化具体可以怎样去做,先看看什么是前端性能,应该怎样去了解和评价前端页面的性能。

  通常前端性能可以认为是用户获取所需要页面数据或执行某个页面动作的一个实时性指标,一般以用户希望获取数据的操作到用户实际获得数据的时间间隔来衡量。例如用户希望获取数据的操作是打开某个页面,那么这个操作的前端性能就可以用该用户操作开始到屏幕展示页面内容给用户的这段时间间隔来评判。用户的等待延时可以分成两部分:可控等待延时和不可控等待延时。可控等待延时可以理解为能通过技术手段和优化来改进缩短的部分,例如减小图片大小让请求加载更快、减少HTTP请求数等。不可控等待延时则是不能或很难通过前后端技术手段来改进优化的,例如鼠标点击延时、CPU计算时间延时、ISP(Internet Service Provider,互联网服务提供商)网络传输延时等。所以要知道的是,前端中的所有优化都是针对可控等待延时这部分来进行的,下面来了解一下如何获取和评价一个页面的具体性能。

5.4.1 前端性能测试

  获取和衡量一个页面的性能,主要可以通过以下几个方面:Performance Timing API、Profile工具、页面埋点计时、资源加载时序图分析。

一、Performance Timing API

  Performance Timing API是一个支持Internet Explorer 9以上版本及WebKit内核浏览器中用于记录页面加载和解析过程中关键时间点的机制,它可以详细记录每个页面资源从开始加载到解析完成这一过程中具体操作发生的时间点,这样根据开始和结束时间戳就可以计算出这个过程所花的时间了。

  图5-4为W3C标准中Performance Timing资源加载和解析过程记录各个关键点的示意图,浏览器中加载和解析一个HTML文件的详细过程先后经历unload、redirect、App Cache、DNS、TCP、Request、Response、Processing、onload几个阶段,每个过程开始和结束的关键时间戳浏览器已经使用performance.timing来记录了,所以根据这个记录并结合简单的计算,我们就可以得到页面中每个过程所消耗的时间。

图5-4 performance API关键时间点记录


function performanceTest(){



let timing = performance.timing,

readyStart = timing.fetchStart - timing.navigationStart,

redirectTime = timing.redirectEnd - timing.redirectStart,

appcacheTime = timing.domainLookupStart - timing.fetchStart,

unloadEventTime = timing.unloadEventEnd - timing.unloadEventStart,

lookupDomainTime = timing.domainLookupEnd - timing.domainLookupStart,

connectTime = timing.connectEnd - timing.connectStart,

requestTime = timing.responseEnd - timing.requestStart,

initDomTreeTime = timing.domInteractive - timing.responseEnd,

domReadyTime = timing.domComplete - timing.domInteractive,

loadEventTime = timing.loadEventEnd - timing.loadEventStart,

loadTime = timing.loadEventEnd - timing.navigationStart;



console.log('准备新页面时间耗时: ' + readyStart);

console.log('redirect 重定向耗时: ' + redirectTime);

console.log('Appcache 耗时: ' + appcacheTime);

console.log('unload 前文档耗时: ' + unloadEventTime);

console.log('DNS 查询耗时: ' + lookupDomainTime);

console.log('TCP连接耗时: ' + connectTime);

console.log('request请求耗时: ' + requestTime);

console.log('请求完毕至DOM加载: ' + initDomTreeTime);

console.log('解析DOM树耗时: ' + domReadyTime);

console.log('load事件耗时: ' + loadEventTime);

console.log('加载时间耗时: ' + loadTime);

}

  通过上面的时间戳计算可以得到几个关键步骤所消耗的时间,对前端有意义的几个过程主要是解析DOM树耗时、load事件耗时和整个加载过程耗时等,不过在页面性能获取时我们可以尽量获取更详细的数据信息,以供后面分析。除了资源加载解析的关键点计时,performance还提供了一些其他方面的功能,我们可以根据具体需要进行选择使用。


performance.memory // 内存占用的具体数据

performance.now() // performance.now()方法返回当前网页自performance.timing到现在的时间,可以精确到微秒,用于更加精确的计数。但实际上,目前网页性能通过毫秒来计算就足够了。

performance.getEntries() // 获取页面所有加载资源的performance timing情况。浏览器获取网页时,会对网页中每一个对象(脚本文件、样式表、图片文件等)发出一个HTTP请求。performance.getEntries方法以数组形式返回所有请求的时间统计信息。

performance.navigation // performance还可以提供用户行为信息,例如网络请求的类型和重定向次数等,一般都存放在performance.navigation对象里面。

performance.navigation.redirectCount // 记录当前网页重定向跳转的次数。

参考资料:https://www.w3.org/TR/resource-timing/。

二、 Profile工具

  Performance Timing API描述了页面资源从加载到解析各个阶段的执行关键点时间记录,但是无法统计JavaScript执行过程中系统资源的占用情况。Profile是Chrome和Firefox等标准浏览器提供的一种用于测试页面脚本运行时系统内存和CPU资源占用情况的API,以Chrome浏览器为例,结合Profile,可以实现以下几个功能。

1.分析页面脚本执行过程中最耗资源的操作

2.记录页面脚本执行过程中JavaScript对象消耗的内存与堆栈的使用情况

3.检测页面脚本执行过程中CPU占用情况

  使用console.profile()和console.profileEnd()就可以分析中间一段代码执行时系统的内存或CPU资源的消耗情况,然后配合浏览器的Profile查看比较消耗系统内存或CPU资源的操作,这样就可以有针对性地进行优化了。


console.profile();

// TODOS,需要测试的页面逻辑动作

for(let i = 0; i < 100000; i ++){

console.log(i * i);

}

console.profileEnd();

三、 页面埋点计时

  使用Profile可以在一定程度上帮助我们分析页面的性能,但缺点是不够灵活。实际项目中,我们不会过多关注页面内存或CPU资源的消耗情况,因为JavaScript有自动内存回收机制。我们关注更多的是页面脚本逻辑执行的时间。除了Performance Timing的关键过程耗时计算,我们还希望检测代码的具体解析或执行时间,这就不能写很多的console.profile()和console.profileEnd()来逐段实现,为了更加简单地处理这种情况,往往选择通过脚本埋点计时的方式来统计每部分代码的运行时间。

  页面JavaScript埋点计时比较容易实现,和Performance Timing记录时间戳有点类似,我们可以记录JavaScript代码开始执行的时间戳,后面在需要记录的地方埋点记录结束时的时间戳,最后通过差值来计算一段HTML解析或JavaScript解析执行的时间。为了方便操作,可以将某个操作开始和结束的时间戳记录到一个数组中,然后分析数组之间的间隔就得到每个步骤的执行时间,下面来看一个时间点记录和分析的例子。


let timeList = [];

function addTime(tag){ timeList.push({"tag":tag,"time":+new Date}); }



addTime("loading");



timeList.push({"tag":"load","time": +new Date()});

// TODOS,load加载时的操作

timeList.push({"tag":"load","time": +new Date()});



timeList.push({"tag":"process","time": +new Date()});

// TODOS,process处理时的操作

timeList.push({"tag":"process","time": +new Date()});



parseTime(timeList); // 输出{load: 时间毫秒数,process: 时间毫秒数}



function parseTime(time){

let timeStep = {},

endTime;

for(let i = 0,len = time.length; i < len; i ++){

if(!time[i]) continue;



endTime = {};

for(let j = i+1; j < len; j++ ){

if(time[j] && time[i].tag == time[j].tag){

endTime.tag = time[j].tag;

endTime.time = time[j].time;

time[j] = null;

}

}

if(endTime.time >= 0 && endTime.tag){

timeStep[endTime.tag] = endTime.time - time[i].time;

}

}

return timeStep;

}

  这种方式常常在移动端页面中使用,因为移动端浏览器HTML解析和JavaScript执行相对较慢,通常为了进行性能优化,我们需要找到页面中执行JavaScript耗时的操作,如果将关键JavaScript的执行过程进行埋点计时并上报,就可以轻松找出JavaScript执行慢的地方,并有针对性地进行优化。

四、资源加载时序图

  我们还可以借助浏览器或其他工具的资源加载时序图来帮助分析页面资源加载过程中的性能问题。这种方法可以粗粒度地宏观分析浏览器的所有资源文件请求耗时和文件加载顺序情况,如保证CSS和数据请求等关键性资源优先加载,JavaScript文件和页面中非关键性图片等内容延后加载。如果因为某个资源的加载十分耗时而阻塞了页面的内容展示,那就要着重考虑。所以,我们需要通过资源加载时序图来辅助分析页面上资源加载顺序的问题。

图5-5

  图5-5为使用Fiddler获取浏览器访问地址 http://www.jixianqianduan.com 时的资源加载时序图。根据此图,我们可以很直观地看到页面上各个资源加载过程所需要的时间和先后顺序,有利于找出加载过程中比较耗时的文件资源,帮助我们有针对性地进行优化。

系列文章:

前端性能优化(一) 前端性能分析: https://my.oschina.net/zhangstephen/blog/1601380

前端性能优化(二) 桌面浏览器前端优化策略: https://my.oschina.net/zhangstephen/blog/1601382

前端性能优化(三) 移动端浏览器前端优化策略: https://my.oschina.net/zhangstephen/blog/1601383

  本文摘自书籍《现代前端技术解析》

© 著作权归作者所有

共有 人打赏支持
ouven

ouven

粉丝 105
博文 30
码字总数 77829
作品 0
深圳
高级程序员
史上最全的前端资源大汇总

1.前言 最近有很多朋友问我有没有相关的书籍推荐,希望能够自学一下前端。 正好最近在查阅文章的时候,发现有朋友已经进行过总结。 经过沟通和“行贿”��,终于取得转载权利,在此感谢晚晴...

mr_lp
2017/01/13
0
0
web前端性能优化指南

摘要:一般来说页面访问的时间有一条著名的“2-5-8原则”。当用户访问一个页面: 1、在2秒内得到响应时,会感觉系统响应很快;2、在2-5秒之间得到响应时,会感觉系统的响应速度还可以;3、在...

技术金三胖
01/13
0
0
通过页面埋点做监控却不影响性能?解密ARMS前端监控数据上报技术内幕

前端监控 (又叫UEM,User Experience Management, 用户体验管理) 一般帮助用户定位页面性能瓶颈、复现用户端的偶发问题。其监控的主要功能包括但不限于: 日志采集 日志上报 数据分析 平台展...

中间件小哥
05/15
0
0
PHP高级程序员所要掌握的技能

很多工作几年的php开发者都会有这样的迷茫,php开发多了,无外乎“增删改查调接口”,真的是这样吗? 实际上开发者除了把自己当成php程序员,更应该关注php以外的东西,将自己定位于能熟练使...

小田天
2016/11/18
82
0
前端性能监控系统

引言 前阵子在w3ctech的走进名企 - 百度前端 FEX 专场上曾“夸下海口”说听完讲座后七天就可以打造自己的前端性能监控系统,既然说出去了也不能食言。从前一篇文章前端数据之美相信大家对前端...

小马_wolf
2016/09/18
42
0
前端性能优化:使用Array.prototype.join代替字符串连接

来源:GBin1.com 有一种非常简单的客户端优化方式,就是用Array.prototype.join代替原有的基本的字符连接的写法。在这个系列的第一篇中,我在代码中使用了基本字符连接: htmlStr += ' ' + i...

gbin1
2013/07/03
418
0
php职业规划

现在工作几年的php开发者都会有这样的迷茫,php开发多了,无外乎“增删改查调接口”,感觉每天的工作都是重复性的劳动,一点新意也没有,感觉技术上没有多大的长进了。真的是这样吗? 实际上...

成越
2016/09/01
85
0
APMCon 2017震撼来袭!参与评论送千元门票 与国内外技术大牛来一场夏日盛宴

APMCon是由听云、极客邦科技与InfoQ联合主办的全球高水准APM技术盛会,聚焦当前最为关键的移动端、Web端和Server端的性能监控和管理技术。整个会议包含智能运维、数据库性能优化、移动性能优...

听云APM
2017/07/03
1K
50
OneAPM x 腾讯 | OneAPM 技术公开课·深圳 报名:前端性能大作战!

「 OneAPM 技术公开课」由应用性能管理第一品牌 OneAPM 发起,内容面向 IT 开发和运维人员。云集技术牛人、知名架构师、实践专家共同探讨技术热点。 11月28日,OneAPM 技术公开课第五期将走进...

OneAPM蓝海讯通
2015/11/16
60
0
ELSE 技术周刊(2017.12.11期)

业界动态 Angular 5.1 & More Now Available Angular发布5.1版本,同时发布了Angular CLI 1.6版本以及首个稳定版本的Angular Material。CLI支持了Service Worker,以及带来对AppShell更好的支...

风清洋ELSE
2017/12/16
0
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

《趣谈网络协议》02之网络分层的真实含义

一、提出问题 1.提出问题 当你听到什么二层设备、三层设备、四层 LB 和七层 LB 中层的时候,是否有点一头雾水,不知道这些所谓的层,对应的各种协议具体要做什么“工作”? 2.这四个问题你弄...

aibinxiao
8分钟前
1
0
Python3学习日志二 Python中的集合set和字典dict

1.集合set 定义一个集合set 我们可以看到定义集合set有两种不同的形式,如果要定义一个空的集合set不能用{}而是要用set();另外,集合是无序的,而且set中的元素是不可重复的,如果你定义了一...

Mr_bullshit
16分钟前
0
0
adb 操作指令详解

ADB,即 Android Debug Bridge,它是 Android 开发/测试人员不可替代的强大工具,也是 Android 设备玩家的好玩具。 注:有部分命令的支持情况可能与 Android 系统版本及定制 ROM 的实现有关。...

孟飞阳
23分钟前
0
0
nodejs安装以及环境配置(很好的node安装和配置文章,少走很多弯路)

一、安装环境 1、本机系统:Windows 10 Pro(64位) 2、Node.js:v6.9.2LTS(64位) 二、安装Node.js步骤 1、下载对应你系统的Node.js版本:https://nodejs.org/en/download/ 2、选安装目录进...

sprouting
40分钟前
0
0
Redisson

了解了Redisson,发现使用挺简单的,接下来准备深入学习一下。 Redisson介绍 Redisson是架设于Redis基础之上的一个Java驻内存数据网格(In-Memory Data Grid) Redisson在基于NIO的Netty框架上...

to_ln
40分钟前
0
0
python有哪些好玩的应用实现,用python爬虫做一个二维码生成器

python爬虫不止可以批量下载数据,还可以有很多有趣的应用,之前也发过很多,比如天气预报实时查询、cmd版的实时翻译、快速浏览论坛热门帖等等,这些都可以算是爬虫的另一个应用方向! 今天给...

python玩家
40分钟前
0
0
jq 判断复选框是否被选中,复选框后台接收

1. 效果 2. 代码 html部分: JS部分: var rememberLogin = $("#rememberLoginId").is(':checked')//获取复选框是否被选中 var rememberLoginval = $("#rememberLoginId").attr('value')//拿......

Lucky_Me
47分钟前
0
0
python爬虫日志(3)-爬去异步加载网页

在浏览器检查元素页面中,选取Network中的XHR选项即可观察每次加载页面,网页发出的请求,观察url的规律即可利用封装的函数对每一页进行爬取。

茫羽行
48分钟前
0
0
Python数据分析numpy基础-维度的认识

什么是多维数组? 核心对象是同型的多维数组(简单理解就是一个表格,通常内容都是些数字),具有相同的数据类型。 概念: 1. axes(轴):数组的维度统称为轴。 2. rank:轴的数量称为rank。...

十年磨一剑3344
53分钟前
0
0
Java 正则表达式相关资料

1.java正则表达式过滤html标签

IT追寻者
57分钟前
0
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部