Closed kidroca closed 3 years ago
Triggered auto assignment to @MonilBhavsar (Engineering
), see https://stackoverflow.com/c/expensify/questions/4319 for more details.
The other large portion of execution time is taken by sendDataToConnection
calls
It will be the focus of a separate ticket - #4592
sendDataToConnection
should be the easier problem to address as it isolated to Onyx.connect
cc @marcaaron
Should we maybe limit the scope of this to just refactoring withWindowDimensions
and create a separate ticket for ReportActionItem
?
I'd also be curious to see the effects on chat switching since we have done the test for web but not Android. I'd be curious to see what it does for us on the native side. Is it possible to do a similar trace? I don't have much experience with the hermes debugger but I thought maybe it would be possible to profile there?
I thought it would be possible to do this with the Hermes debugger in Flipper, but starting the profiler there seems to hang with "Initialising ..." For Android there's another way - it's part of the development menu. It would create a file, like the one shared here, that you can load inside Chrome I'll try it and post results
Since all of the hoverable popups should be noop on native, there would be less withWindowDimensions
components
After analysing this more the HOCs might only be 30-50% to blame, and the rest is due to the many instances of components that use them.
Most of the withWindowDimensions
are used by popups and modals
When we switch to a new chat all the components in the old chat that have componentWillUnmount
would run it
For example ContextMenuItem
uses willUnmount
and so there will be a lot of unmounting going on as each action item would have at least one menu with multiple menu items - that seems to be what's happening in the screenshot I've shared, but originally I've only traced it to withWindowDimensions
Yes the current scope is whatever we can do without massive changes and so far that seems only the withWindowDimensions
refactor
We had a test where all popups we removed. Perhaps for a future ticket we can make the same snapshot captured here and see if this big bar of unmounts gets smaller with no popup components
We can just try the withWindowDimensions
idea and see what happens - doesn't seem hard to do and we can eliminate it as a potential improvement. Worst case scenario some component will have less overhead. 🤷
Managed to get the profiler to work on Android and adding some tips for that in this PR if it helps at all
Marc, I assigned you as you are having context and working on this
Whoops! This issue is 2 days overdue. Let's get this updated quick!
ATM it's not possible to benchmark this with the new performance metrics, as TTI happens before the report screen mounts, where the most withWindowDimension
components are
We can add marks for chat switches and then do a couple of benchmarks - switch to large, medium, with images, etc... Then do the same after the HOC is updated with the suggested changes
ATM it's not possible to benchmark this with the new performance metrics, as TTI happens before the report screen mounts, where the most withWindowDimension components are
Got it. Sounds like this probably will not improve the TTI then. But that's fine - it maybe will help the chat switching as you've mentioned. For that, it might be good to have the Flipper metrics we are discussing in the other issue.
I think it might be a good idea to add mark
, measure
to libs/Performance.js
and have them implemented using react-native-performance
when canCapturePerformanceMetrics()
is true
, while otherwise they should be empty functions. This way we can hook them wherever we need to without constantly checking
Also seeing the plugin code, it might be possible to do something like
new PerformanceObserver((list) => {
list.getEntries()
.filter(entry => entry.name.endsWith('End'))
.forEach(entry => {
const end = entry.name;
const name = end.replace(/End$/, '');
const start = `${name}Start`;
performance.measure(name, start, end);
}
}).observe({type: 'mark', buffered: true});
This would allow us to only put start/end marks
inside the components we'd like to meter e.g.
ReportScreen_Start
mark inside SidebarLinks.onSelectRow
ReportScreen_End
mark inside ReportActionsView.recordTimeToMeasureItemLayout
while otherwise they should be empty functions. This way we can hook them wherever we need to without constantly checking
Yep, that sounds like a good idea.
This would allow us to only put start/end marks inside the components we'd like to meter
I like that too since it's one less thing to worry about. What if we did that, but also abstracted this detail so that we can just do something like...
Performance.start(CONST.TIMING.SOMETHING); // adds the `_start`
Performance.end(CONST.TIMING.SOMETHING); // adds the `_end`
👍 Even better I can submit a PR for this tomorrow
Submitted the PR It should allow us to see any improvements from the suggested changes on the Flipper timeline
Uh oh! This issue is overdue by 2 days. Don't forget to update your issues!
Gonna drop this to weekly for now. We are adding more metrics now which should make it easier to test theories.
I still think many HOCs could be bad, I'll re-capture data now that we have a new way of measuring performance (CAPTURE_METRICS)
I'll again measure chat switching (we have perf marks for those)
Both pre/post tests should happen after fresh login (storage is cleared on log out) and without scrolling to the past (which would add more data to storage and force you to pre-render more)
This issue has not been updated in over 15 days. eroding to Monthly issue.
P.S. Is everyone reading this sure this is really a near-term priority? Be brave: if you disagree, go ahead and close it out. If someone disagrees, they'll reopen it, and if they don't: one less thing to do!
Run some benchmarks on Android, it seems it's almost unaffected by the withWindowDimensions
HOC
Run 1 | Run 2 | Run 3 | Run 4 | Run 5 | Run 6 | Run 7 | Run 8 | Run 9 | Avg | |
---|---|---|---|---|---|---|---|---|---|---|
Native Launch | 243.0ms | 236.0ms | 256.0ms | 229.0ms | 232.0ms | 227.0ms | 208.0ms | 193.0ms | 236.0ms | 228.9ms |
Run JS Bundle | 718.0ms | 680.0ms | 658.0ms | 642.0ms | 749.0ms | 642.0ms | 647.0ms | 651.0ms | 695.0ms | 675.8ms |
TTI | 3070.9ms | 3104.4ms | 2955.4ms | 3141.0ms | 3331.1ms | 3010.0ms | 3164.1ms | 3018.8ms | 3046.3ms | 3.09sec |
Run 1 | Run 2 | Run 3 | Run 4 | Run 5 | Run 6 | Run 7 | Run 8 | Run 9 | Avg | |
---|---|---|---|---|---|---|---|---|---|---|
Native Launch | 231.0ms | 196.0ms | 230.0ms | 219.0ms | 243.0ms | 252.0ms | 228.0ms | 281.0ms | 228.0ms | 234.2ms |
Run JS Bundle | 653.0ms | 644.0ms | 644.0ms | 670.0ms | 650.0ms | 736.0ms | 701.0ms | 659.0ms | 706.0ms | 673.7ms |
TTI | 2903.1ms | 3031.6ms | 3140.3ms | 3048.2ms | 3183.4ms | 3064.0ms | 3098.1ms | 3107.9ms | 3052.6ms | 3.07sec |
Apart from that I've measured chat switch time, where I couldn't see any improvement
I also captured memory usage:
I'm closing this one We can reopen if we find anything new
If you haven’t already, check out our contributing guidelines for onboarding and email contributors@expensify.com to request to join our Slack channel!
What performance issue do we need to solve?
What is the impact of this on end-users?
List any benchmarks that show the severity of the issue
unmountHostComponents
withWindowDimensions
HOCswithOnyx
HOCsProfile data (you can load this in Chrome/Performance): https://u.pcloud.link/publink/show?code=XZwvKwXZpXUhxs7Vdr7kaco3HDxznYmcP7sX
Proposed solution (if any)
HOC usages should be gradually reduced as much as possible They cause 1+ component for each component that uses them
I've described how to change
withWindowDimensions
here: https://github.com/Expensify/App/issues/2326 (DimensionsContextProvider) This will leavewithWindowDimensions
usages throughout the app unchanged, but they will at least not be class based components and would not run class component lifecycleReportActionItem
should be updated not to be HOC based (if possible) as they are the most rendered component They can receive window related props from the parentrenderItem
as well as Onyx related propsList any benchmarks after implementing the changes to show impacts of the proposed solution (if any)
Note: These should be the same as the benchmarks collected before any changes. This is not at all the final result, but it does show some improvement after converting the
withWindowDimensions
wrappings not to be class basedPlatform:
Where is this issue occurring?
Version Number: 1.0.85-0 Logs: https://stackoverflow.com/c/expensify/questions/4856 Notes/Photos/Videos: Any additional supporting documentation Expensify/Expensify Issue URL:
View all open jobs on Upwork