【问题标题】:$(document).ready() check slows down IE?$(document).ready() 检查减慢 IE 速度?
【发布时间】:2011-12-30 21:27:59
【问题描述】:

我一直在与一家名为 Catchpoint 的公司合作,以解决我们客户端代码指标中的一些不一致问题。他们有一些事件触发,这些事件衡量页面加载过程中的里程碑。他们为我们提供的指标在 IE8 中。

现在,他们声称 JQuery 在 IE 中确定 DOM 就绪的方式实际上严重损害了页面性能,我们应该不惜一切代价避免它。我知道 JQuery 对 doScrollCheck() 方法和 documentElement 上的 1ms 递归 setTimeout 爆炸做了什么,我想到他们可能有一个有效的声明。

他们说,每个 $(document).ready() 块都会对性能造成指数级伤害。

我的问题是,他们是否有任何统计数据可以验证这一说法,如果是,我将如何实施一个对 IE 友好的解决方案,而无需根据我的需要重新编写 JQuery 源代码。

【问题讨论】:

  • 请记住,您可以随时深入了解jQuery Source Code 以获取有关此事的一些统计信息...
  • 他说他知道doScrollCheck()方法和1ms递归setTimeout。他可能只有在阅读源代码后才会知道。

标签: jquery performance internet-explorer


【解决方案1】:

根据 JSperf 的说法,在所有浏览器中,多个 DOM 就绪函数确实会减慢页面速度,因此我将重构大量自己的代码以适应这一新发现。当然,IE 慢得令人尴尬,但测试并没有我希望的那样提供信息,因为即使没有 DOM 就绪检查,它也慢得多。摆脱这一点的事情是尽可能减少对这些 DOM 就绪函数的使用。

Chrome 中的结果:

  • 单个 $(document).ready():734,811 次操作/秒
  • 多个 $(document).ready() [4 个块]:151,989 ops/sec
  • 没有 $(document).ready():208,965,555 次操作/秒

在 IE8 中的结果:

  • 单个 $(document).ready():26,349 次操作/秒
  • 多个 $(document).ready() [4 个块]:5,971 ops/sec
  • 没有 $(document).ready():5,000,159 次操作/秒

分析这些指标:

  • 在 Chrome 中,没有 DOM 就绪检查需要 0.35% 的时间来完成 DOM 就绪 检查需要
  • 在 IE 中,没有 DOM 就绪检查需要 DOM 的 0.53% 时间 准备好检查需要

仅这些数据就告诉我们,doScrollCheck() 函数在很大程度上影响了性能

话虽如此:

  • Chrome 的 DOM 就绪检查速度比 IE 快 27.98 倍
  • 在 Chrome 上,执行 4 次 DOM 就绪检查比在 IE 上快 25.45 倍
  • 没有 DOM 就绪检查在 Chrome 上比 IE 快 41.79 倍

从表面上看,这看起来毫无希望——但如果你仔细想想,没有 DOM 就绪功能的 IE 页面执行超过 500 万次/秒,而 Chrome 上的单个 DOM 就绪功能执行不到一百万。这告诉我您是否设法告诉 JQuery 使用更友好的 doScrollCheck() 函数,例如检查 documentElement 是否每 100 毫秒而不是每 1 毫秒滚动一次,您可能会看到页面加载时间与 chrome 相比更具竞争力。

这个基准真正告诉我的是,即使是 DOMContentLoaded 检查也非常慢 - 在 Chrome 上从 2.09 亿次操作/秒降低到 100 万次以下是没有任何借口的。

http://jsperf.com/docready/3

【讨论】:

  • 我不确定这是否真的测试了 OP 想要测试的内容。您正在测试四个函数调用来设置四个 document.ready() 调用与一个函数调用来设置一个 document.ready() 调用。呃,四个函数调用它的速度大约是一个函数调用的 1/4。这在实际代码中是否相关不取决于单个函数调用开销的速度,而是取决于相对于整个启动时间的重要性。这可能很重要,也可能不取决于实际启动代码需要多少时间。
  • 另外,我认为 OP 想知道的是,与知道 DOM 何时准备就绪的其他机制相比,在 IE 中触发 $(document).ready() 的时间是否慢,这不是您要测量的这里。您实际上是在对 $(document).ready() 本身的调用进行基准测试(它只是注册稍后调用的回调函数),而不是在它触发并实际调用回调时进行基准测试。
  • 他确实提到他想要验证“他们说每个 $(document).ready() 块的性能都会成倍地受到损害。”
  • 但你所证明的只是四个函数调用比一个函数调用慢 4 倍。您没有证明这是否与整体启动时间有关。如果整个页面启动时间为 600 毫秒,并且三个额外的 $(document).ready() 调用为 5 毫秒(您的 IE8 计时似乎表明),那么这将小于 1% 的减速 - 可能甚至不相关,当然也不是建议的“指数”。
  • 查看更新的基准分析 - 很想听听您的见解。我真的很好奇这个问题的真正答案,以便更快地准备好 DOM。
【解决方案2】:

这是一个脚本,用于测量$(document).ready() 触发和在正文末尾执行代码之间的时间(这是您可以操作 DOM 的最早时间)。你可以在任何你想要的浏览器中自己运行它。页面在这里:http://jsfiddle.net/jfriend00/dLx4L/

为了方便、长寿和易于共享,我在 jsFiddle 中做了这个,但如果您制作一个实现相同技术的独立网页(不涉及 jsFiddle 中的其他框架),您可能会进行更准确的测试.无论如何,您应该能够在此处了解如何衡量这一点并为其输入实数。

【讨论】:

  • 你看过jsperf.com这个网站吗?这是与 javascript 进行性能比较的更好方法。
  • @GregL - 如果你认为你可以在 jsperf 中编写这个测试,请告诉我们如何。我不认为 jsPerf 可以让您比较就绪事件的时间。它用于测量给定 javascript 操作的执行时间,这不是这个问题。我已经多次使用 jsPerf 来处理它的设计用途。
  • 好的,很酷。你也许是对的。只是检查你是否知道那个很棒的资源。
  • @ŠimeVidas - 你是对的,它可以在没有计时器的情况下完成,但你的代码假设 $(document).ready() 总是最后一个触发 - 我不愿意假设。但是,我确实删除了这里的计时器,而没有假设触发顺序:jsfiddle.net/jfriend00/dLx4L
  • @jfriend00 啊,我明白了。我对您的演示进行了一些改进:jsfiddle.net/k3J9g(将全局变量的数量减少到一个,并将所有逻辑放在一个表达式中以简化其使用)
【解决方案3】:

我的 2c:

我见过很多 Web 开发人员在页面中放入一千万个 javascript 代码......最后一个是准备好文档的。

a) 请记住,在完美的世界中,任何用户都不会在网页加载后立即与网页进行交互(如图所示);和

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

考虑到这个完美的场景, 之间应该有的只是页面 SPLASH 所需的最小值,当然还有文档就绪。

神奇之处来了:将所有其他内容放在单独的 SCRIPT.JS 文件中,并使用 getScript 将其加载到文档就绪中:

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

请记住,$.getScript 当然可以成为 dom-ready 调用之一中的回调。而且,它也可以有回调。

祝你好运!

【讨论】:

  • 这可能会在显示基本 HTML 之前产生最快的时间,但这通常不是目标,也不是这里要问的问题。这里要问的问题是如何在您的页面初始化 javascript 运行之前获得最快的时间。您的技术实际上可能会减慢该过程,因为您动态加载脚本,直到页面加载后才开始加载脚本。如果需要这些脚本来初始化页面,那么整个过程就会变慢。
猜你喜欢
  • 2010-10-20
  • 2011-10-04
  • 2014-04-20
  • 2015-11-27
  • 1970-01-01
  • 2016-12-04
  • 1970-01-01
  • 1970-01-01
  • 2016-08-28
相关资源
最近更新 更多