JQuery mousemove performance - throttle events?

We ran into a mousemove jQuery event propagation performance issue:

We have a canvas to fill the screen, and we need to track whether the user will click on the mouse, so we added a mouse movement listener on this object as follows:

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

This code works fine, but we had serious performance problems in the current Firefox (24) on one test system. The profiler tells us that most of the time was spent in jQuery.event.dispatch() (we tried using the latest jQuery 1.8, 1.9, 1.10 and 2.0).

We successfully reduced the time spent in the dispatch () function using the jQuery.event.fix () performance optimization: http://bitovi.com/blog/2012/04/faster-jquery-event-fix.html but the performance in this the test system was still below expectations.

After some additional testing, I managed to snap it to the mouse used in the system: it used 1000 Hz . We switched the used mouse to 125 Hz and voila, the performance was great.

Our assumption was that the high Hz frequency on the mouse caused a lot of mousemove events, so we changed the code above to use the event throttle and only call the event every X milliseconds:

 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 } } }); 

And it worked like a charme, the performance was great. Although we only miss two milliseconds of events.

Now I have two questions:

  • We have other places where we attach mousemove listeners to various HTML elements and . I would like to add this manual choke to all these mousemove handlers so as not to run the problem again. Is it possible to do this somehow in jQuery (2.0.3)? I saw preDispatch hooks in jQuery javascript, but they are already after the fix () call, which also takes some time, and I would also like to save this call.

  • I was puzzled by the fact that there was already an eventThrottle of 2ms to get really good performance, so I added a counter to see how many events were missed. Amazing result: it only misses events 0-1 ... With a 100 ms throttle, the missed events were in the order of 60-70, so if there are less than 1 muzem in milliseconds, why does this code have such a positive effect in the end?

Thanks for any comments, Christopher

+6
source share
2 answers

At the end of 2015, I was faced with the fact that I finally discovered this problem.

In my browser application, I draw several circles of different sizes in certain places, then drag the visible part of the general screen, showing only the circles from the full background that are visible at the current zoom level. Dragging the mouse generates a mousemove event, which triggers a call to my rendering procedure, which in turn triggers a redraw for each visible circle.

When testing this in IE 11, I found that when I had about 100 circles in the viewport, the rendering when dragging the mouse became extremely volatile. The profiler indicated that this was almost entirely due to the paint () procedure.

My code has already used requestAnimationFrame () from the library. Interestingly, while dragging the screen, I saw a slowdown; but if I only dragged the screen and let it out, letting the library code continue to animate the movement with slowdown, the repainting would be as smooth as butter. Slowing occurred only when dragging the mouse. The problem definitely seemed to be with mousemove. (Let's get back to this in a moment.)

I have reduced the paint () routine to nothing but a simple filled arc - the same problem. I tried to color the filled circle on the screen whenever I changed the zoom level, and then use drawImage () to copy the screen canvas to my main screen - this improved performance, but in IE it was still unstable. Then I tried to use this technique to draw all the circles on the front canvas of the same size as my main visible window, and then change paint () to do nothing but copy the splash screen onto my visible canvas - this again gave a small improvement, but not enough.

Then I tried to run the application in different browsers:

IE 11: very intermittent Firefox 42: very intermittent Chrome 47: ideal for all zoom levels Opera 34: ideal for all zoom levels Desktop Safari 5.1.7 (on PC): slightly variable at all zoom levels

The problem was definitely related to mousemove and how it is handled by different browsers.

In the end, I found this question in StackOverflow and its assumption that the mouse itself sends so many mousemove events that it hides the browser’s ability to redraw quickly enough. And I have a modern mouse with high speed event generation.

I tried adding a Throttle event checker to my mousemove and voila event handler! Success. Now my code smoothly displays in all browsers. (With pleasure.:))

I would like to add this additional information for those who may encounter the problem of paint () not working well in IE and Firefox when dragging with a high-frequency mouse. The proposed mousemove event throttling solution worked for me.

+3
source

1 - there is a jQuery throttle plugin: https://github.com/cowboy/jquery-throttle-debounce

As you can read in the examples , you can replace:

 // 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 - do you want to publish your handler code?

One suggestion: Firebug has performance issues with FF 24. Have you tried comparing performance with Firebug enabled / disabled?

+2
source

Source: https://habr.com/ru/post/955605/


All Articles