MLH-Fellowship / scheduling-profiler-prototype

Custom profiler prototype for React's concurrent mode

Home Page:https://react-scheduling-profiler.vercel.app/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Fix flamegraph, React perf data alignment

taneliang opened this issue · comments

Context

The original prototype's React events/measures are not aligned with their corresponding events in the flamechart:

image

After transitioning the canvas to V2 data, this is what the issue looks like. The blue dot corresponds to the hovered flamegraph event.

image

Investigation

  • Check if #35 is the cause. It is not; changing the duration just scales both graphs together.

  • Fix our profiler data's startTime to match Speedscope's data. Much more success here; the result is that the React data is now misaligned less (but how much exactly and why is still not confirmed):
    image

    We were previously computing the startTime by taking the very first non-zero ts value from the array of raw TimelineEvents in the profile JSON file. The React marks' timestamps were then computed in relation to that startTime.

    However, this does not follow what Speedscope does. Speedscope retrieves the startTime from a TimelineEvent with name === 'Profile'. We use the start (and end) times from Speedscope's computed nodes to render the flamechart events. Speedscope gets the value of start from the first value of the timeDeltas list. https://github.com/v8/v8/blob/44bd8fd7/src/inspector/js_protocol.json#L1486 tells us that this start value is relative to the startTime of the Profile TimelineEvent. This means that our profiling data's startTime is different from the startTime that the flamechart is using, which leads to a displacement.

    As such, I have set our profiling data's startTime to this Profile TimelineEvent's startTime. Although there's still a displacement, I have some confidence based on the above reasoning that we're on the right track and that this is one of the causes of the misalignment.

  • Check if the displacement is caused by canvas rendering logic, or if our preprocessing code is wrong, or if the raw data is already misaligned. Update:

    • We can rule out canvas rendering logic as a possible cause, as we're using the same timestampToPosition utility functions in the React mark, React measure, and flamechart rendering functions.
    • It looks like the's a difference between the flamechart event's start and our React event's timestamp. This points to a cause in either preprocessDataV2 or the raw data.
  • Check if the displacement is consistently 15ms. Update: it's not; another profile has a 5ms difference:
    image

  • Check if the displacement changes with time.

    • Update 1: it seems to change with the number of timeline events elapsed, i.e. the displacement seems to increase with time but only where there are timeline events. Displacements look similar when there is a long gap where there are no events.

    • Update 2: The seems to be caused by https://github.com/jlfwong/speedscope/blob/b7806a1c5f079efb4e2d5c9cb0b7d3f1346b0e82/src/import/chrome.ts#L248, which zeroes out any negative time deltas. As there are quite a few negative time deltas, the errors seem to have accumulated.
      image

      Disabling the zeroing results in the flamegraph being aligned with the events (🎉🎉🎉), but I'm not sure how this will affect the flamegraph. More research needed.
      image

  • Check if there's an endTime computed by Speedscope that we have to align to. jlfwong/speedscope#159 (comment) suggests that there is no endTime now, and Speedscope doesn't seem to calculate it.

  • Figure out how to retrieve startTime from Speedscope's computed profile. I couldn't figure this out, so I'm currently just taking the first TimelineEvent where name === 'Profile'. This likely won't be reliable as Speedscope's logic suggests that there may be multiple Profile and CpuProfile events.