From f1ac8022d503a904dc66685e9b979814730ef3bc Mon Sep 17 00:00:00 2001 From: Timo Tijhof Date: Tue, 29 Nov 2016 13:48:15 -0800 Subject: [PATCH] mediawiki.notification: Improve scroll performance MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit This fixes the problem with random scroll lag when on a page that had 1 or more notifications at some point. The scroll handler was fairly expensive and kept being called on every scroll event. The actual frame where a frame is detected does take more than 16ms to paint but that's unavoidable. It only happens for 1 or 2 frames, which is perfectly within the response guidelines for RAIL. https://developers.google.com/web/fundamentals/performance/rail (MacBook Pro, Latest Chrome, CPU throttle 5x) 1. Before * Duration of no-change scroll event (not crossing offset.top in ither direction) ~5ms * Duration of changed scroll event (crossing the offset.top and swapping classes) ~10ms * Paint: - 16ms for no-change frames (50-60fps) - 40ms for frames that paint a change. (25-30fps) 2. After storing isFloating as boolean and not checking className if nothing changed. * no-change scroll event: ~0.13ms * changed scroll event: ~2ms * Paint: - 15ms for no-change frame (60fps) - 33ms for no-change frame (30fps) 3. After changing $window.scrollTop() to window.pageYOffset. * no-change scroll event: 15μs (0.015ms) * changed scroll event: ~1ms * Paint: - 11ms for no-change frame (60fps) - 20ms for no-change frame (48fps) Change-Id: Ia48b00cd0834700ce79e72d4599c51ff8c6179b5 --- resources/src/mediawiki/mediawiki.notification.js | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/resources/src/mediawiki/mediawiki.notification.js b/resources/src/mediawiki/mediawiki.notification.js index 926f8c5048..e1287dbc56 100644 --- a/resources/src/mediawiki/mediawiki.notification.js +++ b/resources/src/mediawiki/mediawiki.notification.js @@ -262,7 +262,8 @@ * @ignore */ function init() { - var offset, $window = $( window ); + var offset, + isFloating = false; $area = $( '
' ) // Pause auto-hide timers when the mouse is in the notification area. @@ -289,13 +290,17 @@ $area.hide(); function updateAreaMode() { - var isFloating = $window.scrollTop() > offset.top; + var shouldFloat = window.pageYOffset > offset.top; + if ( isFloating === shouldFloat ) { + return; + } + isFloating = shouldFloat; $area .toggleClass( 'mw-notification-area-floating', isFloating ) .toggleClass( 'mw-notification-area-layout', !isFloating ); } - $window.on( 'scroll', updateAreaMode ); + $( window ).on( 'scroll', updateAreaMode ); // Initial mode updateAreaMode(); -- 2.20.1