Skip to content

浏览器阻塞探究 #2

@ericdum

Description

@ericdum

上周发现虾米音乐的js都放在head里面,心想不是会卡进程么?和虾米音乐的同学聊了之后发现他们认为这个网站功能和js密切相关,所以不希望让用户看到不可用的页面。

根据产品选择技术可能无可厚非,其他优化方案这里不谈,我就想看看卡渲染进程到底是怎么卡的。

所以有了以下思路,

  1. 在head中,用while去无限循环跑3秒。
  2. 进入body,输出
  3. 再用同样的方式跑3秒,输出
  4. 外调一个3秒网络延时的js,同时执行其他js
  5. 同时外调一个5秒、10秒网络延时的js,同时执行其他js

期望:

  1. 无限循环js卡住进程导致白屏
  2. 上一步结束后输出
  3. body中的无限循环再次卡住进程,证明head、body无异
  4. 网络进程依次加载js、执行js
  5. 总执行时间3+3+3+5+10 = 24秒

循环代码:

    var time1 = (new Date()).getTime();
    while(((new Date()).getTime()-time1) < 3000);

加载外部js,并即时的代码:

    <script>
        var time = (new Date()).getTime();
        var intv = setInterval(function(){ timer3.innerText = ((new Date()).getTime()-time)/1000 }, 50);
    </script>
    <script onload="clearInterval(intv);" src="http://mujiang.info/delayload/3s.php"></script>

开始测试

查看测试、代码: http://cdpn.io/ABnmI

结果:

qq20131024-1

safari和chrome都类似。但是呈现的顺序不一样。chrome等到两段卡3秒的循环都结束了才呈现。但safari第一段js结束就开始呈现了。

可以看到外调js种,5秒、10秒的测试之用了7秒左右的时间。再去查看timeline,原来第一个三秒的js在请求的同时就开始请求5秒、10秒的js了。

所以来看看完成的期望:

  1. 无限循环js卡住进程导致白屏
  2. body中的无限循环再次卡住进程,证明head、body无异

没完成的是:

  1. 上一步结束后输出 —— 浏览器结果不一致
  2. 网络进程依次加载js、执行js —— 同时加载
  3. 总执行时间3+3+3+5+10 = 24秒 —— 总时间位3+3+3+7 = 16秒,不过这是好事。

至此,又有了几个新的思考:

  1. 既然所有js同时加载,为什么不在一开头就加载呢?(前面有6秒等候时间)。
  2. HTML5 的 async属性能不能防止网络阻塞,执行顺序和加载顺序一样吗。
  3. HTML4 的 defer属性能不能防止执行阻塞。

回答思考

这是刚开在chrome中的Network视图,看着3个js加载之前长长的空白,不觉得蛋微微有点疼么?浪费可耻啊!那6秒都干了些什么!

qq20131024-2

解决方案很简单,很容易观察出来第一段js加载的时候,其他的js就都跟着加载了。

那么我在head最开始就加一段js会怎么样呢?

效果:http://mujiang.info/test/browserjam/index2.php

可以看到执行时间被压到了10秒,快乐整整6秒,就是刚才前面卡的6秒。(口水都流出来了)

Network: (多出来的js就是刚加的js)

qq20131024-3

至于浏览器同学一次能同时加载多少个文件呢?safari、chrome都是6个。其他浏览器没试。

qq20131024-6

话说加载图片会不会占线程呢?答案是会。总数就是6个。就不给图了

async的问题就更简单了,async加载的js不仅不会阻塞解析,还不会阻塞其他js的执行。

效果:http://mujiang.info/test/browserjam/async.php

asd1

至于defer属性,看了文档说被标记的js会在页面解析(parsing)完成之后执行。按照我的理解,浏览器parsing完之后还有构建DOM、构建render tree、layout和parinting的过程。所以如果真的只是不影响parsing的话,那就能解释结果为什么观察不出结果:http://mujiang.info/test/browserjam/defer.php

总结一下

  1. 大量的代码放在前面会导致“白屏”
  2. 当浏览器遇到第一个script的时候会把所有script都拿来下载。
  3. 同时下载的进程为6个。图片、js共享。
  4. async可以避免阻塞。但是js执行顺序为改变。

本文用到的代码都在这里:
https://github.com/ericdum/mujiang.info/tree/master/test/browserjam

好吧,我偏题了,没测出safari有啥好的,除了渲染更新更快(也蛮好的)。不过这些东西我觉得比safari得自身情况更有意思。safari到底怎么提升了速度过几天在看了。

Metadata

Metadata

Assignees

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions