Deferred long-running timer task(s) to improve scrolling smoothness - javascript

I was inspecting my page and I got this warning:
Deferred long-running timer task(s) to improve scrolling smoothness. See crbug.com/574343
I've also seen:
Blink deferred a task in order to make scrolling smoother. Your timer tasks should take less than 50ms to run to avoid this. Please see https://developers.google.com/web/tools/chrome-devtools/profile/evaluate-performance/rail and https://crbug.com/574343#c40 for more information.
What is this?

This occurs when Blink (Chrome's rendering engine) decides to delay executing a timer (like a function passed to requestAnimationFrame, setTimeout, or setInterval) because those functions are generally taking >50ms to execute and there is user touch input. It's done to prioritize handling user input (like scrolls and taps) above what the site is doing.
If you've encountered this message, then its likely your users will get similar behavior. Here's how to reproduce this scenario:
Have long-running javascript that is triggered via timers
Be on mobile (or emulating it with DevTools device mode)
Have touch input, scrolling with finger down on the screen is the most reliable. Tapping or flinging the page may also trigger it, but it is less likely and harder to reproduce.
The devtools' experimental CPU throttling will make the JS take longer and give you a better chance of seeing it.
The method for how to solve this is directly from the referenced issue in the console message down in comment 40:
Record a timeline on the page that is triggering the console message about deferral.
Select the entire timeline and open the "Event Log" pane near the bottom of the window.
Enter "Timer Fired" into the filter text field. (See image at bottom)
Look for timers in the list whose "Total Time" exceeds 50 milliseconds. These are the problematic ones. (Note that timers that exceed 10 milliseconds can also trigger this message in some cases where the browser is processing a user gesture. )
You want these functions to execute faster or less frequently.

Related

Chromium busy indicator

Chromium sometimes shows that my angularjs application is busy, although it isn't:
Instead of the favicon, it shows a spinner.
Instead of the reload circular arrow, it shows a cross.
The application is idle, reacts quickly, and I can't see any activity in the devtools: There's no outstanding request and the timeline has zero events. The computed is idle.
Clicking on the cross (which stops loading), does nothing at all (and the cross does not change to a circular arrow). Nor does clicking on the stop icon in the source code debugger do anything.
Any chance to find out what's causing this?

requestAnimationFrame - Tell when browser loses focus

From what I have read requestAnimationFrame can tell when the browser loses focus. Is there some kind of event that fires when this occurs? I'm looking to pause and resume code in connection with requestAnimationFrame.
requestAnimationFrame is not an element on which an event can be or is fired when the browser loses focus; it just sets up a callback. But standard behavior is that when the browser/tab goes out of focus, callbacks are paused. Therefore, most likely your code (if in a callback) is already being paused.
There is a possibility that all browsers may not pause callbacks, but instead slow them down. However, the W3C spec would seem to imply pausing, not slowing:
Whenever a Document's hidden attribute ([Page Visibility]) is false and the animation frame request callback list is not empty, the user agent MUST regularly queue a task...
If d's hidden attribute is true, continue to the next entry in the contexts list.
If you want to be absolutely sure your code is pausing when the tab is out-of-focus, or if the code you are trying to pause is not structured as part of a RAF callback, then you could consider using the
Page Visibility API.
Note that both RAF and Page Visibility API are available only in IE>=10.

Chrome tab crashing / hanging after brought on foreground being long time on background

I've got a page that shows real-time statistics. It runs a lot of javascript, makes a lot of HTTP requests, renders SVG charts every few seconds using D3.js, has a lot of CSS animations, and rearranges the DOM frequently.
As long as the page is focused, it runs smoothly. If I switch to another tab and come back later, there's often a short pause where the page seems to be frozen before the view suddenly seems to rerender and the page becomes usable again. The longer the tab has been backgrounded, the longer this pause is. If the tab has been in the background for a very long time (hours) and I switch back to it, it will be frozen for a long time then crash.
All these behaviors are observed in Chrome. I haven't tested much in other browsers.
What isn't Chrome doing while the tab is in the background, and what is it doing during that pause when I first switch back to the tab?
UPDATE:
I'm also doing some jQuery animating. This answer and this one may be relevant.
According to that first answer:
"Inactive browser tabs buffer some of the setInterval or setTimeout functions."
stop(true,true) will stop all buffered events and execute immediatly only the last animation.
I've added a call to .stop(true, true) in my code, and at least for short trips away from the tab, I'm not detecting a hiccup. I need to leave it in the background for a long time and test it before I can tell if it made significant difference.
We had a similar issue with SVG graphs and managed to solve it using Page Visibility API introduced with HTML5. If anyone stumbles upon such an issue please refer to the following article Using the Page Visibility API
What we managed to do was to suspend all SVG rendering activities when the browser window is not visible. This managed to stop the tab from crashing.
Yes, it's typical behavior of Chrome browser.
I guess that while your tab is in background, Chrome places all tab data on "back shelf" to clear "front shelf" that works much faster. I know, it sounds unprofessionally, but i hope that you understood.
I think it is very hard to solve this problem in your case (because you are using a lot of manipulations with graphic).. but maybe this method will save you (i had never tested it before):
Every time you update your statistics (or do some highload calculations), you can save a timestamp. Then, when you update your statistics again, you can substract that old timestamp of the new timestamp. And, if you see that the difference between timestamps is very big, use setTimeout() function before next update. Maybe, it will prevent Chrome's chash.

Javascript execution tracking in Chrome - how?

I have ~ 100-200 javascript functions loaded on a web-site.
I want to determine what javascript function is executed when i click one item or another in Google Chrome.
How can i do it with Chrome Web Developer Tools?
Thanks!
One simple approach is to start Chrome Developer Tools, switch to the Sources panel and hit F8 (Pause Execution). This will break on the first executed JavaScript statement.
Another approach is to set an event listener breakpoint for mousedown or click: in the same Sources panel, expand the "Event Listener Breakpoints" in the righthand sidebar. Expand the "Mouse" item and check the events you want to break on (e.g. "click", "mousedown"). Then go click in your page and see the JS execution break in the DevTools. Enjoy!
An alternative to pausing execution(which usually works great, but doesn't work well on pages which frequently execute periodic code)
You can use chrome's profiler to record for a short period of time. After you finish recording, it will show you a summary of cpu time spent in any of the functions which were executed during recording. We don't really care about the cpu time, were just using this tool because it will show us which functions were executed.
Basically just start recording:
Note: in Chrome 58 and above, the "Profiles" tab is renamed to "Memory". In Chrome 88+, the tab name is "Performance".
Then do your action(eg, click a button on the webpage, or do whatever will cause the interesting code to execute). Then stop the recording and view the result:
Notice I'm using "top down" viewing mode - which shows you the call stack, and you can drill down to see which functions eventually got called. For example, some anonymous function was called first(likely as a result of setTimeout or maybe some click event handler), and then it called some method identified by s.track.s.t which then called s_doPlugins and so on...The important thing is that in top down mode, the entries at the top of the tree form the start of a call stack, and so they're usually a function registered by some timer function(setTimeout, setInterval, requestAnimationFrame, etc...) or some event handler(click, mousemove, load, etc...).
You can also use the "chart" viewing mode, which shows you which function was called at which time, plotted on a chart from left to right. This helps you identify which function you're really looking for because you probably have a sense of what time the code executed within your recording(eg, right in the middle).
btw - I believe most other modern browsers have similar capability.
Chrome has updated many times since I wrote this answer, so the screenshots are a bit outdated, but the concept of using the cpu profiler remains the same. I'll update the screenshots another day.
I want to determine what javascript function is executed when i click one item or another in Google Chrome.
Now there's a great extension called Visual Event that does exactly that. It only recognizes event handlers set via popular js libraries (jQuery, YUI, MooTools, Prototype, Glow) and DOM Level 0 events.

JQueryUI animations building up while in a different tab

I have a real-time app where I am animating certain elements on the screen back and forth upon certain websocket-enabled events firing (e.g event "moveLeft" and event "moveRight"). When the user visits another browser tab and returns after many of these events have fired, they see the entire sequence of animation carry out (using .animate() upon each event firing) even though they are no longer relevant to the user. What I would like instead is for the animations to effectively happen while the user is tabbed away so that when they revisit the tab, they see the current world state and simply miss all those animations that were triggered while in another browser tab.
I can't seem to find any documentation on this issue; it bears similarity to the solution where you need to call .stop() before animating other mutually exclusive things so that you get don't a buildup after excessive mouseover events, but that is not really applicable here. Any tips would be greatly appreciated.
There is a similar question here: slideshow goes crazy if you tab away
In your case, since websockets trigger the animations, one solution could be to watch if the window has focus and only trigger the animations when it's in focus.

Categories