通过Timeline描述性能 - acelan86/chromeDevTools GitHub Wiki
[原文地址]https://developers.google.com/chrome-developer-tools/docs/timeline?hl=zh-CN
Timeline面板让你可以记录和分析你的应用运行过程中的的所有活动。它是开始理解研究你的应用的性能问题的最好的地方。
Timeline有三个主要的区块:最顶上的一个概览区块,一个记录视图区域,和一个工具栏。
- 要开始或停止记录,点击Record按钮切换(见创建一份记录)。
- 点击Clear recording按钮从Timeline中清除记录。
- Glue async events模式让你更简单的将异步时间与他们的原因相关联(见关于嵌套事件)
- 你可以根据他们的类型或者持续时间来过滤Timeline中的记录(见过滤和查找记录)
在一份记录中,每个时间对应一个记录被以“瀑布流”方式添加到记录视图中。记录被分成下面四种基本组中的一种:Loading,Scripting,Rendering,以及Painting。这些记录像下面一样分色:
例如,下面是一份HTML页面被加载到Chrome中的记录。第一条记录(Send Request)是Chrome为这个页面发起的HTTP请求,紧随着一个Receive Response记录(对应的HTTP响应),一些Receive Data记录(实际的页面数据),还有一个Finish Loading记录。需要查看一个Timeline记录的完全的事件列表和他们的描述,请见Timeline事件说明。
当你把鼠标放在一条Timeline记录上的时候,会出现一个含有相关联事件的详细信息的弹出层。例如,下面的截图显示了一个和一个图片资源相关连的Finish Loading记录的详细信息。Timeline事件说明解释了每一种记录类型所包含的详细信息。
除了记录视图的细节外,你可以用下面三种模式中的任意一种查看记录:
- Events模式按事件分类展示了了所有记录的事件
- Frames模式展示了页面的渲染性能
- Memory模式展示了内存随时间流逝的使用量
Events模式提供了一个在记录过程中被捕获的所有事件的概览,通过他们的类型来组织。你一眼就可以看出你的应用在哪里耗费了最多的时间,是在哪个任务中。每一个水平条的长度与事件发生到完成所用的事件相关。
当你从Events视图中选择一段时间(见在Timeline区块中放大),记录视图只显示这段时间中的这些记录。
Frames模式提供了洞察你的应用渲染性能的方案。一个“frame”体现了浏览器渲染内容的一个单独帧所需要做的工作,包括display-run Javascript,handle events,update DOM和change styles,layout与paint。目的是为了你的应用运行在每秒60帧(FPS),与大多数(并不是所有)视屏播放的60Hz刷新率一致的目标。因此,你的应用接近为每帧准备16.6ms(1000ms / 60)的时间。
贯穿Frames视图的水平线显示了60FPS和30FPS的帧率目标。一个帧的高度与它渲染这这帧所耗费的实现相应。每一帧中填充的颜色标示了每种类型的任务耗费的时间百分比。
渲染一个帧的时间显示在Records视图的顶部。如果把鼠标放在时间上面,会显示关于这帧的额外的信息,包含每一种类型的任务耗费的时间,CPU时间,以及计算得到的FPS。
见Timeline demo: Diagnosing and fixing forced synchronous layout使用Frames模式的示范。
你可能已经注意到了一个帧中浅灰色或者空白的区域(挖空)。这些区域表示的是:
- 无法通过DevTools量化的活动
- 显示刷新循环中的空闲时间
下面的记录中的帧显示了无法量化的活动和空闲时间。
选中帧范围的平均帧率和它的标准偏差显示在Timeline面板底部。如果你把鼠标放置在平均帧率的上面,那么将浮现一个弹出层,上面显示了关于这些选中帧的附加信息:
- Selected range -- 选中的时间范围,和这个选中区域的帧数。
- Minimum Time -- 选中帧的最小时间,括号里为与之相对应的帧率。
- Average Time -- 选中帧的平均时间,括号里为与之相对应的帧率。
- Maximum Time -- 选中帧的最大时间,括号里为与之相对应的帧速率。
- Standard Deviation -- 计算的到不同平均时间的总和。
- Time by category -- 根据类型分色统计的各种类型处理花费的时间总和。
Memory视图显示了经过的时间内你的应用的内存使用,以及保持在内存中的文档,DOM节点,和事件监听器数量(也就是,没有被垃圾回收的)。
Memory模式不能准确的告诉你什么东西发生了内存泄漏,但它能帮助你定位应用中的什么可能导致内存泄漏。之后你就可以使用堆查看器来定位某个引起内存泄漏的特殊代码。
要创建一份记录,需要先开始记录回话,与你的应用进行交互,然后停止记录。它帮助你增加对你想要记录的活动的类型的了解 - 例如,页面加载时间,图片列表的滚动性能等等。
-
打开你想记录的页面
-
打开Timeline面板并且通过下面的任一操作开始记录::
- 点击面板底部圆形的记录按钮
- 按Ctrl+E或者Cmd+E(MAC)快捷键 记录过程中记录按钮变成红色。
-
做一些必要的用户交互用于记录期望的行为。
-
点击红色的记录按钮停止记录,或者重复上面的快捷键
一个普遍的任务是记录页面从初始化网络请求开始的加载。在这个情形下,键盘快捷键非常有用,它能帮你快速开始一个记录,重载页面,和停止记录。
- 在新标签页或者新窗口中打开任意页面Open any web page in a new tab or window.
- 打开Timeline面板并使用Cmd+E或者Ctrl+E开始记录。Open the Timeline and press Cmd+E (Mac) or Ctrl+E (Windows/Linux) to start recording.
- 使用Cmd+R或Ctrl+R重载页面。Quickly press Cmd+R or Ctrl+R to reload the browser page.
- 当页面完成加载的时候停止记录(参考红色的标记线)
你的记录应该看起来像下面这样。第一个记录(Send Request)是Chrome对这个页面的HTTP请求,然后是对于于HTTP请求的响应接收,接下来是一个或者多个接收数据记录,一个完成加载记录和一个解析HTML的记录。
每个记录类型的细节见Timeline事件说明。
这里有一些关于创建记录的小贴士:
- 保持记录的时间越短越好。越短的记录越容易分析。
- 避免不必要的交互。试着避免那些跟你想要记录和分析活动不相关的交互(鼠标点击,网络加载,等等)。例如,如果你想要记录当你点击“Login”按钮后的事件,就不要滚动页面,加载一个图片等等。
- 禁用浏览器缓存。当记录网络操作时,在DevTools设置面板中禁用浏览器缓存是一个好主意。
- 禁用扩展。Chrom扩展会添加无关的记录到你的应用的Timeline记录中。你可以这么做:
- 用隐私模式打开Chrome窗口
- 为测试创建一个新的Chrome用户配置文件。
这部分提供了一些小贴士帮你分析Timeline记录。
当你把鼠标放置在Timline的某条记录上时,会弹出一个层,上面显示了关于该事件的额外细节。
某些细节展现在所有类型的事件中,比如Duration和CPU Time,而有些只体现在某些事件类型中。要了解每种类型的记录包含的详细信息,请看Timeline事件说明。
当你把鼠标放置在一个Paint记录上时,DevTools会用一个蓝色的虚拟透明矩形高亮屏幕上的区域,就像下面这样。
当DOMContentLoaded和Load事件被浏览器触发的时候,Timeline通过一条蓝色和红色线标注每一个记录。DOMContentLoaded事件在所有的页面DOM内容被加载和解析完毕后触发,Load事件在所有的文档资源(图片和css文件,等等)完全加载后触发。
布局是一种通过chrome计算页面所有元素位置和大小的操作。一般的,chrome对应用中更新的CSS或DOM的布局处理是“懒惰的”。这允许chrome批量的处理样式和布局改变而不是立刻响应每一个要求。然而,一个应用能够通过请求某些布局依赖元素的属性值(比如element.offsetWidth
),来强制chrome立即处理布局。这样的情况叫做“强制同步布局”,如果太过频繁的为一个很大的DOM树做这样的重复操作,它可能成为一个很大的性能瓶颈。
当你的应用触发一个强制异步布局时Timeline会定位出来,并且使用一个黄色的警告图标()标识记录。当你把鼠标放到这个记录上时,会弹出一个层包含一个所提供代码的跟踪栈。
如果一个记录包含一个强制布局的子记录,父亲记录会被用一个稍微变暗的黄色图标标记。展开父亲记录可以定位到发生强制布局的子记录。
查看强制同步布局的实例来掌握检测和修复这种类型的性能问题。
Events在Timeline记录中有时候时嵌套的。你展开“parent”事件来查看它的嵌套“child”事件。以下是两个引起Timeline事件嵌套的原因:
- 在一个事件处理过程中另一个同步事件发生。每一个事件内部生成两个原子事件。一个作为开始另一个作为结束,它们转换成一个单独的“continous”事件。其他发生在两个原子事件之间的事件变成外部事件的儿子。
- 当glue模式打开的时候一个异步事件被作为另外一个事件的结果触发。
注意:Glue模式在Frames模式中自动禁用
下面的截图显示了一个嵌套同步事件的例子。在这个情形下,Chrome在解析某个HTML的过程中发现有一些外部资源需要加载。这些请求在chrome完成解析之前被创建,所有Send Request事件被作为parse HTML事件的儿子显示。
应用中的许多事件都是异步操作的结果。一个图片资源页面的加载过程导致Send Request,然后是Receive Response事件,一个或者多个Receive Date loading事件,和一个Finish Loading事件。有时,异步事件被他们花费的太长时间分割开而使得他们之间更难相互关联。
Timeline面板底部的Glue asynchronous events to causes toggle按钮使得异步事件以触发他们的事件的子节点的方式嵌套展现。
Timeline条被通过下面方式分色:
- 首先,最暗的部分体现了父亲事件和所有的它的同步子节点耗费的时间。
- 然后,较浅的颜色体现了这个时间和所有它的同步子节点耗费的CPU时间。这个和上面glue模式关闭,且事件没有异步子节点的情况一样。
- 灰白的条提现了从开始第一个异步事件到它的最后一个异步儿子节点完成的时间(只有在glue模式下事件有异步儿子节点时可见)
当你把鼠标放在父亲记录上时,下面的信息会被展现:
- Duration 匹配条从事件开始到它的最后一个儿子事件结束的长度.
- Self Time 事件排除它的所有儿子事件后耗费的时间
- CPU time 匹配CPU条
你可以通过类型过滤记录的显示(只显示loading事件,比如),或者只显示长于或者等于1毫秒或者15毫秒的记录。
当Timeline获取焦点的时候,你也可以使用Ctrl+F或者Cmd+F,输入具体字符串来搜索记录。你可以选择性的过滤显示那些包含了搜索串的记录。
为了更容易分析记录,你可以在timeline总览的一个区域“缩小”显示,在记录视图中减小时间规模。
要缩小一个Timeline区块,像下面这么做:
- 在总览区域,用你的鼠标拖出一个区块。
- 在标尺区域调整灰色滑块
这里有一些Timeline选中项操作的小贴士:
- 通过拖拽两个滑动条之间的区域来"Scrub"当前选中区域的记录.
-
触摸板用户:
- 两只手指向左或者向右扫动来移动当前的Timeline选区.
- 两只手指向上或者向下扫动来扩展或者收缩当前Timeline选区。
- 当鼠标放置在一个Timeline选取中时,上下滚动鼠标滚轮也能扩展或者收缩当前选区。
你可以保存一个Timeline记录为json文件,之后可以在Timeline中打开它。
- 在Timeline内右键或者Ctrl+click(Mac—),选择Save Timeline Data…菜单, 或者使用Ctrl+S快捷键。
- 选择一个路径保存文件并点击保存。
- 在Timeline中右键或者Ctrl+click,并选择Load Timeline Data...菜单, 或者使用Ctrl+O快捷键
- 找到JSON文件并点击打开。
应用可以添加自己的事件到Timeline记录中。你可以使用console.timeStamp()
方法添加一个原子事件到记录中去,或者使用console.time()
和console.timeEnd()
方法创建一个代码执行过程中的时间范围。例如,在下面的记录中,console.timeStamp()
用于显示一个“Adding result”事件。详见使用Console标记Timeline。
你可以在Timeline记录中通过开启DevTools设置选项中的Show CPU activity on the ruler来查看CPU活动。
当这个选项时开启的时候,浅灰条在Timeline记录中显示,标识了CPU忙的情况。在CPU活动期间把鼠标放在CPU条上会高亮Timeline区域(就像下面显示的一样)。CPU条的长度通常是它下面的Timeline中所有(高亮的)事件的总和。如果不匹配的话,可能是由于下面的某个原因:
- 页面查看过程中其他页面在相同的线程中运行(例如,两个标签页打开相同的网站,其中一个通过
setTimeout()
调用在执行某个事情)。 - 无法量化的活动。
这部分列出并且说明了记录过程中产生的个别的记录类型和他们的属性,通过类型组织。
某些细节在所有类型的事件中都存在,而某些只应用于某些时间类型。这部分列出了不同事件类型的公共属性。某些事件类型的特殊属性列举子后面的事件说明汇总。
- Aggregated time - 在嵌套事件中,每一个事件分类耗费的时间。
- Call Stack - 子事件中,每一个事件分类耗费的事件。
- CPU time - 事件记录耗费了多少CPU时间。
- Details - 事件的其他细节。
- Duration (at time-stamp) - 事件的子事件全部完成花费了多少时间;时间戳是事件发生的时刻,相对于记录开始的时间。
- Self time - 事件排除子事件外耗费的事件。
- Used Heap Size -事件记录过程中应用消耗的内存总量,+/-的增量是自上次取样后heap size的变化量。
这部分列出了属于Loading分类的事件和他们的属性
事件 | 描述 |
Parse HTML | Chrome执行HTML解析算法 |
Finish Loading | 一个网络请求完成. |
Receive Data | 一个请求的数据接收. 会有一个或者多个接收数据事件 |
Receive Response | 一个HTTP请求的响应初始化 |
Send Request | 一个网络请求被发出 |
- Resource - 请求资源的URL
- Preview - 请求资源的预览 (只有图片).
- Request Method - 请求所用的HTTP方法(比如GET或者POST).
- Status Code - HTTP响应状态码
- MIME Type - 请求资源的MIME类型
- Encoded Data Length - 请求资源的字节长度.
这部分列出了属于Scripting分类的事件和他们的属性
事件 | 描述 |
Animation Frame Fired | 一个计划中的动画帧触发,它的回调方法被调用 |
Cancel Animation Frame | 一个计划中的动画帧被取消 |
GC Event | 垃圾回收发生 |
DOMContentLoaded | 浏览器的DOMContentLoaded触发,当页面上是所有的DOM内容被加载并解析完成后这个事件被触发。 |
Evaluate Script | 脚本执行 |
Event | JavaScript事件(例如 "mousedown", 或者 "key"). |
Function Call | 顶级JavaScirpt方法调用(只在浏览器进入JavaScript引擎时显示). |
Install Timer | 通过`setInterval()`或`setTimeout()`创建一个定时器. |
Request Animation Frame | `requestAnimationFrame()`调用, 计划了一个新的帧 |
Remove Timer | 之前创建的计时器被清除 |
Time | 脚本调用`console.time()` |
Time End | 脚本调用`console.timeEnd()` |
Timer Fired | 通过`setInterval()`或`setTimeout()`计划的一个计时器被触发. |
XHR Ready State Change | XMLHTTPRequest的readystate改变 |
XHR Load | XMLHTTPRequest完成加载 |
- Timer ID - 计时器ID
- Timeout - 计时器指定的timeout
- Repeats - bool值指定了计时器是否重复
- Function Call 被调用的function
这部分列出了属于Rendering分类的事件和他们的属性
事件 | 描述 |
Invalidate layout | 因为DOM改变而被作废的页面布局 |
Layout | 执行页面布局 |
Recalculate style | Chrome重新计算元素样式 |
Scroll | 嵌套视图被滚动 |
- Layout invalidated - 布局记录专用,引起布局失效的代码跟踪栈
- Nodes that need layout - 布局记录专用, 重新布局开始之前标记需要重新布局的节点的数目。一般这些节点因为开发者的代码而失效,附加了一个向上到重布局树根节点的路径。
- Layout tree size - 布局记录专用, 在重布局树的根节点(Chrome开始重新布局的那个节点)下的节点数目。
- Layout scope - 可能的值有"Partial" (重布局的边界时DOM的某个部分) 或者"Whole document".
- Elements affected - Recalculate style记录专有, 样式重计算影响的节点数目。
- Styles invalidated - Recalculate style记录专有, 提供引起样式失效的代码的跟踪栈
这部分列出了属于Rendering分类的事件和他们的属性
事件 | 描述 |
Composite Layers | Chrome的渲染引擎混合图片布局 |
Image Decode | 图片资源被解码. |
Image Resize | 图片自身尺寸被重新设置 |
Paint | 混合布局被绘制到一个显示区域。把鼠标放置到一个Paint记录中会高亮被更新的显示区域 |
- Location - Paint事件专有, 绘制矩形的xy坐标
- Dimensions - Paint事件专有, 绘制区域的宽高。