I was recently involved* in investigating a Chrome performance issue that I thought was worth sharing.
This page has a simple CSS 2D animation, with a ball moving back and forth (taking a second to go across the screen). At the left and right endpoints, the location fragment is updated to
#right. The intent is to simulate a multi-section page with transitions between the section and each section having a bookmarkable URL.
The puzzling part is that the animation skips a few frames in the middle (right as the ball is crossing the thin line). This may not be noticeable depending on your setup, so here's a video of it. This only happens in Chrome, not in Safari or WebKit nightlies.
Here's some hints as to what's going on, each revealing more and more.
- The jerkiness always happens 500ms into the animation (which is the halfway point in the one second version, but one quarter of the way into the 2 second version.
- Even though the animating area stays the same, the larger the window size, the bigger the hiccup.
- The inspector's timeline view for the page shows regular, small, evenly-spaced repaints, but then suddenly 500ms into the animation, there's a full screen repaint, followed by a large gap before updates resume.
- Taking out the location fragment update fixes the jerkiness.
- Chrome has a few things that happen with a 500ms delay.
- Watching the counter on
As it turns out, what's happening is that 500ms after a load finishes, Chrome captures the current page, so that it can be shown on the New Tab Page. This includes getting a thumbnail of the page (which involves repainting all of it and then scaling it down using a high quality filter). Updating the location with the fragment triggers this logic, and the larger the window, the more time is spent painting the page and then scaling it down.
In addition to fixing this on the Chrome side, the best way to avoid this is to update the location at the end of a transition, instead of at the beginning.