前端性能优化之性能测试

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

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

前端性能测试

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

Performance Timing API

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

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

                                                                   图1-1    Performance Timing 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 事件耗时和整个加载过程耗时等,不过在页面性能获取时我们可以尽量获取更详细的数据信息,以供后面分析。除了资源加载解析的关键点计时,preformance 还提供了一些其他方面的功能,我们可以根据具体需要进行选择使用。

performance.memory      //内存占用的具体数据
performance.now()       //performance.now()方法返回当前网页自performance.timing到现在的时间,可以精确到微秒,用于更加精确的计数。但实际上,目前网页性能通过毫秒来计算就足够了
performance.getEntries()        //获取页面所有加载资源的performance timing 情况。浏览器获取网页时,会对网页中每一个对象(脚本文件、样式表、图片文件等)发出一个HTTP请求。performance.getEntries 方法以数组形式返回所有请求的时间统计信息
performance.navigation      //performance 还可以提供用户行为信息,例如网络请求的类型和重定向次数等,一般都存放在performance.navigation对象里面
performance.navigation.redirectCount        //记录当前网页重定向跳转的次数
复制代码

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()});console.log(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 文件和页面中非关键性图片等内容延后加载。如果因为某个资源的加载十分耗时而阻塞了页面的内容展示,那就要着重考虑。所以,我们需要通过资源加载时序图来辅助分析页面上资源加载顺序的问题。

图 1-2 为使用 Fiddler 抓取浏览器访问地址时的资源加载时序图,图 1-3 为 Chrome 浏览器访问猫眼电影官网时的资源加载时序图.根据资源加载时序图我们可以很直观地看到页面上各个资源加载过程所需要的时间和先后顺序,有利于找出加载过程中比较耗时的文件资源,帮助我们有针对性地进行优化。

                                                                   图1-2    Fiddler 页面加载文件资源时序图

                                                        图1-3    Chrome浏览器 猫眼电影官网页面加载文件资源时序图

总结

通过上文介绍的利用Performance Timing API、Prpfile工具、页面埋点计时、资源加载时序图分析几个方面来获取和衡量一个页面的性能,找出加载过程中比较耗时的文件资源,帮助我们有针对性地进行优化。医病必须诊断找到病因,前端性能测试在前端性能优化中属于诊断工作,只有找到病因,才能进行针对性治疗优化。在此欢迎大家加入QQ前端技术交流群 544587175 ,在后续我会从桌面浏览器和移动端浏览器两个方面详细讲解不同终端的优化策略,敬请关注......

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.tpcf.cn/news/453255.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

模拟传输和数字传输的优缺点

与模拟数据通信相比较&#xff0c;数字数据通信具有下列优点&#xff1a; a. 来自声音、视频和其他数据源的各类数据均可统一为数字信号的形式&#xff0c;并通过数字通信系统传输 b. 以数据帧为单位传输数据&#xff0c;并通过检错编码和重发数据帧来发现与纠正通信错误&am…

android浏览SD卡的文件,简单实现浏览Android SD卡中的文件

----Main.javapublic class Main extends Activity {private TextView textView;private Button button;private ListView listView;public File currentParentFile;public File[] currentFiles;public static String sdcardDir ;static {try {//sd卡的路径sdcardDir Environ…

Java线程状态Jstack线程状态BLOCKED/TIMED_WAITING/WAITING解释

一、线程5种状态 新建状态&#xff08;New&#xff09; 新创建了一个线程对象。 就绪状态&#xff08;Runnable&#xff09; 线程对象创建后&#xff0c;其他线程调用了该对象的start()方法。该状态的线程位于可运行线程池中&#xff0c;变得可运行&#xff0c;等待获取CPU的使…

彩票相关知识

很多人做梦都想中得彩票头奖&#xff0c;很多人希望天上能掉下馅饼来砸中自己&#xff0c;很多人在作白日梦……彩票是一种风险投资&#xff0c;是一种四两拨千斤的气势&#xff0c;更是一种众人拾柴火焰高的真实写照&#xff0c;没买过彩票的人是很难体会那种美好的期望及期望…

(模拟信号/数字信号)分别以(模拟信号/数字信号)中传输方式

1、基本概念、基本术语和数据通信系统 1.基本概念和基本术语 数据&#xff1a;能够由计算机处理的数字、字母和符号等具有一定意义的实体。 分类&#xff1a;模拟数据可以在一定的数据区域中取连续的值&#xff0c;如声音和图像&#xff1b;数字数据只能取离散的数值&#xff0…

C# 获取文件名及扩展名

C#通过文件路径获取文件名 string fullPath "/WebSite1/Default.aspx";string filename System.IO.Path.GetFileName(fullPath);//文件名 “Default.aspx” string extension System.IO.Path.GetExtension(fullPath);//扩展名 “.aspx” string fileNameWithoutEx…

android11 rom,小米打造基于安卓11的ROM来了:米10尝鲜

原标题&#xff1a;小米打造基于安卓11的ROM来了&#xff1a;米10尝鲜据XDA报道&#xff0c;距离Android 11正式版发布还有几天时间&#xff0c;9月8日正式面向Pixel 2、Pixel 3、Pixel 4和Pixel 3a等机型推送Android 11正式版。另一方面&#xff0c;各大手机品牌已经紧锣密鼓开…

基于 HTML5 WebGL 的 3D 服务器与客户端的通信

这个例子的初衷是模拟服务器与客户端的通信&#xff0c;我把整个需求简化变成了今天的这个例子。3D 机房方面的模拟一般都是需要鹰眼来辅助的&#xff0c;这样找产品以及整个空间的概括会比较明确&#xff0c;在这个例子中我也加了&#xff0c;这篇文章就算是我对这次项目的一个…

什么是顺序执行以及其特点

顺序执行是程序的一种执行方式。是把一个具有独立功能的程序独占处理机直至最终结束的过程称为程序的顺序执行 顺序执行的特点&#xff1a;顺序性&#xff1a;程序顺序执行时&#xff0c;其执行过程可看作一系列严格按程序规定的状态转移过程&#xff0c;也即是每执行一条指令&…

一年成为Emacs高手(像神一样使用编辑器)

作者: 陈斌(redguardtoo) 更新时间: 2012-02-10 五 原创时间: 2012-01-31 周二 15:08 很容易.一年多前我还在Vi阵营,偶尔使用Emacs还总是忘记退出(C-x C-c)的快捷键,但是一年后我跨入高手行列. 现在网上很多中文文章都是和你强调Emacs有多牛,以激发你的兴趣.最有名的大概是王垠…

七种常见的核酸序列蛋白编码能力预测工具 | ncRNAs | lncRNA

注&#xff1a;这些工具的应用都是受限的&#xff0c;有些本来就是只能用于预测动物&#xff0c;在使用之前务必用ground truth数据来测试一些。我想预测某一个植物的转录本&#xff0c;所以可以拿已经注释得比较好的拟南芥来测试一下。&#xff08;测试的结果还是比较惊人的&a…

android预览界面编译出错,Android O预览findViewById编译错误

我试图测试Android O Developer Preview的第二阶段。 项目创建后&#xff0c;我只是点击了构建并运行但我没有任何成功。Android默认生成的代码如下&#xff1a;Toolbar toolbar (Toolbar) findViewById(R.id.toolbar);发生编译错误。Error:(18, 37) error: reference to find…

中断与异常的区别

中断&#xff1a; 中断是CPU&#xff08;硬件&#xff09;所具备的功能 &#xff0c;它是指系统停止当前正在运行的程序而转向其他服务&#xff0c;可能是因 为优先级高的请求服务了&#xff0c;或者是因为人为安排中断。中断是属于正常现象。主要由CPU以外的事件引起的 中断…

寒武纪找到了引领中国AI芯片走向世界的路

大约6亿年前在地质学上被称作“寒武纪”的时代&#xff0c;大量无脊椎动物在短时间内出现“生命大爆发”。如今&#xff0c;“寒武纪”这个名字再次被人们提及&#xff0c;它源自中科院计算所研发的人工智能芯片处理器的命名&#xff0c;意喻人工智能即将迎来大爆发的时代。“寒…

浅谈PPM (Project Portfolio Management)

前言&#xff1a; 本文以纯理论性的PPM讲解为主&#xff0c;不会涉及到具体如何实施&#xff0c;我会在以后介绍详细的PPM实施方案介绍。 PPM&#xff0c;可能很多人并不清楚甚至可能没听说过&#xff0c;这是一个近些年才流行起来的概念&#xff0c;是Project Portfolio Mana…

poj 3071 Football

http://poj.org/problem?id3071 2^n 支足球队比赛&#xff0c;共比n场&#xff0c;第一场1号与2号比&#xff0c;3号与4号比…… 每场胜出者进入下一场&#xff0c;输者淘汰 每一场都是相邻的两个队伍比拼 已知任意两个队伍比拼获胜的概率 求最后哪只队伍获胜的概率最大 dp[i]…

进程调度与作业调度

进程调度是真正让某个就绪状态的进程到处理机上运行&#xff0c;而作业调度只是使作业具有了竞争处理机的机会。进程调度&#xff08;又称微观调度、低级调度、短程调度&#xff09;&#xff1a; 是按照某种调度算法从就绪状态的进程中选择一个进程到处理机上运行。负责进程调…

tensorflow源码安装

主要参考&#xff1a;https://www.tensorflow.org/install/install_sources#ConfigureInstallation卸载tensorflow sudo pip uninstall tensorflow 安装git 安装git时记得先安装&#xff0c;后更新系统 sudo apt install git安装jdk8: myubuntu:~$ java myubun…

Makefile学习之通配符和自动变量

规则中的通配符 “*” &#xff0c;“&#xff1f;” &#xff0c;“ [...]”, " % " , " wildcard " 1.“*” *.c表示所有后缀为.C的文件&#xff1b; 如果文件中用到通配符&#xff0c;使用“\*”; 2.通配符在变量中的使用&#xff1b; objects*.c 注意…

英语中十二个月名称的由来

转自网络&#xff0c;原出处不详。 公历一年有12个月&#xff0c;但不少人并不知道12 个月的英语名称的来历。公历起源于古罗马历法。罗马的英语原来只有10 个月&#xff0c;古罗马皇帝决定增加两个月放在年尾&#xff0c;后来朱里斯*凯撒大帝把这两个月移到年初&#xff0c;…