[关闭]
@ghostcdy 2016-01-29T10:17:56.000000Z 字数 2593 阅读 351

性能打点引发的命案

未分类


问题:

我们常用打点计时的方式来统计每个过程的耗时。然而,并不是我们想象的那么简单。
基哥说:打点计时应该放在setTimeout中,因为还有事情没做完。
好像是这么个理,but,测试结果出乎预料。

实验:

PC采用chrome浏览器,移动端采用iPhone 6 plus + Fiddler + willow代理 + Rosin(log查看)

A:渲染10000个节点测试代码:

  1. <!doctype html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>A</title>
  6. </head>
  7. <body>
  8. <div id="inner"></div>
  9. <script>
  10. console.time('A');
  11. render(10000);
  12. console.timeEnd('A');
  13. //渲染节点
  14. function render(max){
  15. var a = '';
  16. for (var i = 0; i < max; i++) {
  17. a += '<li>' + i + '</li>';
  18. }
  19. document.getElementById('inner').innerHTML = '<ul>' + a + '</ul>';
  20. }
  21. </script>
  22. </body>
  23. </html>

其中一次测试结果
PC:16.949ms
iPhone:59ms
ps:好像挺快的。
基哥说,这个打点不对,应该放在setTimeout里。

B:打点放在setTimeout里

  1. var time = Number(new Date());
  2. render(10000);
  3. setTimeout(function(){
  4. console.log(Number(new Date()) - time + 'ms');
  5. },0);
  6. //渲染节点
  7. function render(max){
  8. var a = '';
  9. for (var i = 0; i < max; i++) {
  10. a += '<li>' + i + '</li>';
  11. }
  12. document.getElementById('inner').innerHTML = '<ul>' + a + '</ul>';
  13. }

其中一次测试结果
PC:504ms
iPhone:5593ms
和A对比差距如此巨大,发生了什么?

C:寻找渲染到setTimeout中间做了什么,让渲染异步试试

  1. setTimeout(function(){
  2. var time = Number(new Date());
  3. render(10000);
  4. setTimeout(function(){
  5. console.log(Number(new Date()) - time + 'ms');
  6. },0);
  7. },0);
  8. //渲染节点
  9. function render(max){
  10. var a = '';
  11. for (var i = 0; i < max; i++) {
  12. a += '<li>' + i + '</li>';
  13. }
  14. document.getElementById('inner').innerHTML = '<ul>' + a + '</ul>';
  15. }

其中一次测试结果
PC:203ms
iPhone:5943ms

D:setTimeout做了什么?

直接测试setTimeout:

  1. var time = Number(new Date());
  2. setTimeout(function(){
  3. console.log(Number(new Date()) - time + 'ms');
  4. },0);

其中一次测试结果
PC:255ms
iPhone:14ms

E: 关闭控制台,关闭插件换IE试试

  1. var time = Number(new Date());
  2. setTimeout(function(){
  3. alert(Number(new Date()) - time + 'ms');
  4. },0);

其中一次测试结果
PC:13ms
iPhone:14ms
结论:确实控制台在页面初始化后做了些事情。

F: 再次重新测试渲染10000个节点

  1. var time = Number(new Date());
  2. render(10000);
  3. setTimeout(function(){
  4. alert(Number(new Date()) - time + 'ms');
  5. },0);
  6. //渲染节点
  7. function render(max){
  8. var a = '';
  9. for (var i = 0; i < max; i++) {
  10. a += '<li>' + i + '</li>';
  11. }
  12. document.getElementById('inner').innerHTML = '<ul>' + a + '</ul>';
  13. }

其中一次测试结果
PC:134ms
iPhone:8156ms

G:测试页面加载的过程

  1. var time = [Number(new Date())];
  2. //A位置
  3. //render(10000);
  4. window.onload = function(){
  5. time[1] = Number(new Date());
  6. //B位置
  7. setTimeout(function(){
  8. //C位置
  9. time[5] = Number(new Date());
  10. print();
  11. },0);
  12. };
  13. time[2] = Number(new Date());
  14. //D位置
  15. setTimeout(function(){
  16. //E位置
  17. time[3] = Number(new Date());
  18. },0);
  19. time[4] = Number(new Date());
  20. function print(){
  21. var t = '', len = time.length;
  22. for(var i = 1; i < len; i++){
  23. t += '【' + i + '】:' + (time[i] - time[0]) + ';';
  24. }
  25. alert(t);
  26. }
  27. //渲染节点
  28. function render(max){
  29. var a = '';
  30. for (var i = 0; i < max; i++) {
  31. a += '<li>' + i + '</li>';
  32. }
  33. document.getElementById('inner').innerHTML = '<ul>' + a + '</ul>';
  34. }

其中一次结果:

终端 1:onload 2 3:setTimeout 4 5:onload中的setTimeout
IE 13 0 23 0 23
Chrome 1 0 2 0 2
iPhone 2 0 14 0 14

IE中不同位置渲染10000个节点:

IE中位置 1:onload 2 3:setTimeout 4 5:onload中的setTimeout
A 121 62 131 63 131
B 12 0 129 0 129
C 12 0 22 0 84
D 121 0 132 60 132
E 11 0 70 0 70

渲染过程是密集型运算,会阻塞setTimeout。

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注