-
Notifications
You must be signed in to change notification settings - Fork 50.4k
Description
There are a few concerns that I heard about ReactPerf, in the order of importance:
- (1) It is gated by
__DEV__but React Native wants to have a way to enable it in production builds and pass the accumulated info into systrace - (2) It is often broken by refactoring
- (3) It appears generic but depends on specific module and method names
- (4) It has some obscure bugs that are hard to fix because of the coupling
- (5) The
console.table()visualization is poor - (6) We are working on a new DevTools API so they should align
If I’m mistaken here, please let me know!
In #5306, we started introducing a new set of APIs for first-class instrumentation. It makes sense that we transition ReactPerf to the new API, and fix some of these issues while we’re at it.
I talked to some people on the React Native about this. What I understand so far is:
ASAP
- We want to remove
ReactPerffunction wrapping completely (addresses 2, somewhat mitigates overhead from fixing 1) - We want to create a devtool like
ReactDOMDebugTool, e.g.ReactPerfTool(addresses 6) - Unlike
ReactDOMDebugTool,ReactPerfToolwill not be gated by__DEV__(addresses 1) ReactPerfToolwill havestartMeasurement()andendMeasurement()methods for profiling functions (addresses 1)- It can have more granular methods for specific parts of React lifecycle if needed (addresses 2, 3, 5)
- Calls to
ReactPerfToolwill be gated by a runtime flag, e.g.ReactPerfTool.isActive(addresses 1)
In the Future
- Rather than reach out into the profiled functions,
startMeasurement()will accept arbitrary arguments (addresses 3) - We would separate generating user-meaningful data from its accumulation so it would be easy to test (addresses 4)
- (Bonus) We can use a noop decorator + Babel plugin to insert
if (ReactPerfTool.isActive) ReactPerfTool.startMeasurement()and.endMeasurement()calls (mitigates pain and potential breakage from addressing 1) - (Bonus) Rather than
console.table()API we can provide a component that interprets that data and displays it in an overlay, both on web and native (addresses 5)
The decorator + Babel plugin part is the one I’m not sure about because it would involve complicating tooling. On the other hand, it will allow adding performance measurement to any functions in the codebase without risking having early returns, missing endMeasurement() calls, and similar breakage during refactorings.
The first actionable step, in my opinion, would be to remove the function wrapping and the __DEV__ gate from the existing ReactPerf, and replace measure() with explicit startMeasurement() and endMeasurement() calls gated by ReactPerf.isActive wherever it is used.
We would still pass the function as an argument so we don’t have to rewrite everything at once, but this would give the RN team more freedom, and unlock future refactorings. We can also combine this with introducing decorator + Babel transform if this is the way we want to go, to avoid adding manual startMeasurement() and endMeasurement() calls all over the place.
Does this make sense? What have I missed?