Skip to content
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

[Performance] [Audit] ReportActionContextMenu slows down cell rendering time significantly #4106

Closed
jsamr opened this issue Jul 16, 2021 · 30 comments · Fixed by #4194
Closed
Assignees
Labels
Daily KSv2 Engineering External Added to denote the issue can be worked on by a contributor

Comments

@jsamr
Copy link
Collaborator

jsamr commented Jul 16, 2021

If you haven’t already, check out our contributing guidelines for onboarding and email contributors@expensify.com to request to join our Slack channel!


This report is part of #3957, scenario "Rendering Individual chat messages".

Pattern

The full commit log can be inspected with Flipper or React Devtools, see #3957 (comment) for instructions.

image

This commit chart spans over 1.4s (c77 to c144). Each spike in the chart is a ReportActionContextMenu rendered for one cell.

Flamegraph

This is an excerpt of the 100th commit (c100):

image

Also note that those spikes could be caused by the heavy usage of react-native-svg, which can impede performance. Quoting William Candillon

Using SVG heavily in an app can degrade its performance, therefore use it with parsimony."

Proposal: render only one context menu, change dynamically its content on press

Instead of rendering ReportActionContextMenu for every cell, render only one menu at the root of the screen. When a report action is pressed, pass the parameters required to update the view to a callback and render the content accordingly. The callback can be shared via a React context.

@jsamr jsamr added the AutoAssignerTriage Auto assign issues for triage to an available triage team member label Jul 16, 2021
@MelvinBot
Copy link

Triggered auto assignment to @stephanieelliott (AutoAssignerTriage), see https://stackoverflow.com/c/expensify/questions/4749 for more details.

@MelvinBot MelvinBot removed the AutoAssignerTriage Auto assign issues for triage to an available triage team member label Jul 16, 2021
@parasharrajat

This comment has been minimized.

@jsamr
Copy link
Collaborator Author

jsamr commented Jul 16, 2021

@parasharrajat I agree with you; too much DOM event subscribers is a bad pattern and most certainly impedes performance. Much better to have one subscriber with a state shared in a top-level React context!

@jsamr
Copy link
Collaborator Author

jsamr commented Jul 16, 2021

@parasharrajat The great advantage of one context to share a state is that it guarantees React fiber will batch every update related to a dimension event in the same commit. Whereas when updating each component because of a DOM event, updates might happen in short bursts of commits which is most likely slower.

@parasharrajat

This comment has been minimized.

@marcaaron
Copy link
Contributor

This one makes perfect sense to me, but unsure how to prioritize.

I think @roryabraham might have the most context on this feature. Any thoughts on how difficult this would be to unwind? I think this could end up being a pretty significant refactor, but since we now understand the importance of keeping virtualized list items simple it feels like it needs to be done.

Ideas for benchmarking this one:

Disable the context menu code and just render a chat without the extra bells and whistles we added. What kinds of performance improvements do we see?

@kidroca

This comment has been minimized.

@marcaaron
Copy link
Contributor

@parasharrajat @kidroca Thanks for the extra context. Just a heads up I'm gonna clean these comments up a bit since I think this issue is broader than the withWindowDimensions HOC. If we think the issue over there is worth reopening we can continue conversation here. 🙇

@roryabraham
Copy link
Contributor

roryabraham commented Jul 16, 2021

Actually, I did sort of try this once before, albeit for a different reason. My implementation caused an undesirable wiggling effect with the mini ReportActionContextMenu that appears on hover as its position is dynamically calculated.

So my thoughts on this is that if we move forward with this, we should:

  1. Break apart the ReportActionContextMenu into two separate components – a very lean simple one called MiniReportActionContextMenu that is basically the existing ReportActionContextMenu with the isMini prop, and another one that displays a modal popover.
    • MiniReportActionContextMenu could probably strip out a fair amount of the expensive layout measuring code.
    • For now, the MiniReportActionContextMenu could probably be a noop on native platforms, because it only ever appears on hover anyways. That way I think RN might be smart enough to optimize it out of the render tree entirely.
  2. Keep MiniReportActionContextMenu as a child of the ReportActionItem (avoid the wiggle effect).
  3. Make a single PopoverReportActionContextMenu a sibling of this InvertedFlatList, as this issue suggests, and calculate its position when the modal is meant to open.

@marcaaron
Copy link
Contributor

Did some A/B testing with context menu logic removed and it looks like we could maybe shave off about ~500ms from every chat switch by refactoring this. Here are some rough numbers (also keep in mind this was in iOS simulator + using the production API)...

Avg. Chat Switch Time w/ Context Menu Avg. Chat Switch Time w/ Context Menu removed Difference
1332.25 ms 901.75 ms 430.5 ms

That seems pretty signifcant since anything over 1 second is going to feel very slow.

@MelvinBot MelvinBot added the Monthly KSv2 label Jul 20, 2021
@parasharrajat
Copy link
Member

parasharrajat commented Jul 21, 2021

Is Anyone working on this? If not, I am up for the task. @roryabraham has laid a good foundation of what needs to be done here #4106 (comment)

@marcaaron
Copy link
Contributor

No and @roryabraham plan sounds good to me.

@MelvinBot
Copy link

Triggered auto assignment to @bondydaa (Engineering), see https://stackoverflow.com/c/expensify/questions/4319 for more details.

@stephanieelliott
Copy link
Contributor

Moving this along, @bondydaa sounds like the proposed solution is here: #4106 (comment)

@kidroca
Copy link
Contributor

kidroca commented Jul 21, 2021

IMO it's possible to extract this entirely from the action item, and instead of having a menu item/s per each action item have the context menu at the root level. You can use an event associated with the action item in question e.g. on long press - position and provide context to the popup menu

@parasharrajat
Copy link
Member

That is a plan all along.

@quinthar
Copy link
Contributor

quinthar commented Jul 21, 2021 via email

@parasharrajat
Copy link
Member

parasharrajat commented Jul 21, 2021

@quinthar I have not started yet. Need a 🟢 signal. But I expect it achieve in 3-4 days from the start date.

@quinthar
Copy link
Contributor

quinthar commented Jul 21, 2021 via email

@marcaaron marcaaron assigned parasharrajat and unassigned bondydaa Jul 21, 2021
@marcaaron marcaaron added Daily KSv2 and removed Weekly KSv2 labels Jul 21, 2021
@marcaaron
Copy link
Contributor

@quinthar I will expedite this.

@marcaaron marcaaron self-assigned this Jul 21, 2021
@parasharrajat
Copy link
Member

Hi @marcaaron. PR is ready for review. Thank you.

@MelvinBot MelvinBot added Overdue and removed Overdue labels Jul 26, 2021
@marcaaron
Copy link
Contributor

Quick update here. We are seeing great progress with the PR opened by Rajat. It should be on staging soon!

Especially on Android where the chats are opening 0.7 seconds faster 🤯

Separately, I think I will look into further improving the metrics for chat switch time so we can track it in Firebase alongside the other critical metrics that have been recently set up.

Big success ! Great job everyone 🙇

@MelvinBot MelvinBot removed the Overdue label Jul 29, 2021
@quinthar
Copy link
Contributor

quinthar commented Jul 29, 2021 via email

@MelvinBot
Copy link

@parasharrajat, @marcaaron Eep! 4 days overdue now. Issues have feelings too...

@parasharrajat
Copy link
Member

PR is merged and we are waiting for the regression period to be over before closing it.

@MelvinBot MelvinBot removed the Overdue label Aug 3, 2021
@parasharrajat
Copy link
Member

@Expensify/contributor-management any update on this task?

@roryabraham roryabraham added the External Added to denote the issue can be worked on by a contributor label Aug 9, 2021
@MelvinBot
Copy link

Triggered auto assignment to @Christinadobrzyn (External), see https://stackoverflow.com/c/expensify/questions/8582 for more details.

@MelvinBot MelvinBot removed the Overdue label Aug 9, 2021
@roryabraham
Copy link
Contributor

@Christinadobrzyn Seems like maybe we didn't follow the normal process here. If I'm not mistaken, @parasharrajat submitted a PR for this issue without first getting hired on Upwork. So we should create the Upwork job and make sure @parasharrajat is paid for his work.

@parasharrajat
Copy link
Member

Sorry for the miscommunication here but there is an active job that needs to be paid out. https://www.upwork.com/jobs/ReportActionContextMenu-slows-down-cell-rendering-time-significantly_%7E01fc756cf8f4b57ccb

@marcaaron
Copy link
Contributor

I gotchu @parasharrajat

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Daily KSv2 Engineering External Added to denote the issue can be worked on by a contributor
Projects
None yet
Development

Successfully merging a pull request may close this issue.

10 participants