$(document).ready()会减慢IE的运行速度吗?

4

我一直在与名为Catchpoint的公司合作,解决我们客户端代码指标中的一些不一致性。他们有一些事件触发器,用于测量页面加载过程中的里程碑。他们为我们提供的度量标准是基于IE8。

现在,他们声称JQuery在IE中确定DOM就绪的方式实际上严重影响页面性能,我们应该尽可能避免使用它。我知道JQuery使用doScrollCheck()方法和1毫秒递归setTimeout爆炸对documentElement进行操作,我意识到他们可能有一个有效的主张。

他们说每个$(document).ready()块都会呈指数级别受到影响。

我的问题是,是否有任何统计数据来验证这一说法,如果有,我该如何实施一个IE友好的解决方案而不需要重写JQuery源码以满足我的需求。


请记住,您可以随时深入研究 jQuery源代码 以获取有关此事的一些统计数据... - balexandre
4
他说他知道 doScrollCheck() 方法和 1ms 递归的 setTimeout。如果他没有阅读源代码,他可能不会知道这些内容。 - AlienWebguy
3个回答

3
根据JSperf的测试结果,在所有浏览器中,多个DOM就绪函数确实会明显减慢页面速度,以至于我将重构很多自己的代码以适应这一新发现。当然,IE的速度更慢,但测试结果并不像我希望的那样有信息量,因为即使没有DOM就绪检查,它也要慢得多。从中可以得出的结论是尽可能减少使用这些DOM就绪函数。
Chrome中的结果:
- 单个$(document).ready():734,811 ops/sec - 多个$(document).ready() [4块]:151,989 ops/sec - 没有$(document).ready():208,965,555 ops/sec
IE8中的结果:
- 单个$(document).ready():26,349 ops/sec - 多个$(document).ready() [4块]:5,971 ops/sec - 没有$(document).ready():5,000,159 ops/sec

分析这些指标:

  • 在Chrome中,没有DOM准备检查占DOM准备检查时间的0.35%
  • 在IE中,没有DOM准备检查占DOM准备检查时间的0.53%

仅凭这些数据就可以告诉我们doScrollCheck()函数会严重影响性能

话虽如此:

  • 在Chrome中,DOM准备检查比IE快27.98倍
  • 在Chrome中,进行4次DOM准备检查比IE快25.45倍
  • 在Chrome中,没有DOM准备检查比IE快41.79倍
表面上看,这似乎是无望的 - 但如果你仔细想想,没有DOM准备功能的IE页面正在执行超过500万个操作/秒,而Chrome上的单个DOM准备功能执行不到100万次。这告诉我,如果你设法告诉JQuery使用更友好的doScrollCheck()函数,例如每100ms检查一次documentElement是否可滚动,而不是每1ms,你可能会看到页面加载时间与Chrome更具竞争力。

这个基准测试真正告诉我的是,即使是DOMContentLoaded检查也非常慢 - 没有理由从209万个操作/秒下降到Chrome下的不到100万个操作/秒。

http://jsperf.com/docready/3


2
我不确定这个测试是否真正测试了OP想要测试的内容。您正在测试四个函数调用来设置四个document.ready()调用,而不是一个函数调用来设置一个document.ready()调用。显然,四个函数调用的速度约为一个函数调用的1/4。无论这在实际代码中是否相关取决于单个函数调用开销的速度与整体启动时间的相对重要性。这可能很重要,也可能不重要,具体取决于实际启动代码所需的时间。 - jfriend00
另外,我认为 OP 想知道的是相对于其他知道 DOM 准备就绪的机制,IE 中触发 $(document).ready() 的时间是否较慢,而这不是你在这里测量的。你实际上正在对 $(document).ready() 的调用本身进行基准测试(它仅注册回调函数以稍后调用),而不是基准测试它何时触发并实际调用回调。 - jfriend00
1
他确实提到他想要验证一下“他们说每个$(document).ready()块都会指数级地影响性能。” - AlienWebguy
查看基准测试的最新分析 - 很想听听您的见解。实际上,我对更快的DOM就绪替代方案的真正答案非常好奇。 - AlienWebguy
你实际上在哪里测量到达实际domready回调的时间?我只看到在jsperf中测量注册回调的时间,这不是这个问题更重要的部分。另一方面,我上面的测试测量了从第一个脚本执行到document.ready()触发的时间,这才是我们关心的。我这里实际上没有真正的IE8,所以无法在IE8中运行我的脚本。 - jfriend00
显示剩余4条评论

0

这里有一个脚本,可以测量$(document).ready()触发和代码在body结束时执行的时间(这是您可以操作DOM的最早可能时间)。您可以在任何您想要的浏览器中运行它。页面在这里:http://jsfiddle.net/jfriend00/dLx4L/

我在jsFiddle中完成了这个脚本,以方便、长久和易于共享,但如果您制作一个实现相同技术的独立网页(没有像jsFiddle中那样涉及其他框架),您可能可以做出更准确的测试。无论如何,您应该能够在这里了解如何测量并给出真实数字。


你看过 http://jsperf.com 这个网站吗?它是使用 JavaScript 进行性能比较的更好方式。 - GregL
@GregL - 如果您认为您可以在jsperf中编写此测试,请展示给我们看。我不认为jsPerf允许您比较ready事件的时间。它是用于测量给定JavaScript操作的执行时间,而这不是本问题所涉及的内容。我已经多次使用jsPerf进行其设计的类型的测试。 - jfriend00
好的,很酷。你可能是对的。只是想确认你是否知道那个很棒的资源。 - GregL
@ŠimeVidas - 你说得对,它可以在没有计时器的情况下完成,但是你的代码假设 $(document).ready() 总是最后一个触发的 - 我不想做出这种假设。但是,我在这里删除了计时器,而不做有关触发顺序的假设:http://jsfiddle.net/jfriend00/dLx4L/. - jfriend00
@jfriend00 哦,我明白了。我稍微改进了你的演示:http://jsfiddle.net/k3J9g/ (将全局变量的数量减少到一个,并将所有逻辑放在一个表达式中,以简化它的使用) - Šime Vidas
@ŠimeVidas - 做得好。你的代码没有告诉你哪个先来(我的代码根据哪个先来显示正值或负值),但除此之外,看起来两者都给出了类似的结果。 - jfriend00

0

我的建议:

我看到很多网页开发者在页面中放置了数百万行的JavaScript代码...最后还是在document-ready中加载。

a)请记住,在完美的世界中,没有用户会在页面加载(显示)时立即与网页交互;并且

b)在完美的世界中,用户很可能在进行任何交互之前(甚至上下滚动)查看整个页面。

有了这个完美的场景,你应该在< script type ... >< /script>之间只放置页面闪屏所需的最小化内容,当然还有document-ready。

这里有一个技巧:将其他所有内容放入单独的SCRIPT.JS文件中,并在document-ready中使用getScript加载它:

$(document).ready( function () {
    ...
    ...
    $.getScript('your-scripts-path/your-script-file-name.js');
});

请注意,$.getScript当然可以成为dom-ready调用之一的回调函数。而且,它也可以有回调函数。
祝你好运!

这可能会生成最快的时间,直到您的基本HTML显示出来,但这通常不是目标,也不是在这里提出的问题。这里提出的问题是如何在页面初始化JavaScript运行之前获得最快的时间。您的技术实际上可能会减慢该过程,因为您动态加载脚本,这样做不会在页面加载后立即开始加载脚本。如果这些脚本需要初始化页面,则整个过程会变慢。 - jfriend00

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接