102 Commits
Author SHA1 Message Date
RickyandGitHub 30b47103d4 Fix spelling errors and typos (#19138) 2020-06-15 19:59:44 -04:00
Rick Hanlonandshengxinjing 655affa302 Clarifications
Co-authored-by: shengxinjing <316783812@qq.com>
2020-06-12 21:09:29 -04:00
Sebastian MarkbågeandGitHub 2325375f4f Nit: add suffix _TIMEOUT consistently in scheduler (#18696) 2020-04-21 19:44:42 -07:00
Sebastian MarkbågeandGitHub 5474a83e25 Disable console.logs in the second render pass of DEV mode double render (#18547)
* Disable console log during the second rerender

* Use the disabled log to avoid double yielding values in scheduler mock

* Reenable debugRenderPhaseSideEffectsForStrictMode in tests that can
2020-04-08 16:43:51 -07:00
Sebastian MarkbågeandGitHub 3e94bce765 Enable prefer-const lint rules (#18451)
* Enable prefer-const rule

Stylistically I don't like this but Closure Compiler takes advantage of
this information.

* Auto-fix lints

* Manually fix the remaining callsites
2020-04-01 12:35:52 -07:00
Andrew Clark ad445b127e Update package.jsons for 16.13.1 patch relase 2020-03-19 12:58:31 -07:00
Sunil PaiandGitHub c1c5499cc3 update version numbers for 16.13 (#18143)
also includes a bugfix when downloading error codes from circleci.
2020-02-26 20:33:29 +00:00
Andrew ClarkandGitHub 9dba218d93 [Mock Scheduler] Mimic browser's advanceTime (#17967)
The mock Scheduler that we use in our tests has its own fake timer
implementation. The `unstable_advanceTime` method advances the timeline.

Currently, a call to `unstable_advanceTime` will also flush any pending
expired work. But that's not how it works in the browser: when a timer
fires, the corresponding task is added to the Scheduler queue. However,
we will still wait until the next message event before flushing it.

This commit changes `unstable_advanceTime` to more closely resemble the
browser behavior, by removing the automatic flushing of expired work.

```js
// Before this commit
Scheduler.unstable_advanceTime(ms);

// Equivalent behavior after this commit
Scheduler.unstable_advanceTime(ms);
Scheduler.unstable_flushExpired();
```

The general principle is to prefer separate APIs for scheduling tasks
and flushing them.

This change does not affect any public APIs. `unstable_advanceTime` is
only used by our own test suite. It is not used by `act`.

However, we may need to update tests in www, like Relay's.
2020-02-04 11:35:21 -08:00
Dan AbramovandGitHub e706721490 Update Flow to 0.84 (#17805)
* Update Flow to 0.84

* Fix violations

* Use inexact object syntax in files from fbsource

* Fix warning extraction to use a modern parser

* Codemod inexact objects to new syntax

* Tighten types that can be exact

* Revert unintentional formatting changes from codemod
2020-01-09 14:50:44 +00:00
Dan AbramovandGitHub b979db4e72 Bump Prettier (#17811)
* Bump Prettier

* Reformat

* Use non-deprecated option
2020-01-09 13:54:11 +00:00
伊撒尔andAndrew Clark 7309c5f934 Use zero-fill right shift instead of Math.floor (#17616)
For positive numbers, binary displacement is better.
2019-12-17 11:16:04 -08:00
Dan AbramovandGitHub 0cf22a56a1 Use console directly instead of warning() modules (#17599)
* Replace all warning/lowPriWarning with console calls

* Replace console.warn/error with a custom wrapper at build time

* Fail the build for console.error/warn() where we can't read the stack
2019-12-14 18:09:25 +00:00
Luna Ruan 9a5f28dbed update version numbers for 16.12 2019-11-14 16:02:18 -08:00
Andrew ClarkandGitHub a2e05b6c14 [Scheduler] Delete old rAF implementation (#17252)
We've been using the message loop version for a while. Time to delete.
2019-11-01 13:32:22 -07:00
Andrew Clark 8075c8505b Update local package versions for 16.10 release 2019-10-22 14:30:06 -07:00
Andrew ClarkandGitHub cd1b167ad4 [Scheduler Profiler] Use microsecond precision (#17010)
The `performance.now` returns a timestamp in milliseconds as a float.
The browser has the option to adjust the precision of the float, but
it's usually more precise than a millisecond. However, this precision
is lost when the timestamp is logged by the Scheduler profiler, because
we store the numbers in an Int32Array.

This change multiplies the millisecond float value by 1000, giving us
three more degrees of precision.
2019-10-07 09:16:18 -07:00
Andrew Clark d256f88ac6 Update local version numbers for 16.10.2 release 2019-10-03 14:14:10 -07:00
Andrew Clark 2a264a9dbe Update local version numbers for 16.10.1 release 2019-09-28 21:41:42 -07:00
Andrew Clark 93f5f11b79 Update local version numbers for 16.10 release 2019-09-27 13:31:35 -07:00
Andrew ClarkandGitHub 901139c291 [scheduler][profiler] Start time of delayed tasks (#16809)
Fixes a bug in the Scheduler profiler where the start time of a delayed
tasks is always 0.
2019-09-17 10:24:48 -07:00
HeavenandAndrew Clark cdbfa5044b fix typo inteval -> interval & continutation -> continuation (#16760)
* fix typo alterate -> alternate

* fix typo interal -> interval & continutation -> continuation
2019-09-14 12:51:20 -07:00
Andrew ClarkandGitHub 45b6443c90 Spelling is fundamental (#16782) 2019-09-13 16:27:18 -07:00
Andrew ClarkandGitHub 45898d0be0 [Scheduler] Prevent event log from growing unbounded (#16781)
If a Scheduler profile runs without stopping, the event log will grow
unbounded. Eventually it will run out of memory and the VM will throw
an error.

To prevent this from happening, let's automatically stop the profiler
once the log exceeds a certain limit. We'll also print a warning with
advice to call `stopLoggingProfilingEvents` explicitly.
2019-09-13 15:50:25 -07:00
Andrew ClarkandGitHub 0a2215cc0e [Scheduler][www] Put profiling feature behind flag (#16757)
Our infra currently doesn't support loading a separate profiling
build of Scheduler. Until that's fixed, the recommendation is to load
a single build and gate the profiling feature behind a flag.

Alternative to #16659
2019-09-11 13:28:03 -07:00
Dan AbramovandGitHub 962dfc2c33 Remove experimental scheduler flags (#16672) 2019-09-05 20:08:06 +01:00
Dan AbramovandGitHub 040ca0fad7 Enable MessageLoop implementation by default (#16408) 2019-09-05 19:25:51 +01:00
Dan AbramovandSebastian Markbåge 0f6e3cd61c [Scheduler] Profiler Features (second try) (#16542)
* Revert "Revert "[Scheduler] Profiling features (#16145)" (#16392)"

This reverts commit 4ba1412305.

* Fix copy paste mistake

* Remove init path dependency on ArrayBuffer

* Add a regression test for cancelling multiple tasks

* Prevent deopt from adding isQueued later

* Remove pop() calls that were added for profiling

* Verify that Suspend/Unsuspend events match up in tests

This currently breaks tests.

* Treat Suspend and Resume as exiting and entering work loop

Their definitions used to be more fuzzy. For example, Suspend didn't always fire on exit, and sometimes fired when we did _not_ exit (such as at task enqueue).

I chatted to Boone, and he's saying treating Suspend and Resume as strictly exiting and entering the loop is fine for their use case.

* Revert "Prevent deopt from adding isQueued later"

This reverts commit 9c30b0b695.

Unnecessary because GCC

* Start counter with 1

* Group exports into unstable_Profiling namespace

* No catch in PROD codepath

* No label TODO

* No null checks
2019-08-22 13:58:12 -07:00
Dan AbramovandGitHub 2d68bd0960 Fix message loop behavior when host callback is cancelled (#16407)
* Add a regression test for cancelCallback with message loop

* If there's nothing scheduled, we're not running

* Add more tests from #16271
2019-08-19 21:20:21 +01:00
Dan AbramovandGitHub 4ba1412305 Revert "[Scheduler] Profiling features (#16145)" (#16392)
This reverts commit a34ca7bce6.
2019-08-14 20:02:41 +01:00
Andrew ClarkandGitHub a34ca7bce6 [Scheduler] Profiling features (#16145)
* [Scheduler] Mark user-timing events

Marks when Scheduler starts and stops running a task. Also marks when
a task is initially scheduled, and when Scheduler is waiting for a
callback, which can't be inferred from a sample-based JavaScript CPU
profile alone.

The plan is to use the user-timing events to build a Scheduler profiler
that shows how the lifetime of tasks interact with each other and
with unscheduled main thread work.

The test suite works by printing an text representation of a
Scheduler flamegraph.

* Expose shared array buffer with profiling info

Array contains

- the priority Scheduler is currently running
- the size of the queue
- the id of the currently running task

* Replace user-timing calls with event log

Events are written to an array buffer using a custom instruction format.
For now, this is only meant to be used during page start up, before the
profiler worker has a chance to start up. Once the worker is ready, call
`stopLoggingProfilerEvents` to return the log up to that point, then
send the array buffer to the worker.

Then switch to the sampling based approach.

* Record the current run ID

Each synchronous block of Scheduler work is given a unique run ID. This
is different than a task ID because a single task will have more than
one run if it yields with a continuation.
2019-08-13 19:01:17 -07:00
Desmond BrandandAndrew Clark 7a7e792a6f Make SchedulerMinHeap flow strict (#16351)
@acdlite while browsing Twitter, I saw [an opportunity][1] to do
something more productive than browsing Twitter.

[1]: https://twitter.com/acdlite/status/1160247965908234240

Test plan:

`yarn flow-ci`, `yarn test-prod`, `yarn lint`
2019-08-10 13:44:23 -07:00
Andrew ClarkandGitHub e349da19b8 [Scheduler] Temporarily remove wrapper function (#16345)
This code is being compiled incorrectly by something in the Facebook
build pipeline. I'm removing it temporarily to unblock the sync while
we investigate.
2019-08-09 18:08:29 -07:00
Andrew ClarkandGitHub d77c6232d3 [Scheduler] Store Tasks on a Min Binary Heap (#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
2019-08-08 16:18:05 -07:00
Andrew Clark 85d05b3a4d Bump package.json versions 2019-08-08 14:24:39 -07:00
Andrew ClarkandGitHub 75ab53b9e1 [scheduler] Yield many times per frame, no rAF (#16214)
Adds experimental flag to yield many times per frame using a message
event loop, instead of the current approach of guessing the next vsync
and yielding at the end of the frame.

This new approach forgoes a `requestAnimationFrame` entirely. It posts a
message event and performs a small amount of work (5ms) before yielding
to the browser, regardless of where it might be in the vsync cycle. At
the end of the event, if there's work left over, it posts another
message event.

This should keep the main thread responsive even for really high frame
rates. It also shouldn't matter if the hardware frame rate changes after
page load (our current heuristic only detects if the frame rate
increases, not decreases).

The main risk is that yielding more often will exacerbate main thread
contention with other browser tasks.

Let's try it and see.
2019-07-26 15:43:57 -07:00
Andrew ClarkandGitHub c0830a0e63 [Scheduler] Test browser implementation details (#16198)
The Scheduler implementation uses browser APIs like `MessageChannel`,
`requestAnimationFrame`, and `setTimeout` to schedule work on the main
thread. Most of our tests treat these as implementation details;
however, the sequence and timing of these APIs are not precisely
specified, and can vary wildly across browsers.

To prevent regressions, we need the ability to simulate specific edge
cases that we may encounter in various browsers.

This adds a new test suite that mocks all browser methods used in our
implementation. It assumes as little as possible about the order and
timing of events. The only thing it assumes is that
requestAnimationFrame is passed a frame time that is equal to or less
than the time returned by performance.now. Everything else can be
controlled at will.

It also includes Scheduler-specific invariants, e.g. only one rAF
callback can be scheduled at a time.

It overlaps slightly with the existing SchedulerDOM-test suite, which
also mocks the browser APIs, but exposes a higher-level set of testing
primitives. I will consolidate the two suites in a follow-up.
2019-07-25 15:53:14 -07:00
Andrew ClarkandGitHub 19354db511 [Scheduler] Add names to inline functions (#16180)
Noticed when looking at the performance profiler with Luna that it's
hard to tell which event causes `performWorkUntilDeadline` to fire
because these functions are anonymous.
2019-07-23 11:08:24 -07:00
Andrew ClarkandGitHub bff7abf6ba [Scheduler][Bugfix] Multiple rAFs in same frame (#16184)
Always sets `isRAFLoopRunning` back to false when an animation frame is
scheduled. Fixes a bug where two rAFs fire in the same frame, but the
second one exits and fails to schedule a new rAF.

Fixes bug observed in Safari.
2019-07-23 10:44:27 -07:00
Andrew ClarkandGitHub 3f2cafe8be [WIP][Scheduler] Use rIC to post first callback (#16166)
Scheduler uses `requestAnimationFrame` to post tasks to the browser.
If this happens at the beginning of a frame, the callback might not
fire until the subsequent frame, even if the main thread is idle.

Our theory was that this wouldn't be an issue in practice, because once
the first rAF fires, we schedule the next rAF as early as possible in
that frame. Combined with our heuristic for computing frame deadlines,
we shouldn't get any idle time in between frames — only before the
*first* frame.

This reasoning holds true when you have a small number of large tasks,
such as the ones posted by React. The idle time before the task starts
is negligible relative to the lifetime of the entire task.

However, it does not hold if you have many small tasks posted over a
span of time, perhaps spawned by a flurry of IO events. In this case,
instead of single, contiguous rAF loop preceded by an idle frame, you
get many rAF loops preceded by many idle frames. Our new theory is that
this is contributing to poor main thread utilization during page loads.

To try to reclaim as much idle time as possible, this PR adds two
experimental flags. The first one adds a `requestIdleCallback` call to
start the rAF loop, which will fire before rAF if there's idle time left
in the frame. (We still call rAF in case there isn't. We start working
in whichever event fires first.)

The second flag tries a similar strategy using `setTimeout(fn, 0)`. If
the timer fires before rAF, we'll assume that the main thread is idle.

If either `requestIdleCallback` or `setTimeout` fires before rAF, we'll
immediately peform some work. Since we don't have a real frame time that
we can use to compute the frame deadline, we'll do an entire frame
length of work. This will probably push us past the vsync, but this is
fine because we can catch up during the next frame, by which point a
real rAF will have fired and the loop can proceed the same way it
does today.

Test plan: Try this on Facebook to see if it improves load times
2019-07-22 13:12:33 -07:00
Andrew ClarkandGitHub 2bd88e38aa [Scheduler] Bugfix: Cancelling a continuation (#16151)
Cancelling the original task should also cancel its continuation.
2019-07-22 13:10:33 -07:00
Andrew ClarkandGitHub d2d9b1f701 [Scheduler] Support inferring priority from stack (#16105)
When executing a task, wraps the callback in an extra function whose
name includes the current priority level. Profiling tools with access
to function names can use this to determine the priority of the task.
2019-07-10 18:59:44 -07:00
Andrew ClarkandGitHub 4d307de458 Prefix mock Scheduler APIs with _unstable (#15999)
For now this is only meant to be consumed via `act`.
2019-06-26 12:16:08 -07:00
Andrew Clark 4189f712c1 [Scheduler] Increase max frame length to 300
Forgot to apply this change before merging.

https://github.com/facebook/react/pull/15959#discussion_r296429705
2019-06-22 01:38:19 -07:00
Andrew Clark 595c9414ba [Scheduler] Fix navigator.isInputPending call
Must be called as a method.
2019-06-22 00:50:13 -07:00
Andrew ClarkandGitHub e7fcfe1047 [scheduler] Put isPendingInput behind a flag (#15962) 2019-06-22 00:46:27 -07:00
Andrew ClarkandGitHub 6568a79931 [Scheduler] requestPaint (#15960)
* [Scheduler] requestPaint

Signals to Scheduler that the browser needs to paint the screen. React
will call it in the commit phase. Scheduler will yield at the end of
the current frame, even if there is no pending input.

When `isInputPending` is not available, this has no effect, because we
yield at the end of every frame regardless.

React will call `requestPaint` in the commit phase as long as there's at
least one effect. We could choose not to call it if none of the effects
are DOM mutations, but this is so rare that it doesn't seem worthwhile
to bother checking.

* Fall back gracefully if requestPaint is missing
2019-06-22 00:15:09 -07:00
Andrew ClarkandGitHub 8d4ddd33ac [Scheduler] Yield less if there's no pending input (#15959)
At the end of each frame, Scheduler yields control of the main thread so
the browser can execute important tasks; most importantly, painting the
screen and responding to user input. There's some overhead involved in
regaining control of the main thread, so we'd like to yield as
infrequently as possible to keep the UI responsive.

The reason we yield on every frame is because there's no way for us to
know whether we're blocking user input.

`isInputPending` is an experimental browser API that gives us this
information. It tells us whether there's a pending user input, which
also means it tells us if there's *not* a pending user input. We can use
this signal to decide whether it's OK not to yield.

There's a max frame length after which we'll yield regardless, as a
precaution against blocking non-input tasks that we don't know about.
2019-06-22 00:05:38 -07:00
Andrew ClarkandGitHub 35ef78de3e [Scheduler] Integrated timers (#15911)
Adds a `delay` option to `scheduleCallback`. When specified, the task is
not scheduled until after the delay has elapsed.

Delayed tasks are scheduled on a timer queue maintained by Scheduler,
instead of directly with the browser. The main benefit is to reduce the
number of native browser timers that Scheduler's `message` event handler
has to contend with; so, after yielding to the browser at the end of the
frame, Scheduler will more quickly regain control of the main thread.
Because we're able to flush the timer queue without yielding to browser
timer events, there's also less task switching overhead (though in the
absence of `isInputPending`, this is mostly a theoretical win since we
yield every frame regardless).

If the queue of non-delayed tasks is non-empty — that is, if there is
pending CPU bound work — Scheduler is able to avoid a browser timer
entirely by periodically checking its own timer queue while flushing
tasks (inside the `message` event handler). Once the CPU-bound work is
complete, if there are still pending delayed tasks, Scheduler will
schedule a single browser timer that fires once the earliest delay
has elapsed.
2019-06-19 16:05:07 -07:00
Andrew ClarkandGitHub 3af91eb8ce [Scheduler] Use continuation pattern for posting host callback (#15910)
* [scheduler] Internal rename: Callback -> Task

Rename Callback type to Task. Does not affect the public API, only
internal names, though eventually we'll probably want to align with the
WICG Main-thread Scheduling proposal
(https://github.com/WICG/main-thread-scheduling).

* [scheduler] flushFirstTask() -> flushTask(task)

Pass task as an argument to `flushTask` instead of using a module-
level variable.

* [scheduler] Add startTime field

This does not change any semantics, but in the future `startTime` may
represent a future time, to support delayed tasks.

* [Scheduler] Use continuation pattern for host cb

As I prepare to implement integrated timers, I noticed some
peculiarities in the Scheduler implementation that could afford to be
cleaned up.

This is a refactor and shouldn't affect any observable behavior; mostly
it removes some concepts that existed in earlier iterations of Scheduler
and are no longer needed.

The main change is to how the DOM implementation schedules an additional
callback before yielding to the main thread. It used to follow the same
code path for scheduling task; now it has its own branch directly
inside the message event handler. The special case for error handling
— where we call `postMessage` immediately without waiting for rAF —
has similarly been localized inside the catch block of the message
event handler.
2019-06-19 15:57:33 -07:00
Sunil PaiandGitHub d278a3ff8b act() - s / flushPassiveEffects / Scheduler.unstable_flushWithoutYielding (#15591)
* s/flushPassiveEffects/unstable_flushWithoutYielding

a first crack at flushing the scheduler manually from inside act(). uses unstable_flushWithoutYielding(). The tests that changed, mostly replaced toFlushAndYield(...) with toHaveYielded(). For some tests that tested the state of the tree before flushing effects (but still after updates), I replaced act() with bacthedUpdates().

* ugh lint

* pass build, flushPassiveEffects returns nothing now

* pass test-fire

* flush all work (not just effects), add a compatibility mode

of note, unstable_flushWithoutYielding now returns a boolean much like flushPassiveEffects

* umd build for scheduler/unstable_mock, pass the fixture with it

* add a comment to Shcduler.umd.js for why we're exporting unstable_flushWithoutYielding

* run testsutilsact tests in both sync/concurrent modes

* augh lint

* use a feature flag for the missing mock scheduler warning

I also tried writing a test for it, but couldn't get the scheduler to unmock. included the failing test.

* Update ReactTestUtilsAct-test.js

- pass the mock scheduler warning test,
- rewrite some tests to use Scheduler.yieldValue
- structure concurrent/legacy suites neatly

* pass failing tests in batchedmode-test

* fix pretty/lint/import errors

* pass test-build

* nit: pull .create(null) out of the act() call
2019-05-16 17:12:36 +01:00