facebook / react

The library for web and native user interfaces.
https://react.dev
MIT License
224.98k stars 45.87k forks source link

Combine Profiler data sources #22529

Open bvaughn opened 2 years ago

bvaughn commented 2 years ago

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:

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:

Doing this has a few benefits:

It would have the following downside 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:

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.

tagalong420 commented 2 years ago
 I use Chrome Browser all the time and I run into that problem also. My

browser want load or it throws a error message (505 ) or a (404) i have got a error that was a (808) i don't know we're the 808 came from but the other two was Browser issues. If i can find the reports on it I'll send them to ya..

James Loftin

On Fri, Oct 8, 2021, 10:56 AM Brian Vaughn @.***> wrote:

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.

What if we took a step back and revisited how the scheduling profiler worked?

Currently, the profiler is entirely driven off of Chrome performance profile data, which includes several React-specific user timing marks for things like updates, rendering/committing, suspense, etc. Recording a profile 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---")
  • 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:

  • 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.)

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/facebook/react/issues/22529, or unsubscribe https://github.com/notifications/unsubscribe-auth/AKVRGWUPTQADIGNOFYRAZ4DUF4IDDANCNFSM5FT5G3LQ .

bvaughn commented 2 years ago

Note that this issue is related to #22090.

bvaughn commented 2 years ago

Background info

Moving Timeline data out of User Timing marks and into DevTools provides a few benefits:

But it also has a major downside:

The above downside could be mitigated by profiling both with React DevTools and Chrome– but the user experience would be pretty awkward:

  1. Start profiling in React DevTools.
  2. Open the Performance tab and start profiling in Chrome.
  3. (Use the app...)
  4. Stop the Chrome profiler and export JSON data.
  5. Open React DevTools and stop profiling.
  6. Import the JSON data exported in step 4.

The question then is, is it worth supporting both (React DevTools in-memory samples and User Timing data). The simpler case (React DevTools only) is enough when sreenshots and other data aren't needed. User Timing marks are enough when we don't need the two profilers to be connected and we don't need component stacks.

The matrix below shows which feature(s) would be available should we choose to support both.

DevTools only Chrome only DevTools then Chrome
Legacy profiling data
Timeline: Updates, lanes, suspense
Timeline: Component stacks
Timeline: JavaScript samples, screenshots, etc

Open questions

Given the above constraints, which combination of modes do we want to support? @lunaruan and I chatted out of band today and agreed on the following:

Pros Cons Support?
Record in DevTools Simplest UX. Missing screenshots and JavaScript samples.
Record in Chrome Performance Has screenshots and JavaScript samples. Slightly awkward UX. No legacy profiling data.
Record in both (and merge) All of the data Really awkward UX; complicated programming logic.