减小改动
“颜色排序器”中的多彩颜色是用过正弦曲线生成的。在光谱中设置一个中心点,然后以一定的偏移来创建这个曲线。这就把颜色变成了一个“彩虹模型”。我们还可以通过改变红绿蓝三原色的使用频率来改变颜色。
function makeColorSorter(frequency1, frequency2, frequency3, phase1, phase2, phase3, center, width, len) { for (var i = 0; i < len; ++i) { var red = Math.floor(Math.sin(frequency1 * i + phase1) * width + center); var green = Math.floor(Math.sin(frequency2 * i + phase2) * width + center); var blue = Math.floor(Math.sin(frequency3 * i + phase3) * width + center); console.log('red: ' + decimalToHex(red)); console.log('green: ' + decimalToHex(green)); console.log('blue: ' + decimalToHex(blue)); var div = $('<div class="colorBlock"></div>'); div.css('background-color', '#' + decimalToHex(red) + decimalToHex(green) + decimalToHex(blue)); $('#colors').append(div); } }
我们要去掉console.log函数。这些调用非常的糟糕,因为每次执行都会调用decimalToHex函数,这意味着decimalToHex函数会被多调用2倍的次数。这个函数大幅度的改变了DOM结构。每次循环,都向id为colors的div中添加一个新的div。这就让我怀疑这就是e.extend.mergefunction做的事情。用性能分析器做一个小实验就可以搞清楚。
我想要一次把所有的div添加进去,而不是在每个循环中添加一个新的div。创建一个变量来存储数据,然后在最后一次性添加进去。
function makeColorSorter(frequency1, frequency2, frequency3, phase1, phase2, phase3, center, width, len) { var colors = ""; for (var i = 0; i < len; ++i) { var red = Math.floor(Math.sin(frequency1 * i + phase1) * width + center); var green = Math.floor(Math.sin(frequency2 * i + phase2) * width + center); var blue = Math.floor(Math.sin(frequency3 * i + phase3) * width + center); colors += '<div class="colorBlock" style="background-color: #' + decimalToHex(red) + decimalToHex(green) + decimalToHex(blue) + '"></div>'; } $('#colors').append(colors); }
这个小改动意味着DOM只在添加所有div的时候做一次改变。用时间线进行测试,我们发现从点击到渲染花费了31毫秒。这个dom变动,使得第四个版本的运行时间降低了86%。我可以再次打开性能分析器(profiler),发现e.extend.merge函数占用了很少的时间,在列表中已经看不到它了。
我们还可以完全移除decimalToHex函数让代码更快一点。因为CSS支持RGB颜色,所以我们不需要把他们转换到16进制。现在我们可以这样写makeColorSorter函数。
function makeColorSorter(frequency1, frequency2, frequency3, phase1, phase2, phase3, center, width, len) { var colors = ""; for (var i = 0; i < len; ++i) { var red = Math.floor(Math.sin(frequency1 * i + phase1) * width + center); var green = Math.floor(Math.sin(frequency2 * i + phase2) * width + center); var blue = Math.floor(Math.sin(frequency3 * i + phase3) * width + center); colors += '<div class="colorBlock" style="background-color: rgb(' + red + ',' + green + ',' + blue + ')"></div>'; } $('#colors').append(colors); }
第五个版本的执行只用了26毫秒而且代码行数从28行减少到18行。
在你的应用中进行Javascript性能分析
实际工作中的应用要比“颜色排序器”复杂的多,但是做性能分析要遵循同样的基本原则
1、 设置一个基线,这样你就知道你是从何处开始的。
2、 把问题从应用的其他代码隔离出来。
3、 在一个可控的环境下进行优化,频繁的使用时间线(timelines)和性能分析器(profiles)
还有一些性能优化的准则
1、 从最慢的部分开始,这样在时间优化上可以得到最大的提升。
2、 控制环境。如果你换了电脑或者做了任何大的改动,都要设置新的基线。
3、 多次分析以防你电脑的异常导致得到不正确的结果。
每个人都想要他的网站更快,你必须开发新的功能,但是新的功能通常会让网站更慢。所以花费时间来做性能优化是有价值的。
性能分析和优化使得最终版颜色分类器的执行时间减少了92%。你的网站可以变快多少?