7

我们面临与 mousemove 相关的 jQuery 事件传播性能问题:

我们有一个屏幕填充画布,需要跟踪用户是否在其上拖动鼠标,因此我们在该对象上添加了一个鼠标移动侦听器,如下所示:

ourCanvas.on('mousemove',
   function(event) {
      event.preventDefault();
      //our drag code here
   }
});

这段代码运行良好,但我们在一个测试系统上的当前 Firefox (24) 中遇到了严重的性能问题。分析器告诉我们,大部分时间都花在了jQuery.event.dispatch()(我们尝试了当前最新的 jQuery 1.8、1.9、1.10 和 2.0)。

我们通过在此处使用“jQuery.event.fix()”性能优化成功地减少了 dispatch() 函数所花费的时间:http: //bitovi.com/blog/2012/04/faster-jquery-event-fix。 html但该测试系统的性能仍远低于我们的预期。

经过一些进一步的测试,我设法将其固定在系统上使用的鼠标上:它使用了1000Hz。我们将使用过的鼠标调低到 125Hz,瞧,性能很棒。

我们的假设是,鼠标的高 Hz 速率会导致大量 mousemove 事件,因此我们更改了上面的代码以应用事件限制,并且仅每 X 毫秒调用一次事件处理:

var lastMove = 0;
var eventThrottle = 1;
ourCanvas.on('mousemove',
   function(event) {
      event.preventDefault();
      var now = Date.now();
      if (now > lastMove + eventThrottle) {
          lastMove = now;
          //our drag code here
      }
   }
});

它就像一个魅力,表现很棒。即使我们只跳过两毫秒的事件。

现在我有两个问题:

  1. 我们在其他位置将 mousemove 侦听器附加到不同的 HTML 元素,我想将这个手工制作的节流阀添加到所有这些mousemove处理程序中,以免再次遇到问题。这在 jQuery (2.0.3) 中是否有可能以一种很好的方式实现?我preDispatch在 jQuery javascript 中看到了钩子,但它们已经在调用 fix() 之后,这也需要一些时间,我也想保存该调用。

  2. 我对 2ms 已经足以获得非常好的性能这一事实感到困惑,eventThrottle所以我添加了一个计数器来查看有多少事件被跳过。令人惊讶的结果:它只跳过了 0-1 个事件……在 100 毫秒的节流阀下,跳过的事件大约为 60-70,所以如果每毫秒的 mousemove 事件少于 1 个,为什么这段代码会有这样的事件?毕竟是积极的影响吗?

感谢您的任何评论,克里斯托弗

4

2 回答 2

3

2015 年底,我遇到了我最终发现的问题。

在我的浏览器应用程序中,我在特定位置绘制多个不同大小的圆圈,然后拖动整个屏幕的可见部分,仅显示在当前缩放级别可见的完整背景中的圆圈。拖动鼠标会生成一个 mousemove 事件,该事件会触发对我的渲染例程的调用,这反过来会导致每个可见圆圈的重绘。

在 IE 11 中对此进行测试时,我发现在可视区域中有大约 100 多个圆圈时,拖动鼠标时的渲染变得非常不稳定。分析器表明这几乎完全是由于 paint() 例程。

我的代码已经在使用库中的 requestAnimationFrame()。有趣的是,在拖动屏幕时,我看到了减速;但如果我只是拖动屏幕并释放它,让库代码继续以减速方式为运动设置动画,重新绘制就像黄油一样顺利。减速仅在拖动鼠标时发生。问题肯定似乎与mousemove有关。(一会儿回到这个。)

我将paint() 例程缩减为一个简单的填充弧——同样的问题。每当我更改缩放级别时,我都会尝试将填充的圆圈绘制到屏幕外的画布上,然后使用 drawImage() 将屏幕外的画布复制到我的主屏幕——这提高了性能,但在 IE 中仍然无法使用。然后我尝试使用这种技术将所有圆圈绘制到与我的主可见窗口大小相同的屏幕外画布上,然后将 paint() 更改为除了将屏幕外画布复制到我的可见画布之外什么都不做——这又带来了一个小的改进,但还不够。

然后我尝试在各种浏览器中运行我的应用程序:

IE 11:非常不稳定 Firefox 42:非常不稳定 Chrome 47:在所有缩放级别都非常平滑 Opera 34:在所有缩放级别都非常平滑 Desktop Safari 5.1.7(在 PC 上):在所有缩放级别都略微不稳定

这个问题肯定与 mousemove 以及不同浏览器如何处理它有关。

最终,我在 StackOverflow 上发现了这个问题,它暗示鼠标本身正在发送如此多的 mousemove 事件,以至于它淹没了浏览器足够快地重新绘制的能力。而且我确实有一个具有高事件生成率的现代鼠标。

我尝试将 eventThrottle 检查添加到我的 mousemove 事件处理程序中,瞧!成功。我的代码现在可以在所有浏览器上顺利呈现。(高兴地赞成。:))

我想为任何可能在使用高频鼠标拖动时遇到 IE 和 Firefox 中的 Paint() 性能不佳问题的人添加此附加信息。建议的限制 mousemove 事件的解决方案对我有用。

于 2015-12-19T04:04:07.467 回答
2

1 - 有一个油门 jQuery 插件:https ://github.com/cowboy/jquery-throttle-debounce

正如您在示例中所读到的,您可以替换:

// Bind the not-at-all throttled handler to the resize event.
$(window).resize( handler );

// Bind the throttled handler to the resize event.
$(window).resize( $.throttle( 250, handler ) ); // This is the line you want!

2 - 你想发布你的处理程序的代码吗?

一个盲点建议:Firebug 与 FF 24 存在性能问题。您是否尝试比较启用/禁用 Firebug 的性能?

于 2013-10-11T14:49:11.863 回答