Expiration times#10426
Conversation
ee127ed to
796db96
Compare
|
Confirms that this makes the Triangle demo work as expected. Still need to write some unit tests, but this is ready for review. |
|
Added unit tests. I confirmed that all the existing tests, including the sync DOM ones, are passing when expiration is enabled. |
| getPublicInstance, | ||
|
|
||
| now(): number { | ||
| // Test renderer does not use expiration |
There was a problem hiding this comment.
@sebmarkbage I went back and forth on whether this should be an optional method. Landed on making it required because all renderers will need to account for features like expiration boundaries.
There was a problem hiding this comment.
Since scheduleDeferredCallback is required it seems reasonable that this would be too since they kind of pair together.
| return false; | ||
| } | ||
|
|
||
| // TODO: Better polyfill |
There was a problem hiding this comment.
Is this polyfill sufficient? Or am I overlooking something?
There was a problem hiding this comment.
It's fine. Maybe we should colocate it with ReactDOMFrameScheduling to have all these in one place?
It is also performance.now aware: https://github.com/facebook/react/blob/master/src/renderers/shared/ReactDOMFrameScheduling.js#L73
67388a1 to
14e68e3
Compare
| window.performance && | ||
| typeof window.performance.now === 'function' | ||
| ) { | ||
| now = function() { |
There was a problem hiding this comment.
Why not now = performance.now and now = Date.now?
There was a problem hiding this comment.
performance.now needs to be bound, but looks like Date.now doesn't. I'll update.
da21094 to
43360d9
Compare
0d4f363 to
36244ac
Compare
| } = ReactTypeOfWork; | ||
| var {Placement, Ref, Update} = ReactTypeOfSideEffect; | ||
| var {OffscreenPriority} = ReactPriorityLevel; | ||
| var {Never} = ReactFiberExpirationTime; |
There was a problem hiding this comment.
I like that this name change decouples this expiration time from the UI context in which it's used. What we really mean is 'this might never finish updating, and that's ok' and that may or may not be literally "offscreen" in the UI.
| TaskPriority, | ||
| HighPriority, | ||
| LowPriority, | ||
| OffscreenPriority, |
There was a problem hiding this comment.
haha, I guess it's not a rename after all. ("OffscreenPriority" to "Never" expirationTime)
|
Deploy preview ready! Built with commit 564c7e9 |
|
@gaearon I’ve rebased this locally, just haven’t pushed yet. I’ll work on getting all my PRs updated tomorrow. |
* [Work-in-progress] Assign expiration times to updates An expiration time represents a time in the future by which an update should flush. The priority of the update is related to the difference between the current clock time and the expiration time. This has the effect of increasing the priority of updates as time progresses, to prevent starvation. This lays the initial groundwork for expiration times without changing any behavior. Future commits will replace work priority with expiration times. * Replace pendingWorkPriority with expiration times Instead of a priority, a fiber has an expiration time that represents a point in the future by which it should render. Pending updates still have priorities so that they can be coalesced. We use a host config method to read the current time. This commit implements everything except that method, which currently returns a constant value. So this just proves that expiration times work the same as priorities when time is frozen. Subsequent commits will show the effect of advancing time. * Triangle Demo should use a class shouldComponentUpdate was removed from functional components. Running the demo shows, now that expiration is enabled, the demo does not starve. (Still won't run smoothly until we add back the ability to resume interrupted work.) * Use a magic value for task expiration time There are a few cases related to sync mode where we need to distinguish between work that is scheduled as task and work that is treated like task because it expires. For example, batchedUpdates. We don't want to perform any work until the end of the batch, regardless of how much time has elapsed. * Use current time to calculate expiration time * Add unit tests for expiration and coalescing * Delete unnecessary abstraction * Move performance.now polyfill to ReactDOMFrameScheduling * Add expiration to fuzz tester * Expiration nits - Rename Done -> NoWork - Use max int32 instead of max safe int - Use bitwise operations instead of Math functions
An expiration time represents a time in the future by which an update should flush. The priority of the update is related to the difference between the current clock time and the expiration time. This has the effect of increasing the priority of updates as time progresses, to prevent starvation.