【问题标题】:Javascript OnScroll performance comparisonJavascript OnScroll 性能对比
【发布时间】:2018-07-13 17:07:48
【问题描述】:

更新:类似的问题有一个很好的答案,展示了如何以一种有用的方式使用 requestAnimationFrame 和滚动: scroll events: requestAnimationFrame VS requestIdleCallback VS passive event listeners


假设我想在我的网站上添加一些由滚动触发的昂贵操作。例如,我在 jsfiddle 中使用了视差效果。

现在我一直在读,它一定不能直接绑定到事件,有时后面跟着 sn-ps 是为了更好。只是一些例子:

  1. Attaching JavaScript Handlers to Scroll Events = BAD!
  2. How to develop high performance onScroll event?
  3. How to make faster scroll effects?
  4. 60FPS onscroll event listener

他们所说的基本上是不要这样做:

  // Bad guy 1
  $(window).scroll( function() {
    animate(ex1);
  });

或者这个

  // Bad guy 2
  window.addEventListener('scroll', onScroll, false);
  function onScroll() {
    animate(ex2);
  }

但是使用超时、间隔、requestAnimationFrame 之类的,例如:

  // Good guy
  $(window).scroll( function() {
   scrolling1 = true;
  });

  setInterval( function() {
    if (scrolling1) {
      scrolling1 = false;
      animate(ex3);
    }
  }, 50 );

因此,我将在上面链接中找到的选项添加到 jsfiddle 中,该 jsfiddle 尝试通过为每种方法添加计数器来比较它们,如下所示:

  // Test
  $(window).scroll( function() {
    counter = counter + 1;
    // output result of counter
    animate(ex1);
  });

最好检查完整的jsfiddle

结果:一切顺利进行的计算次数大致相同。如果我能忍受波涛汹涌的影响,也许我可以保护一些资源。与我阅读的所有内容相比,这对我来说似乎是合乎逻辑的!

第一个问题: 我错过了什么还是这是一个有效的测试?如果它无效,我该如何正确测试? 编辑:澄清一下,我想测试一下上述方法是否能节省性能。

第二个问题: 如果它是有效的,为什么每个人都对 onscroll 感到紧张?如果流畅的动画需要对整个站点进行 5000 次计算,那么无论如何都无法更改它?

(嗯,有时我会使用检查来确定对象是否在视口中,但老实说,我什至不知道这些检查是否没有被阻止的代码本身那么昂贵,特别是如果它们涉及五个不同的offset、windowHeight、scrolltTop、getBoundingClientRect 和 outerHeight 等变量...)

【问题讨论】:

  • 你在测试什么?表现?独立于浏览器(javascript引擎)、设备、操作系统?你需要测试所有这些东西......但无论如何我认为你应该使用被动事件侦听器或滚动事件的东西
  • developer.mozilla.org/en-US/docs/Web/API/EventTarget/… 看起来这些天对于 chrome 和 firefox 来说是自动的...在 touchstart 和 touchend
  • 谢谢科迪。我正在尝试验证上述任何方法是否真的在优化性能,或者是否没有必要。我将其添加到我的问题中。我很快会更仔细地阅读这些链接。 (看起来我应该在旧浏览器中对其进行测试,以了解这些方法之间的更多区别?)
  • 大声笑,我打算在 IE11 中为你测试,但我什至无法在其中加载 jsfiddle。但是,是的,我想知道 iOS/Safari 如何处理滚动事件。我认为这是一个非常具体的话题,我希望在过去一年左右研究过它的人可以加入

标签: javascript jquery scroll onscroll


【解决方案1】:

所以,@SirPeople 已经正确回答了你的第一个问题,这确实是一个很好的测试来查看 animate 函数被调用的频率,但它是一个不好的测试来比较不同 sn-ps 的性能。

这是执行的性能记录:

函数animate 一点也不贵。我拍了一张性能记录(下一张图片),它显示在我查看的一次迭代中它花费了 0.64 毫秒到 1.29 毫秒(第 1-5 点)。并且一旦函数完成,重绘完全不需要时间(第 6 点),这可能是因为页面几乎没有内容。当我们查看时间时,我们可以看到所有五个动画函数和重绘都发生在不到 10 毫秒的时间内,这意味着在正常情况下,我们可以获得流畅的 60fps 动画(第 7 点)。

此外,如果我们想比较 onscroll 事件侦听器,我们需要单独测试每个侦听器并比较结果。如果其中一个监听器真的阻塞了,它会对整个页面产生影响,如果没有性能调试,你将不知道它是哪一个。

我做了两个 jsfiddles window.scroll 和 RAF。而且,令我惊讶的是,似乎没有任何区别。

为什么人们会关心这个?

正如您在上面链接的 jsfiddles 中看到的,如果事件处理程序变得太大,整个页面将会滞后。

现在呢?

我自己不是表演大师,但是:

【讨论】:

  • 很好,谢谢。我并没有试图让动画功能变得更昂贵,而且比较不同站点上的方法也更合乎逻辑。我想你的回答,Cody 的 cmets 和 @SirPeople 的回答没什么好说的了。让我们看看交叉点观察者将来是否会改变。
【解决方案2】:

我不完全确定我是否正确地回答了你的问题和你的所有陈述,但我会尽力给你一个答案:

  • 是我遗漏了什么还是这是一个有效的测试?如果无效,如何正确测试?

如果您正在测量函数被调用的次数,这是一个有效的测试,这当然取决于浏览器,所以,如果 GPU 增强以及您的问题中已经评论的其他一些基准参数.

如果我们认为测量正确,那么可以说通过使用超时或 requestAnimationFramework 可以节省时间,因为我们基本上遵循debouncing or throttling 的原则。基本上,我们不想请求或调用一个函数的次数超过需要的次数。在计时器的情况下,我们将排队较少的函数调用,而在requestAnimationFrame 的情况下,因为它在重新绘制之前将调用排队并按顺序执行它们。在超时时,如果计算量很大,可能会发生重叠。

我在why using requestAnimationFrame 中找到了更好的答案,解释了浏览器中动画的主要问题,例如剪切、闪烁或跳帧。它还包括一个很好的演示。

我认为你的测试方法是正确的,你也应该正确解释它,也许因为你的硬件和你的引擎,调用接近于相同的数字,但正如所说,去抖动和节流是一种性能缓解。

Here also one more article supporting not attach handlers to window scroll from Twitter。 (免责声明:本文来自 2011 年,浏览器以不同方式处理滚动优化)。

  • 为什么每个人都对 onscroll 感到紧张?如果流畅的动画需要在整个站点上进行 5000 次计算,那么无论如何都无法更改它?

我不认为性能受到影响,但是对于上述动画问题,您的滚动调用可能会导致用户体验最差,或者即使您的计时器不同步,您仍然可以获得同样的“性能”问题。人们只是建议保存呼叫以滚动,因为: 人类的视觉持久性不需要超高的帧率,因此尝试更频繁地显示图像是没有用的。 对于更复杂的计算或繁重的动画,浏览器已经在进行优化,就像您检查过的那样,与 2、3 或 6 年前您公开的文章相比,有些 browsers had optimize this things。

【讨论】:

  • 非常感谢,这很有帮助。不过,我现在将 Sandros 的答案标记为正确,因为它指出了问题从哪里开始(昂贵的动画功能)与性能记录,并显示了如何更好地进行比较(不是在一页上运行所有示例)。不过,您的回答有帮助,再次感谢!
  • 嘿,很高兴您发现这个答案很有用。答案没问题,我也喜欢他用浏览器分析。
猜你喜欢
  • 2020-01-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-03-14
  • 1970-01-01
  • 1970-01-01
  • 2010-11-17
  • 1970-01-01
相关资源
最近更新 更多