前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >专栏 >使用Chrome对项目进行性能分析

使用Chrome对项目进行性能分析

作者头像
用户1428723
发布于 2020-08-06 07:48:37
发布于 2020-08-06 07:48:37
9510
举报
文章被收录于专栏:代码与画家代码与画家

最近发现一篇关于使用Chrome进行调试和优化的文章,写的特别全面和友好,虽然Chrome版本比较老了,但是和现在的功能基本没有大变化,还是非常值得参考的。下面是原作者的连接,但是已经打不开了

,http://www.kazaff.me/2014/01/26/chrome-developer-tools%E4%B9%8B%E5%86%85%E5%AD%98%E5%88%86%E6%9E%90/

-------转载分割线-------

前面的几篇中分别介绍了DevTools的不同面板,这次来看一下Profiles面板,如下图:

工具栏中的按钮功能都比较明显,除了视图模式选择框一开始难以理解。 在Profiles面板的右边列表区域中,Function列显示的影响性能的函数集合~ 而Bottom Up允许你查看指定函数的被调用轨迹(自底向上,类似异常错误提示信息中的堆栈信息)。 Top Down视图则显示函数调用深度轨迹(自上而下,类似单步调试时的step in)。

在“隐身模式”的窗口下打开上面的“output”标签卡,然后打开DevTools的Profiles面板,点击面板中的“Start”按钮,然后点击页面上的“测试按钮”,然后点击面板中的“Stop”按钮,在创建的“Profile1”中可以看到收集的信息,如下图:

Profile面板就是这么简单,我们接下来的关注点在如何查找js中的“内存泄露”或定为“内存膨胀”的原因! 在javascript中产生内存泄露的原因和其他语言也非常类似,一般是因为代码出于某种问题而没有及时释放申请到的内存而造成的!这个“泄露”过程是通常是持续渐进的,一点一点的消耗完计算机的内存资源~~对于那些基于js框架实现的SPA架构的系统,内存泄露将会是一个非常值得重视的关注点!

说到这里,就不得不提到V8的垃圾回收机制~(http://newhtml.net/v8-garbage-collection/)即便JS拥有自动回收机制,合理的内存管理还是非常有必要的!通常情况下,当你解决内存泄露问题时,请先问一下你自己下面这三个问题:

  1. 我的页面消耗了太多内存么? DevTools工具的Timeline面板能帮你分析提供数据支撑,Memory视图能显示出当前页面的Dom节点数,JS事件监听器个数等(性能优化的首要准则:避免持续引用太多DOM元素,注销掉过期的事件监听器,不要用全局变量存储你不需要的数据!)
  2. 我的页面存在内存泄露么? 对象构造追踪器能帮你缩小内存泄露的排查范围,它会实时监控JS中对象的构造情况,你可以使用“heap profiler”来记录JS的堆信息快照,通过分析和比对多张快照来定位哪些对象并没有被垃圾回收释放!
  3. 我的页面垃圾回收的频率是多少? 如果页面垃圾回收太频繁,那可能说明你的代码创建对象太频繁了,Timeline面板的Memory视图可以帮助你锁定频繁创建对象的代码位置!

术语和原理


对象大小 这里的对象,包括了JS中的基础类型(整型,字符串)和对象类型~ 一个对象有两种形式来持有内存:

  • 直接拥有
  • 间接引用

这两种形式分别对应着DevTools的Profiles面板中Heap Profiler的Shallow Size 和 Retained Size,看下图:

Shallow Size 这一列代表对象直接持有的内存大小。一个标准的JS对象通常会持有用于描述自身逻辑和存储直接值(属性值)的内存。 通常情况下应该只有字符串和数组类型可能拥有一个较大的Shallow Size。

Retained Size 这一列代表着只有当前对象所引用的其他对象占用的内存大小(稍微有点绕口,这已经我能翻译出来的最简单的解释了)! 官方文档中在描述这部分定义的时候提到了GC roots,但是同时也表明:这玩意儿并不需要开发者去关心! 按照我粗俗的理解,应该表达的是能够用于计算对象引用计数时追溯到的最初的那个根节点,我们先继续往后看。

Object’s Retaining Tree 在JS申请的堆内存中,对象之间的复杂关系会生成一张关系网,如下图:

构成这张关系网的元素有两种:

  • Nodes:节点,对应一个对象,用创建该对象的构造方法来命名
  • Edges:连接线,对应着对象间的引用关系,用对象属性名来命名

你可能注意到上面的快照截图中有一列叫:Distance,它表示当前对象到GC root的距离。 如果同类型的对象几乎都拥有相同的距离值,只有其中个别几个对象的距离值很大,那么你就要特别留意了!

Dominators 统治者对象拥有一棵树,树中的节点是该统治对象能完全控制的对象集合,如下图:

图中:

  • 节点1完全控制节点2
  • 节点2完全控制节点3,节点4,节点6
  • 节点3完全控制节点5
  • 节点5完全控制节点8
  • 节点6完全控制节点7

这就引出一条规则:如果节点B存在于每一条从根节点到节点A的路径当中,那么我们可以称节点B是节点A的统治节点!

V8特性

现在我们来说一下V8的虚拟机中和内存有关的一些特性,了解这些有利于我们分析问题和看懂heap快照!

JavaScript对象 JS中有三种基础类型:

  • Numbers
  • Booleans
  • Strings

其中,Numbers会以下面两种方式来存储:

  • small integers(SMIs):31位内的整数值
  • heap numbers:超过SMI表大小的值,例如doubles

Strings也会对应两种存储方案:

  • VM heap
  • 非VM heap

一个JS对象会从JS的堆内存(VM heap)中申请自己所需要的内存,而V8的垃圾回收器会在该对象不在活跃(没有任何对它的强引用后)后回收内存。

本地对象(Native objects)代表那些不在JS堆内存中的对象集合,它不受控于V8的垃圾回收机制~

Chrome的任务管理器 你可以通过“Shift”+“Esc”开启Chrome任务管理器,它能让你了解当前浏览器的一些情况,包括内存使用率,特别是能查看JS的内存消耗,如下图:

当然这个方法还是过于粗糙,回想前几篇介绍DevTools的文章,我们可以回忆起在Timeline面板中有一个Memory视图,我们来看一下如何使用它来判别页面中的内存泄露!

通常情况下,为了发现并修复内存泄露问题,我们必须要有能力做到以下两点:

  • 可以重建泄露的场景(或者叫操作序列)
  • 基准(baseline)

前者是为了定位问题点,后者是为了验证是否修复!

通常情况下,当你准备的操作序列执行完毕后点击工具条中的垃圾箱图标(启动浏览器的垃圾回收)时,如果发现相关的资源并没有回归基准状态,那通常意味着你的代码出现了内存泄露~

一旦你确定存在内存泄露,就可以利用heap profiler来继续深究了!

打开Profiles面板,选择“Take Heap Snapshot”并点击“Start”按钮,如下图:

需要注意的是,每次你创建快照,都会自动触发一次垃圾回收~~

下面主要解释一下snapshot视图,快照可以按照不同的视角来展示:

  • Summary:按照构造方法名称来分组显示对象
  • Comparison:显示两个不同快照的差异
  • Containment:允许查看堆内容
  • Dominators:显示统治者树(没有上面那张gif图那么直观啊~这不是坑爹么?)

PS:Dominators视图默认没有开启,需要在Settings里选择“Show advanced heap snapshot”,并重启浏览器~~

Summary视图 前面其实已经提到过该视图,包括视图中显示的个别列的含义(Distance,Shallow Size,Retained Size),我们只来说一下还没有提到过的一些地方,该视图中的“Constructor”列,是基于对象的构造方法名称来分组显示当前页面中的所有对象(之前貌似也说过~)。而“Object Count”则显示对应类型的对象个数,这应该很容易理解吧~

注意,上图中,以黄色背景标注的对象表明该对象包含指向其他对象的引用,而红色背景的对象则表示它虽然没有被直接引用,但由于它属于“detached DOM tree”的一部分,所以它也是无法被回收(可以参见下面说的Dom泄露~),“@”后面的数字代表的是该对象的唯一的ID

Comparison视图 该视图用于比对多个快照细节,来帮助你发现它们之间的差异,进而锁定哪些对象有内存泄露! 通常情况下,你提供的用来验证内存泄露的操作序列应该是相抵消的,举个例子:开启某一个窗口,再关闭它! 这样更有利于你利用基准来判断是否发生了内存泄露! 那么实际流程应该如下:

  1. 打开对应的页面,在开始你的操作序列之前创建一张heap快照;
  2. 开始你的操作序列,例如打开一个窗口;
  3. 结束你的操作序列,例如关闭它;
  4. 创建第二张heap快照,并和第一张快照进行对比。

Containment视图 这个视图可以让你更近距离观察对象结构,允许你观察函数内部的闭包,VM内核对象等~

利用Containment视图,你可以查看到所有创建的闭包细节,利用Comparison视图来对比多张快照能直观的看到闭包的增长,使用Timeline面板的Memory视图你会得到内存增长曲线,我就不截图了……

除了闭包造成的内存泄露外,我们再来看一个DOM泄露~~ 看下图:

#leaf节点会持有指向它的父节点#li的引用(一直递归到根节点#tree),所以只要#leaf还处于活跃状态(没释放),那么整棵DOM树都不会释放。所以在进行一些DOM操作的时候一定要注意这一点啊~~ 有兴趣的童鞋可以测试一下下面这段例子:

上述内容只是从官方手册中提炼出来的,可能有错误,也可能不够精细,如果发现错误,希望能够回帖更正我~ 谢谢~

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2017-09-23,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 代码与画家 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
2020-5-10-RESTfulAPI中能否使用query string
之前2020-5-6-restful理解 - huangtengxiao和大家介绍了对RESTful的理解。然后就有小伙伴问了我灵魂问题,对于RESTfulAPI设计,是不是不能使用query string?
黄腾霄
2020/06/10
5980
2020-5-16-理解Graphql
之前2020-5-6-restful理解 - huangtengxiao和大家提及了RESTfulAPI的一个弊端,就是接口膨胀。
黄腾霄
2020/06/10
6580
2020-5-11-HATEOAS简介
之前2020-5-6-restful理解 - huangtengxiao和大家介绍了对RESTful的理解。今天和大家介绍下RESTful中最重要的一个概念HATEOAS。
黄腾霄
2020/06/10
7790
更好的理解RESTFUL
RESTFUL 当前已然成为 API 设计的最佳规范, 但是有些读者还对 RESTFUL 不太了解, 包括微信群里这两天也有朋友在问, 今天干脆总结下。
iTesting
2019/10/29
4470
更好的理解RESTFUL
通俗易懂RESTful,如何设计RESTful风格API「建议收藏」
REST — REpresentational State Transfer 直译:表现层状态转移。这个中文直译经常出现在很多文章中。尼玛,谁听得懂“表现层状态转移”,这是人话吗?
全栈程序员站长
2022/07/04
7590
通俗易懂RESTful,如何设计RESTful风格API「建议收藏」
CoAP | 物联网中的RESTful架构实现
说起 HTTP,相信大家都不陌生,HTTP 全称 Hyper Text Transfer Protocol,即超文本传输协议。
Mculover666
2020/07/16
9180
深入理解什么是RESTful API ?
越来越多的人开始意识到,网站即软件,而且是一种新型的软件。   这种"互联网软件"采用客户端/服务器模式,建立在分布式体系上,通过互联网通信,具有高延时(high latency)、高并发等特点。   网站开发,完全可以采用软件开发的模式。但是传统上,软件和网络是两个不同的领域,很少有交集;软件开发主要针对单机环境,网络则主要研究系统之间的通信。互联网的兴起,使得这两个领域开始融合,** 现在我们必须考虑,如何开发在互联网环境中使用的软件。**
竹清
2018/08/31
6430
深入理解什么是RESTful API ?
深入理解什么是RESTful API ?
越来越多的人开始意识到,网站即软件,而且是一种新型的软件。   这种"互联网软件"采用客户端/服务器模式,建立在分布式体系上,通过互联网通信,具有高延时(high latency)、高并发等特点。   网站开发,完全可以采用软件开发的模式。但是传统上,软件和网络是两个不同的领域,很少有交集;软件开发主要针对单机环境,网络则主要研究系统之间的通信。互联网的兴起,使得这两个领域开始融合,** 现在我们必须考虑,如何开发在互联网环境中使用的软件。**
AWeiLoveAndroid
2018/09/03
3.2K0
深入理解什么是RESTful API ?
理解RESTful架构
越来越多的人开始意识到,网站即软件,而且是一种新型的软件。 这种"互联网软件"采用客户端/服务器模式,建立在分布式体系上,通过互联网通信,具有高延时(high latency)、高并发等特点。 网站开
非著名程序员
2018/02/08
5390
理解RESTful架构
前端要知道的RESTful API架构风格
前端程序员在开发完页面后总是要对接口的,跟后端联调有时候还占用蛮大的时间的,那么你了解你和后端对的接口都是什么风格吗,你们公司接口设计的如何,你使用愉快吗?自己在写Node服务时你遇到如何定义好接口的问题吗?下面介绍一种API架构风格,也是目前主流的API设计风格,你或许一直在使用。
张张
2019/12/27
9270
restful api接口规范和服务调用的区别_rest接口规范
网络应用程序,分为前端和后端两个部分。当前的发展趋势,就是前端设备层出不穷(手机、平板、桌面电脑、其他专用设备…)。因此,必须有一种统一的机制,方便不同的前端设备与后端进行通信。这导致API构架的流行,甚至出现”APIFirst”的设计思想。RESTful API是目前比较成熟的一套互联网应用程序的API设计理论。
全栈程序员站长
2022/10/01
1.8K0
如何给老婆解释什么是Restful
果不其然,看着看着,她又对我发难了,“Restful是什么呀,老公?是restaurant的形容词吗,突然就觉得好饿了啊......”
Java3y
2019/09/24
4850
如何给老婆解释什么是Restful
理解RESTFul和SOA
RESTFul基于HTTP协议,是一种明确构建在客户端/服务端体系结构上的一种风格, rest是Representational State Transfer的缩写
yaphetsfang
2020/07/30
8640
RESTful 架构到底是什么?
REST这个词,是Roy Thomas Fielding在他2000年的博士论文中提出的。
JavaEdge
2021/10/18
6250
我所理解的RESTful Web API [设计篇]
《我所理解的RESTful Web API [Web标准篇]》Web服务已经成为了异质系统之间的互联与集成的主要手段,在过去一段不短的时间里,Web服务几乎清一水地采用SOAP来构建。构建REST风格的Web服务是最近两三年风行的潮流,所以很多人以为REST是一个事物。而事实却是:REST自其诞生之日起到现在(2014年)已经有14年了,它为什么叫这么一个“奇怪”的名字呢? 目录 一、为什么叫这个“奇怪”的名字?二、采用URI标识资源 二、采用URI标识资源 三、使
蒋金楠
2018/01/15
1K0
我所理解的RESTful Web API [设计篇]
RESTful 架构以及 RESTful API开发
在周三的测试运维试听课程中,芒果给大家介绍了RESTful架构以及RESTful API开发-Django REST Framework,这里我们来做个小总结。
TestOps
2022/04/07
8780
RESTful 架构以及 RESTful API开发
RESTful入门概述
RESTful(Representational State Transfer)表述性状态转移,就是目前最流行的一种互联网软件架构。它结构清晰、符合标准、易于理解、扩展方便,所以正得到越来越多网站的采用。
爱笑的架构师
2020/09/24
2020
RESTful
HTTPS为接口的安全提供了保障,可以有效防止通信被窃听和篡改,可以通过 cerbot等工具。
仇诺伊
2020/04/23
7610
RESTful
接口测试概念之RESTful​ API
接口测试和开发中,我们常常会听到一个概念:restful风格、RESTful API,这些概念到底是什么呢?
吾非同
2020/10/23
7600
RESTful API,以及如何使用它构建 web 应用程序。
RESTful API是一种基于REST(Representational State Transfer)架构风格的API(Application Programming Interface),它采用HTTP协议中的GET、POST、PUT、DELETE等方法,对资源进行操作。RESTful API的核心思想是以URL为资源的唯一标识符,通过HTTP协议中的动词方法对资源进行操作。
人不走空
2024/02/20
2940
相关推荐
2020-5-10-RESTfulAPI中能否使用query string
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
查看详情【社区公告】 技术创作特训营有奖征文