Repository: react
Issue: Root-level performance events
Labels: React Core Team

DevTools (and other perf related infra) would benefit from being able to observer the following:
* Starting (or resuming) work on a root.
* Completing (or yielding) work on a root.
* Committing work for a root.
* A particularly component suspending during a render.
* A suspended (identified by a component stack) promise resolving/retrying.
* An update being scheduled (e.g. `setState`) by a component (identified by a component stack).
* A root-level `render` call being made.

In order to fit within the context of the scheduler, we would also want to emit/capture the following events:
* The scheduler is starting to run tasks at a specific priority.
* The scheduler is stopping.
* The scheduler currently has X number of tasks scheduled for each priority. (Maybe this could be logged periodically? Or along with each time we stopped work at a priority?)

We could use this info to e.g. draw a timeline in the Profiler UI that showed CPU/IO work breakdown.

If we used a mechanism like `performance.mark` to record these events as part of the browser's profiling session, we could also include information about _unscheduled_ JavaScript- as well as other important related concepts, like network requests, paints, etc.

### Sequencing
- [ ] (ʀᴇᴀᴄᴛ) Add logging to react-reconciler and scheduler packages.
    * e.g. Make sure we are logging start/stop/yield/cancel for renders correctly
    * e.g. Make sure state-updates are being logged with the scheduled priority (not just the current)
    * Research: Make sure performance.mark is actually fast enough to use.
    * Add some basic test coverage to ensure we are marking the expected events in the expected order.
    * (Do not expose component stacks for now).
- [ ] (ʀᴇᴀᴄᴛ) Design API for DevTools to start/stop performance marking.
    * This shouldn’t be on by default, only when we’re actually profiling.
- [ ] (ʀᴇᴀᴄᴛ) Design public API (if we want one) for collecting and logging these new data points.
    * Web-speed would probably like to collect this data.
- [ ] (ᴅᴇᴠᴛᴏᴏʟs) [Parse Chrome](https://docs.google.com/document/d/1CvAClvFfyA5R-PhYUmn5OOQtYMH4h6I0nSsKchNAySU/preview) performance profile JSON output.
    * Filter unsupported event types.
    * Massage data slightly (e.g. combine multiple micro-yields into a single task).
- [ ] (ᴅᴇᴠᴛᴏᴏʟs) Create visualization (chart) UI for data.
    * Turn individual events (or “B” and “E” pairs) into graphics on a timeline.
    * Needs exploratory prototyping / design work.
- [ ] (ᴅᴇᴠᴛᴏᴏʟs) Create zoom-and-pan controls.
    * Something that works similar to Chrome’s Performance tab probably.
    * Enables zooming in on regions of profiling data.
    * Would be nice to build using the interactions stuff Dominic/Nicolas made for Comet
    * Consider not zooming all the way out by default (but setting some max zoom-out cap?)
    * Consider adding windowing logic to avoid rendering things outside of the viewport?
- [ ] (ᴅᴇᴠᴛᴏᴏʟs) Add [Chrome debug protocol](https://chromedevtools.github.io/devtools-protocol/tot/Profiler#method-start) support
    * Requires [“debugger” permission](https://developer.chrome.com/extensions/debugger), but it should be an [optional permission](https://developer.chrome.com/extensions/permissions) that we just-in-time prompt for.
- [ ] (ʀᴇᴀᴄᴛ/ᴅᴇᴠᴛᴏᴏʟs) Initial integration.
    * When user starts profiling React, Chrome’s profiling recorder should also be started.
        * We may want to enable running one without the other? Depends on how much overhead.
    * Also call the React hook to enable performance.mark calls for scheduler and react-dom.
- [ ] (ʀᴇᴀᴄᴛ/ᴅᴇᴠᴛᴏᴏʟs) Improved integration.
    * Add component stack ID to marked “update state” and “suspend” events (e.g. “state-update-normal-123”)
    * Read actual component stack string from DevTools using this ID.
- [ ] (ʀᴇᴀᴄᴛ/ᴅᴇᴠᴛᴏᴏʟs) Explore implementing a queue size visualization
    * Would require a new event or a hook into scheduler to get the current queue size.