-
Notifications
You must be signed in to change notification settings - Fork 1.9k
Description
Description
Memory leaks in MAUI are exacerbated by orders of magnitude due to their propagation through the visual tree via held references (e.g. Parent, Content, ItemsSource, Children). This leads to entire pages and binding contexts being held in memory indefinitely (sometimes even entire apps), resulting in severe performance degradation, UI choppiness, and eventual forced application shutdowns by the operating system.
I believe this is the most critically severe performance-related issue in MAUI apps today. The behavior is the same across platforms. Lots of effort has been going into fixing individual leaks, but the ROI on these efforts is muted by the all-or-nothing nature of this problem.
Steps to Reproduce
No response
Link to public reproduction project repository
https://github.com/AdamEssenmacher/MemoryToolkit.Maui/tree/main/samples
Version with bug
8.0.7 SR2
Is this a regression from previous behavior?
Yes, this used to work in Xamarin.Forms
Last version that worked well
Unknown/Other
Affected platforms
iOS, Android, Windows, macOS, I was not able test on other platforms
Affected platform versions
No response
Did you find any workaround?
There are three distinct actions that, when applied systemically through the visual tree bottom-up (from leaf to root), can whack leaky views into non-leaking states and compartmentalize small leaks so that they remain isolated to their offending views:
1) Clear the binding context: This contributes to compartmentalization by removing the reference. It also gives the view a chance to reset itself to a near-default state where leaks are least likely to happen (some views only leak in certain states).
2) Clear references to other views: By clearing properties like Content and ItemsSource and calling ClearLogicalChildren(), we can achieve compartmentalization by breaking the visual tree apart.
3) Disconnect (and, if applicable, dispose) the handler: Many handlers are written in such a way that problematic event handlers are only cleaned up when explicitly disconnected.
View Lifecycle Challenges
The workaround I've offered above might not be an ideal or permanent solution. Executing these cleanup measures requires that we have knowledge of when an app is "done with" a given view or page. MAUI currently does not really have a standardized component lifecycle, so there isn't really a central event or hook we can rely on. I have developed an approach that attempts to address this by making an educated guess about when an app is probably "done with" a given Element by checking for these conditions:
- The
Element'sPage(or itself, if theElementis aPage) was just popped off the navigation stack. - The
Elementhas been unloaded and is not (or no longer) hosted within aPage(e.g. aControlTemplatethat was just swapped out). - The
Elementis hosted within aNavigationPagethat has been unloaded
Stopgap Solution
I have developed a behavior that detects leaky views during development using this definition of "done with", and another behavior that automatically applies the cleanup measures described earlier. I offer them as stop-gap measures pending a more robust solution.
Request for Assistance
I encourage the community to provide feedback on these behaviors, and to contribute ideas for how MAUI might incorporate improved lifecycle management to prevent and contain memory leaks.
Relevant log output
No response
Metadata
Metadata
Assignees
Labels
Type
Projects
Status