-
Notifications
You must be signed in to change notification settings - Fork 46.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add new ReactPerf #6046
Add new ReactPerf #6046
Conversation
@gaearon updated the pull request. |
I want to verify whether my understanding of the constraints in #6015 (comment) is correct. Here is an example I came up with. @sebmarkbage @spicyj Can you please confirm whether this is right? RequirementsSay we’ve got three components. Regular Recursive BatchComponents mount (or updated) recursively like they normally do. Numbers correspond to the current time, phrases to events the Perf tool receives. The columns show whether the time period is counted towards
Funny BatchWe need to make sure that it is easy to introduce out-of-stack updates later. For example, we want a top-level update of As an extra safety measure, we will absurdly include an update of
Note how the Formal InputRelationships
Events
Desired OutputExclusive
Inclusive
Do these calculations look right? Is this the desired output for these scenarios? |
@gaearon updated the pull request. |
Yea, this looks right. I can't see how steps 13-14 could possibly happen but if it could, then yea, that would be the right call. The point of decoupling this is so that in theory, someone else could've implemented this perf tool without changing the core. Since you're effectively mapping the names of methods 1:1, it doesn't create much decoupling. If we change the algorithm, you would still have to go change the ReactNewPerf implementation. A good guideline is to put things that are likely to change together into the same file. So, if we can't decouple, we might as well put all of ReactNewPerf into ReactCompositeComponent etc. to make it easy to refactor. I understand that this is your later step "It should not rely on the rendering and mounting stack matching parent hierarchy". One suggestion that I have is that you could, have start and stop timer associated with component time in ReactNewPerf. E.g. That way we can restructure the order completely without changing ReactNewPerf. |
We could pass something like Is this what you’re getting at? |
Even better! |
Ideally the tree information would be exposed through the new devtools API, so perhaps it would be sufficient for the perf tools to use that rather than building another one specifically for perf? |
This looks good so far. I'm going to mark this as |
Can do that. But it’s not exposed yet, is it? Meaning I’d need to add these events to the devtool code myself. Currently I don’t have enough context about what kind of information DevTools want. I can start by firing notifications on the devtool for every lifecycle hook with the internal instance. Would that be sufficient? ReactNewPerf would tune in to "mounted" and "unmounted" events and use this as a chance to track the owners. If I do this, we’ll need to gate devtool API by something like |
Currently these events are exposed through the devtools (search for https://github.com/facebook/react-devtools/blob/master/backend/attachRenderer.js (Note that the terminology is a bit confusing there. The The "backend" part of the devtools is an event protocol designed by @jaredly to be sufficient to track the tree. A good start might be to mirror that API.
I think you mean the parents. We use the term "owner" for the thing that created the element which is not the same as the thing mounting it - which is the parent. To track inclusive time you need the parent. It is unfortunate that tracking the tree might add a lot of overhead but it is probably nice to be able to visualize this in terms of a full tree.
The idea is that we can check for Currently the devtools work in production mode because it just uses monkey patching. That sucks for optimizations and package size. Maybe a |
Note that a |
:) I am really enjoying this thread. I like to refer as the current devtools work as duck punch monkey patching since it is doing duck punch detection for ReactDOM 0.13, 0.14, 0.15, and RN. |
Thank you, this is very helpful.
Thanks for correcting me. I thought owners should be used for the inclusive calculation but I trust you that parents make more sense here. I don’t really understand the problem well enough yet to see why.
👍
Since this is all very confusing I’ll finish the implementation first, and then we’ll decide how to proceed with the feature flags both for Perf and tree tracking. |
Sure. If you want, you can also just add a temporary constant flag (always |
Currently, in |
@gaearon updated the pull request. |
@gaearon updated the pull request. |
3 similar comments
@gaearon updated the pull request. |
@gaearon updated the pull request. |
@gaearon updated the pull request. |
@gaearon updated the pull request. |
return flushHistory; | ||
} | ||
}, | ||
onBeginFlush() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you explain a bit on why the flush batch is important? Does it matter if the implementation batches or just does the work whenever?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this comes down to the way printWasted()
heuristic works. It says “count a render as wasted if no DOM operations below were made during the same batch”. I was trying to replicate the existing behavior so this is the main reason.
I think we may want to reconsider this as part of #6632. I’d leave it as is for now though.
@gaearon updated the pull request. |
1 similar comment
@gaearon updated the pull request. |
@gaearon updated the pull request. |
Add new ReactPerf (cherry picked from commit 98a8f49)
This is a work in progress on implementing new ReactPerf as discussed in #6015.
Per @sebmarkbage’s request, I decided to focus on removing dependencies on internal method names. Data will be explicitly passed to the perf tool from React methods, and we will attempt to not rely on the execution order.
Rather than refactor the existing code, I chose to create a new tool side by side so I can compare their output until I’m confident about correctness. I will later add
PROFILE
feature gates to the calls.totalTime
for flushestotalTime
twice for nested flushes (fixes a minor bug in ReactPerf)endMeasure()
displayNames
and other component informationcounts
andcreated
for componentsexclusive
times for componentsinclusive
times for components based on parent treeprintDOM()
printWasted()
ReactPerf
asreact-addons-perf
PROFILE
gate and put calls behind itWeakMap
in__PROFILE__
buildsReact.unstable_Instrumentation
get*()
methods and deprecatedprintDOM()
andgetMeasurementSummaryMap()
are still therePROFILE
start()
is called inside the lifecycle or, better, consider providing support for that. See also React Perf: "cannot set property totalTime of undefined" #2095, Call Perf method in setState callback #3436, https://github.com/lostthetrail/react-ssr-perf