Skip to content

Commit d77c623

Browse files
authored
[Scheduler] Store Tasks on a Min Binary Heap (facebook#16245)
* [Scheduler] Store Tasks on a Min Binary Heap Switches Scheduler's priority queue implementation (for both tasks and timers) to an array-based min binary heap. This replaces the naive linked-list implementation that was left over from the queue we once used to schedule React roots. A list was arguably fine when it was only used for roots, since the total number of roots is usually small, and is only 1 in the common case of a single-page app. Since Scheduler is now used for many types of JavaScript tasks (e.g. including timers), the total number of tasks can be much larger. Binary heaps are the standard way to implement priority queues. Insertion is O(1) in the average case (append to the end) and O(log n) in the worst. Deletion is O(log n). Peek is O(1). * Sophie nits
1 parent 95767ac commit d77c623

File tree

3 files changed

+171
-242
lines changed

3 files changed

+171
-242
lines changed

packages/react-dom/src/__tests__/ReactUpdates-test.js

+3-15
Original file line numberDiff line numberDiff line change
@@ -1631,6 +1631,7 @@ describe('ReactUpdates', () => {
16311631
ReactDOM.render(<App />, container);
16321632
while (error === null) {
16331633
Scheduler.unstable_flushNumberOfYields(1);
1634+
Scheduler.unstable_clearYields();
16341635
}
16351636
expect(error).toContain('Warning: Maximum update depth exceeded.');
16361637
expect(stack).toContain('in NonTerminating');
@@ -1653,34 +1654,21 @@ describe('ReactUpdates', () => {
16531654
React.useEffect(() => {
16541655
if (step < LIMIT) {
16551656
setStep(x => x + 1);
1656-
Scheduler.unstable_yieldValue(step);
16571657
}
16581658
});
1659+
Scheduler.unstable_yieldValue(step);
16591660
return step;
16601661
}
16611662

16621663
const container = document.createElement('div');
16631664
act(() => {
16641665
ReactDOM.render(<Terminating />, container);
16651666
});
1666-
1667-
// Verify we can flush them asynchronously without warning
1668-
for (let i = 0; i < LIMIT * 2; i++) {
1669-
Scheduler.unstable_flushNumberOfYields(1);
1670-
}
16711667
expect(container.textContent).toBe('50');
1672-
1673-
// Verify restarting from 0 doesn't cross the limit
16741668
act(() => {
16751669
_setStep(0);
1676-
// flush once to update the dom
1677-
Scheduler.unstable_flushNumberOfYields(1);
1678-
expect(container.textContent).toBe('0');
1679-
for (let i = 0; i < LIMIT * 2; i++) {
1680-
Scheduler.unstable_flushNumberOfYields(1);
1681-
}
1682-
expect(container.textContent).toBe('50');
16831670
});
1671+
expect(container.textContent).toBe('50');
16841672
});
16851673

16861674
it('can have many updates inside useEffect without triggering a warning', () => {

0 commit comments

Comments
 (0)