At F8 —Facebook’s annual developer conference — the company’s engineers took to the breakout stages to discuss the newest versions of the React and Relay frameworks, both of which were rewritten from the ground up to deliver significantly better performance to the applications that are written with them. In some cases, that means better performance for certain features of certain applications since developers can selectively apply the framework capabilities to some parts of their apps, and not others.
But like pretty much any framework or SDK that’s designed to hide a lot of complexity and heavy lifting behind a few lines of code or declarations, React introduces overhead to the applications that are built with it and the effects of that overhead are typically felt by end-users in the performance of their apps.
During his presentation, Facebook engineering manager Tom Occhino discussed how, “in some cases, this leads to sub-optimal application load times or other eperiences where application appears unresponsive.” Occhino gave examples such as jank — a well-known term to developers that describes the jittery look of applications during user initiated operations such as page scrolling where, as opposed to a naturally fluid feeling, a page seems to stutter as it’s scrolled. Another example Occhino discussed is when the user attempts to do something with their application and they get a pinwheel or some other indication that the system is busy with other tasks.
Describing that jittery user experience in video-terms, Occhino said that the cause of dropped frames is that "we were often wasting CPU cycles rendering low priority stuff and not what’s on the screen. We were interrupting work that needed to be done that has significantly more priority.”
According to Occhino, given this set of circumstances, one way to naturally improve the perceived performance of a React app is to reprioritize tasks in a way that the experience that’s right in front of the end-user gets the highest priority in terms of system resources like CPU.
For example, said Occhino, if the end-user is in the process of typing something, system resources should not be diverted at that moment to deliver some notification that lights up in the corner of the screen. The priority for those resources should be to allow the user to keep typing without being interrupted. But optimizing such prioritizations so that most application interactivity is happening according to end-user expectations can be tricky. For example, while that notification in the corner should take less priority than the end-user’s keyboard activity, it still has to be delivered on a timely basis. According to Occhino, “it’s not just about deferring the work. We want to be able to maybe start the rendering [of that notification] and then pause [to accommodate the keyboard activity]. We don’t know what the optimal scheduling is, but we know we need to have more control over it."
Another example Occhino gave had to do with tabbed interfaces where one tab has focus and the others are hidden. “The way the Web is designed to work by default, you render the hidden tab anyway. But the first tab more important. These are all examples where lower priority rendering work is getting in the way of highter priority work.”
To better understand how to optimize the prioritization, Facebook has established benchmarks based on end-user expectations. Occhino said that "any gesture like a drag of an object has to be responded to very quickly, within 10ms.” Users expect an immediate response when they attempt to drag something. “But with a tap or a click,” said Occhino, “we have more time, around 80-100ms. The difference between tapping and dragging is big.” Apparently though, when it comes to an activity where the end-user knows the app must go out to the network, the expectations are less demanding. “Network activity?” Occhino rhetorically asked. “We have forever. About 1000ms (1 second)."
Referring back to the example involving tabs, Occhino said that for hidden content, “We can get to this whenever. But ideally before the user clicks on the tab. We have to do the more important work first.”
So, as it turns out, while these optimizations may, on the surface appear to make apps perform better, they are not necessarily performance improvements to React. Rather, “it’s actually scheduling” said Occhino.
Thankfully, because React is architecturally similar to the way API calls work — declarations are like API calls in that they are decoupled from React’s underlying core — Facebook was able to rewrite the core while avoiding any breaking changes.
The new version of React’s core - React Fiber — is actually based on a data structure from computer science called the fiber. React Fiber has already been put into production on Facebook.com. But the scheduling features are currently turned off. They will, according to Occhino, be turned on incrementally over time.
For developers who are looking to work with the new core in their apps, it will be available as a part of release 16 of React.