Chrome infinite scroll performance
See original GitHub issueIssue Summary
There appears to be a possible layout bug in Chrome that causes long delays when loading/displaying pages of our content list with infinite scroll. This screen cap demonstrates the issue where I am attempting to scroll as quickly as possible (it was particularly bad when recording, I didn’t reach the bottom of the list to keep the gif short):
For comparison, here’s exactly the same set of posts in safari and scrolling as quickly as possible (note it reaches the bottom of the list before Chrome even displays 1 extra page):
Performance in Firefox is similar to Safari.
Things I’ve ruled out:
- scripts taking longer to run in Chrome - captured profiles indicate that the time spent in scripts whilst the spinner is displayed is pretty minimal compared to the length of the delay
- network requests / images - profiles from both browsers and the logs in ghost indicate that the time spent in the ajax request is minimal, typical response time from the server is ~60ms. Removing images from the template to avoid the loading and 404s made no difference
- rendering of list items - removing the list item component and simply rendering a
<h3>{{post.title}}</h3>
inside each list element still displays the same problem - layout bug - on further investigation the JS, layout + paint step is pretty quick
Scroll behaviour and timeouts stalling network connections
I’ve observed that when dragging with the scrollbar rather than the trackpad it’s not possible to reproduce the slow behaviour.
Looking at the timeline profile I can see quite a few scroll events and timers are created, it now seems possible that those events/timers are somehow causing the stalled network requests that I’ve shown in my comment below
Possible layout bug?
Removing all other layout to leave only the scrollable element with the same styling does not exhibit the dire performance illustrated above. This leads me to think that there may be a bug in Chrome’s layout engine that is being triggered by something in our surrounding styles/HTML, perhaps something to do with flexbox and an expanding element? I’ve not had much luck confirming this via profiling, the profiles appear to show Chrome sitting there doing nothing for quite a while before a very quick paint step.
Steps to Reproduce
- Import a large number of posts into the blog
- Load the content screen
- Scroll
Technical details:
- Ghost Version: master (a degree of this is also visible in LTS but the scroll behaviour has been improved in master)
- Browser/OS:
- Chrome 55.0.2883.95 / macOS 10.12.3
- Chrome 56.0.2924.87 / macOS 10.12.3
- Chrome Canary 58.0.3000.0 / macOS 10.12.3
Issue Analytics
- State:
- Created 7 years ago
- Comments:14 (6 by maintainers)
Top GitHub Comments
I experienced a similar problem with my own app in React. I stumbled across this post looking for a solution. My issue was related to “Content Download” and infinite scrolling. Disabling the touch events did not work for me, but Chrome honors the
mousewheel
event despite the fact that most other browsers don’t. I put a conditionale.preventDefault()
on the event and that seems to have done the trick.I am still not 100% sure as to how this directly impacted the scroll event in Chrome. Here is a more in-depth response on stack overflow.
I eventually tracked this down to a Chrome “optimisation” behaviour that is enabled when you have touch event handlers registered. Disabling touch events in Ember’s EventDispatcher solved the problems I was seeing:
Another confounding factor which may/may not have been an issue I noticed when profiling - Chrome seemed to be flagging long frames (~30ms) when scrolling, as far as I can tell that time was taken up entirely by Chrome’s
scrollUpdate
andmouseWheel
events, there was only a ms or two that were JS related and it was the same when I’d removedember-infinity
to test. I bring this up as I’ve seen mention that the delayed setTimeout and xhr behaviour can be triggered when frames are taking >16ms.