Skip to content

Combine Profiler data sources #22529

Open
@bvaughn

Description

@bvaughn

Time sensitive API changes (ideally these should land before 18.0 release):

(DevTools will decide whether or not to store the data or log User Timing marks, since it knows when it's profiling.)

Additional, non-blocking changes:

DevTools hook changes:

DevTools Timeline changes:

Future optimizations:

  • Consider merging logic between profilingHooks and preprocessData to remove redundancies. If the code was moved somewhere else, then profilingHooks could call it during rendering and preprocessData could call it too (as it processed each mark) and avoid having to build up the same in-memory representations.
  • Double check that internalModuleSourceToRanges is being initialized correctly for the in-memory profiler. (Technically this doesn't matter yet, since we don't have JavaScript samples for the in memory profiler– but still.)

Motivation

There are currently two React profilers: the "legacy" profiler (which reads data from Fibers during the commit phase) and the "scheduling" profiler (which reads data in the form of User Timing marks in a Chrome performance profile). This separation is confusing as both profilers live in the same extension/app but import/export different types of data.

Let's take a step back and revisit how the scheduling profiler works...

Recording a profile currently requires a user to do the following:

  1. Click "record" in Chrome
  2. Use the app
  3. Click "stop" in Chrome
  4. Export the profile JSON
  5. Import it into the React DevTools

It would be nice if DevTools could start/stop recording and import the data itself, but the only way to do this is using the Chrome DevTools Protocol which would require the use of an extremely powerful permission that I don't think we would want to ask users for.

This approach also has the downside of not working with React Native (or non-Chrome browsers).

So why do we do it? We do it because the profile gives us a lot of nice extra data: CPU samples of the JavaScript stack, Network requests, screenshots (if enabled), user events (e.g. "click").

But we don't need this data. The scheduling profiler could still be a useful tool even if included only the React specific marks.

My proposal then is that we consider doing this:

  • Replace the user timing API with a direct React-to-DevTools API (where these marks are logged to DevTools directly).
  • When profiling starts in React DevTools, generate a unique ID string
  • Log this unique ID to the User Profiling API along with each commit (e.g. "react-sync-marker-<uid>-<index>-<timestamp>")
  • Allow users to export/import additional native profiling information (which can be aligned using the sync marks) but is not required.

Doing this has a few benefits:

  • We could start both profilers and join the commit and scheduling profiler data streams (huge benefit).
  • It would make the profiler easier to use in the simple case (if you didn't want/need native profiler info) since you could start/stop it from within React DevTools.
  • It would let us add component and call stacks without the extra serialization overhead.

It would have the following downside though:

  • Recording profiles with native information would be a little more complicated, since you'd need to start React DevTools and then start the browser profiler. (We could show instructions for doing this in the DevTools profiler though.)

A note about component and call stacks

The scheduling profiler currently shows component names for things like state-updates (e.g. "state update scheduled by Foo") but it does not include component or call stacks. These would both be useful because:

  • Component stack would help identify which instance of foo was e.g. scheduling the update
  • Call stack would show e.g. which piece of state was being updated (and by what)

The reason we don't include this information is because we won't want to pay the cost of string serializing it all and logging it as a User Timing mark.

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions