用Chrome开发者工具做JavaScript性能分析

388 查看

英文原文:,编译:伯乐在线——王筱

你的网站正常运转。现在我们来让它运转的更快。网站的性能由页面载入速度和代码执行效率决定。一些服务可以让你的网站载入更快,比如压缩JSCDN,但是让代码执行的更快你要做的事情。

代码中很小的改动都可能对性能造成巨大的影响。快速灵活的网站和可怕的“无响应脚本”对话框可能只有几行代码的差别。这篇文章告诉你如何通过用Chrome开发者工具(Chrome Developer Tools)找到这几行关键的代码。

设置一个基线

我们来看一个简单的“颜色排序器”应用,这个应用展示了一个由各种颜色构成的网格,你可以拖拽这些颜色进行混合。每一个点都是一个div标签加上一些让它看起来是圆的的CSS。

用chrome开发者工具进行JS性能分析

生成这些颜色是需要技巧的,所以我借助了”Making Annoying Rainbows in Javascript”

页面载入的很快,但还是花费了一些时间,在渲染之前还闪了一下。是时候对这个页面进行性能分析让它更快了。

在开始做性能优化的时候要设置一个基线,来明确这个页面的速度到底怎样。这个基线可以让你知道自己是否做了优化并帮助你权衡利弊。在这片文章里我们要使用chrome开发者工具

性能分析器(profiler)是chrome开发者工具的一部分,点击小扳手下面的工具菜单就可以打开它。Firebug也有一些性能评测工具,但是webkit内核的浏览器(chrome和safari)在对代码进行性能分析和展示时间线方面是最棒的。Chrome还提供一种很棒的事件跟踪工具,叫做 speed tracer

在时间线(timeline)标签下开始记录,载入页面然后停止记录,这样就设置了一个基线。(打开chrome开发者工具,点击“时间线”标签,然后点击窗口底部圆形的黑色“记录”图标开始记录)。chrome是很智能的,只有页面开始载入的时候才会开始记录。我记录了三次然后取了平均值,以防我的电脑在第一次测试的时候运行的很慢。

用chrome开发者工具进行JS性能分析

我的平均基线,也就是从第一个请求到页面全部渲染结束所花费的时间是1.25秒。这个时间不是太长,但是对于这样一个小的页面来说也不算好。

我想让代码执行的更快,但是我并不知道是什么让它慢下来的。性能分析器(profiler)帮助我找到原因。

 

创建一个Profile

时间线(timeline)告诉我们代码运行花费的时间,但是并没有帮助我们知道代码运行的时候发生了什么。我们可以做一些改动然后不断的测每次代码运行的时间,但这是盲目的。profiles给我们提供了更好的方法。profiler告诉我们哪些函数的执行占用了大部分时间。让我们切换到chrome开发者工具的“Profiles”标签页开始性能测试,这里一共提供了三种类型的性能测试。

1、      javascript cpu 性能测试

显示javascript占用了多少CPU

2、      css选择器性能测试

显示处理CSS选择器占用的CPU

3、      堆栈快照

显示javascript对象的内存占用情况

我们想要javascript代码执行的更快,所以我们进行CPU性能测试。我们开始性能测试,刷新页面然后停止。

用chrome开发者工具进行JS性能分析

通过性能分析首先知道很多函数在执行。“颜色排序器”使用了jQuery和jQuery  UI,来处理些管理插件和解析表达式之类的事情。我发现列表最顶端的是decimalToHex和makeColorSorter两个函数。这两个函数占用了CPU13.2%的时间,这是做优化的好地方。

我们可以点击函数调用旁边的“下一个”箭头来查看完整的函数调用堆栈。展开后,可以看到decimalToHex是被makeColorSorter调用的,makeColorSorter是通过$(document).ready调用的。

代码如下

弄清楚这两个函数是哪里调用的,也就弄清楚了让颜色可以排序并不是最大的性能问题。通常情况下性能问题都是由多余的排序操作造成的,但是在我的代码中相比与排序增加DOM元素花费了更多时间。

我想要让这些函数执行的更快,但是首先我想要将我的改动区隔开。在页面载入过程中会发生很多事情,我不想要这些影响到我的性能分析。

 

区隔问题

我做了第二个版本,这个版本中“颜色排序器”在我点击按钮之后才载入,而不是在document ready的时候载入。这就把文档载入的过程分离出去,让我可以只对颜色分类进行性能测试。调完性能之后我可以立刻改回去。

让我们调用新的函数testColorSorter并把它绑定到一个可点击的按钮上。

在我们进行性能分析之前改变应用可能导致意外的结果。这个改动看起来很安全,但是我还是要重新运行性能检测器来看看我是不是无意中改变了什么。我会开始一次新的性能分析,点击应用中的按钮然后停止。

用chrome开发者工具进行JS性能分析

我首先注意到decimalToHex函数的载入只占用了4.23%的时间。这是代码执行花费时间最多的地方。我们创建一个新的基线来看看这个方案对代码有多大的优化。

用chrome开发者工具进行JS性能分析

有些事件在我点击按钮之前有触发了,但是我只关注从我点击鼠标到浏览器渲染“颜色排序器”花费的时间。鼠标在390毫秒时点击,渲染事件在726毫秒处被触发。726减去390得到我的基线336毫秒。和第一个基线一样我重复了3次来取平均值。

这时,我知道如何获得并且得到了代码确切的运行时间,我们已经准备好开始解决问题了。

 

让代码更高效

性能分析器只告诉我们哪个函数造成的问题,所以我们要查看下函数的源码来了解函数做了些什么。

“颜色排序器”中的每一个颜色点都有一个16进制的色彩值,例如#86F01B和#2345FE.这些值表示一种颜色中红,绿,蓝三原色各自的数值。例如的背景色是#2456FE,代表红色的值是36,绿色的值是86,蓝色的是254,每一个数值必须是0到255之间的。

decimalToHex函数把这用RGB值表示的颜色转化为页面中我们使用的16进制颜色。这个函数十分的简单,但是我还是留下了一个可以去掉的调试代码console.log在那里。

decimalToHex 函数还在数字之前加上了补位。这是很重要的一点,因为有些10进制数字对应的是1个16进制数字。比如十进制中的10对应着16进制中的C,但是在CSS中需要一个两位数。为了让这个进制换算更快速,我们让这段代码不是那么泛化。我知道每个需要补位的数字长度都为1,所以我们可以这样重写这个函数。