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

Fix retain cycles preventing objects from being deallocated after logging out #21047

Merged
merged 19 commits into from
Jul 14, 2023

Conversation

staskus
Copy link
Contributor

@staskus staskus commented Jul 10, 2023

Fixes #21010

Memory is not deallocated after logging out.

It is caused by 2 main issues:

  • WPTabBarController held strongly by singleton RootViewCoordinator after logging out (see more details)
  • Dashboard, Reader, Notification, and other initial view controllers and dependencies that have retain cycles preventing them from releasing (see more details)

Solution

To address issues in RootViewCoordinator I decided to limit the changes as much as possible to avoid cascading code changes throughout the codebase. For now, I decided to manually release a reference to RootViewPresenter (WPTabBarController) once logging out. See more info in commit message.

⚠️ Other issues not addressed by this PR

  • I noticed that the memory footprint remains high after logout, it may be more related to stores or services, I need to investigate more
  • There's a significant number of memory leaks in the app. This login -> logout case helps to quickly reproduce and confirm whether the issues with initial VCs are fixed but I think we'll need to create more tasks to go through all the main flows
  • There looks to be a memory leak with Login VCs as well, they are allocated and not deallocated when logging in and logging out as well Memory not deallocated after logging in #21075

To test:

Login & Logout (On both Jetpack and WordPress apps)

  1. Login
  2. Logout
    3 Check Memory Graph
  3. WPTabBarController and other non-login related view controllers should be deallocated

Regression: WordPress without static posters

  1. Open WordPress
  2. Enabled all the phases
  3. Relaunch application
  4. Confirm that no tabs are displayed and navigation in menu works

Regression: WordPress with static posters

  1. Open WordPress
  2. Enable static posters phase
  3. Relaunch application
  4. Confirm that tabs are displayed but Reader and Notifications tab is showing static poster

Regression: Dashboard Blaze card

  1. Open Jetpack
  2. Log into the .com site with a post
  3. Select "Promote your content with Blaze" card
  4. Confirm that navigation to Blaze controller is working

Regression: Dashboard Quick Actions

  1. Open Jetpack
  2. Log into the account
  3. Select "Stats, "Posts", "Pages", "Media" buttons
  4. Confirm that navigation works

Regression: Dashboard navigation

  1. Open Jetpack
  2. Confirm site picker, home, and menu navigation works

Regression: Reader navigation

  1. Open Jetpack
  2. Select Reader tab
  3. Confirm opening Post works
  4. Confirm opening Search works

Regression Notes

  1. Potential unintended areas of impact

Breaking the currently existing functionality, especially root navigation

  1. What I did to test those areas of impact (or what existing automated tests I relied on)
  • Unit test suite
  • UI test suite
  • Manual testing
  1. What automated tests I added (or what prevented me from doing so)

None for now but It may be worth considering about performance tests or tests confirming the deallocation of main VCs

PR submission checklist:

  • I have completed the Regression Notes.
  • I have considered adding unit tests for my changes.
  • I have considered adding accessibility improvements for my changes.
  • I have considered if this change warrants user-facing release notes and have added them to RELEASE-NOTES.txt if necessary.

@staskus
Copy link
Contributor Author

staskus commented Jul 10, 2023

@guarani Just informing you that it's still in progress, although most of the classes are finally released after the logout:

  • The work still requires thorough testing since it involves architectural changes at RootViewCoordinator
  • There's a significant number of memory leaks in the app. This login -> logout case helps to quickly reproduce and confirm whether the issues are fixed but I think we'll need to create more tasks to go through all the main flows
  • Even when dozens of VCs, Views, and related classes are deallocated after logout, the memory footprint in the app still didn't decrease. I haven't dug deep but it feels like some blog or site-related information is cached and kept in memory after logout. Our Stores and some services are either singletons or held by singletons which doesn't allow them to be released automatically after logout

@wpmobilebot
Copy link
Contributor

wpmobilebot commented Jul 10, 2023

WordPress Alpha📲 You can test the changes from this Pull Request in WordPress Alpha by scanning the QR code below to install the corresponding build.
App NameWordPress Alpha WordPress Alpha
ConfigurationRelease-Alpha
Build Numberpr21047-d1358ae
Version22.8
Bundle IDorg.wordpress.alpha
Commitd1358ae
App Center BuildWPiOS - One-Offs #6341
Automatticians: You can use our internal self-serve MC tool to give yourself access to App Center if needed.

@wpmobilebot
Copy link
Contributor

wpmobilebot commented Jul 10, 2023

Jetpack Alpha📲 You can test the changes from this Pull Request in Jetpack Alpha by scanning the QR code below to install the corresponding build.
App NameJetpack Alpha Jetpack Alpha
ConfigurationRelease-Alpha
Build Numberpr21047-d1358ae
Version22.8
Bundle IDcom.jetpack.alpha
Commitd1358ae
App Center Buildjetpack-installable-builds #5367
Automatticians: You can use our internal self-serve MC tool to give yourself access to App Center if needed.

Problem:
- RootViewCoordinator is a singleton
- RootViewCoordinator holds a strong reference to RootViewPresenter
- WPTabBarController implements RootViewPresenter and is presenter as rootViewController
- When WPTabBarController is dismissed, RootViewCoordinator continues to hold a strong reference to a WPTabBarController creating a memory leak

Solution:
- Move presentation logic from WindowsManager to RootViewCoordinator
- Only initialize RootViewPresenter when needed
- Release RootViewPresenter after logging out. Not making RootViewPresenter weak or unowned to avoid further cascading changes through the codebase to handle RootViewPresenter being optional
- RootViewPresenter should not be accessed before the root view is presented. If it happens - print a warning. All the issues should be addressed with further improvements.
@staskus staskus force-pushed the fix/21010-memory-not-deallocated-after-logging-out branch from 880e34c to daf8e08 Compare July 11, 2023 10:28
@staskus staskus added this to the 22.9 milestone Jul 11, 2023
@staskus staskus requested a review from guarani July 11, 2023 11:24
@staskus staskus marked this pull request as ready for review July 11, 2023 11:26
Copy link
Contributor

@guarani guarani left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I only did a partial review since you mention this isn't ready yet. I just went through the code changes but didn't test it. Once it's ready I can dive deeper and actually test the changes, let me know if this works for you.

I left some comments with first impressions, but they're things I might be able to answer myself after spending more time review and testing.

@staskus staskus requested a review from guarani July 12, 2023 12:51
Copy link
Contributor

@guarani guarani left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Login & Logout (On both Jetpack and WordPress apps)

  1. Login
  2. Logout
    3 Check Memory Graph
  3. WPTabBarController and other non-login related view controllers should be deallocated

Here the app's starting memory was 155 MB, went to 313 MB after logging in, and stayed high (323 MB) after logging out (the increase is explained by navigating to the log out screen). I saw you mention how there's many other retain cycles that are out of scope of this PR and that could explain this. I checked the Memory Graph and indeed WPTabBarController is no longer there (this was while testing the Jetpack app), which is a good sign.

This PR does appear to fix a retain cycle, but it might not be reducing the app's memory consumption overall. If so, putting this in the release notes as I suggested earlier might more sense once we've addressed some of the other retain cycles. What do you think?


It's not easy to grok how the window management works (especially across the two apps + the migration flow). However, I think the approach is promising. I'm happy to approve this once I can spend more time on the regression testing tomorrow and can get a bit more confidence in the fix. On a side note, splitting this into multiple PRs could be an option so that if for example a change needs to be reverted, we won't need to revert all these separate fixes.

RELEASE-NOTES.txt Show resolved Hide resolved
@staskus
Copy link
Contributor Author

staskus commented Jul 13, 2023

Thanks for the review, @guarani !

This PR does appear to fix a retain cycle, but it might not be reducing the app's memory consumption overall. If so, putting this in the release notes as I suggested earlier might more sense once we've addressed some of the other retain cycles. What do you think?

Yes, you're right. I had the expectation of fixing these retain cycles to clean the memory but there're more issues that I will address with future PRs. I didn't want to make this one too big. I will update the release notes.

On a side note, splitting this into multiple PRs could be an option so that if for example a change needs to be reverted, we won't need to revert all these separate fixes.

A lot of the small retain cycle improvements include retain cycles with BlogDashboardViewController, so only fixing all of them change anything fundamentally. However, we could split RootViewCoordinator fixes and all the retain cycle fixes in 2 PRs if needed.

@staskus staskus changed the title Fix memory not deallocated after logging out Fix retain cycles preventing classes from being deallocated after logging out Jul 13, 2023
@staskus staskus changed the title Fix retain cycles preventing classes from being deallocated after logging out Fix retain cycles preventing objects from being deallocated after logging out Jul 13, 2023
@staskus staskus requested a review from guarani July 13, 2023 07:33
Copy link
Contributor

@guarani guarani left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Finished manual testing and everything is working as before.

Tested on iPhone:

  • Login & Logout (On both Jetpack and WordPress apps). Tested:
    • Tested WP app
    • Tested WP to JP app migration
    • Tested JP app
  • Regression test: WordPress without static posters
  • Regression test: WordPress with static posters
  • Regression test: Dashboard Blaze card

Tested on iPad:

  • Regression test: Dashboard Quick Actions
  • Regression test: Dashboard navigation
  • Regression test: Reader navigation

The code changes look good and I think this is ready to merge 👍

@staskus staskus merged commit cb5ccda into trunk Jul 14, 2023
@staskus staskus deleted the fix/21010-memory-not-deallocated-after-logging-out branch July 14, 2023 08:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Memory not deallocated after logging out
4 participants