Potential Memory Leak when using Popup
See original GitHub issueIs there an existing issue for this?
- I have searched the existing issues
Current Behavior
When opening a popup from a page defined in the AppShell xaml, the popup is never eligible for garbage collection. In a scenario where a popup is used repeatedly, this will lead to memory being allocated that can never be reclaimed.
When opening a popup from a page that has been pushed onto the navigation stack, the popup does become eligible for garbage collection, although it appears to only do so after the page is dismissed. If this is truly the case, that would explain why popups presented by Shell-defined pages cannot be collected since the Shell-defined pages exist for the lifetime of the app.
This does not appear to be platform specific; I was able to recreate on iOS, Android, and Windows.
Expected Behavior
Once a popup is dismissed (and has gone out of scope), it should be eligible for garbage collection.
Steps To Reproduce
- Open and run solution in reproduction repo.
- Add a breakpoint to the finalizer in CustomPopup.xaml.cs.
- Click the “Create popup, but don’t open” button
- Click “Force Garbage Collection”
- Notice breakpoint hits
- Click the “Open popup using MainPage” button
- Dismiss the popup
- Click “Force Garbage Collection”
- Notice breakpoint does not hit.
- Click the “Open popup using New Page” button
- Dismiss the popup
- Return to Main page
- Click “Force Garbage Collection”
- Notice breakpoint hits
Link to public reproduction project repository
https://github.com/JustinC-IADS/PopupMemoryLeakRepo/tree/main/PopupMemoryLeak
Environment
- .NET MAUI CommunityToolkit: 1.3.0
- OS: Windows 11, iOS 16, Android (does not appear to be OS-releated)
- .NET MAUI: 6.0.400
Anything else?
No response
Issue Analytics
- State:
- Created a year ago
- Reactions:2
- Comments:7 (2 by maintainers)
Top GitHub Comments
@pictos is correct. On Windows, I’m using the built-in VS diagnostic tools.
This example is intentionally extreme (the popup is allocating a large chunk of memory) to illustrate the point. Regardless of how much memory pressure there is or how many times GC runs, it is never able to reclaim any of the allocated memory.
@pictos, I’ve update the reproduction repo to .net7 and the latest version of the toolkit just now.
Open the repo and search for “put breakpoint here”, you’ll find a console message inside of a custom popup finalizer.
Run the program on any target (if you select Windows, you can see the memory usage grow in the profiler)
There are 3 buttons that illustrate various scenarios (and a button to force GC).
The first button will create a popup, but not actually show it. This version allows the finalizer to run with no issue. Sometimes it is necessary to force GC to see it hit immediately, but the instance is obviously eligible for GC.
The second button creates a popup and uses the current page to display it. This is the most problematic scenario. After the popup has been displayed, I can find no way for it to ever be garbage collected.
The third button creates a popup and uses a new page to display it. From what I can tell, the popup will become eligible for GC after the new page is closed, but not before.
My working theory is that once a popup is shown, it does not become eligible for GC until the page that was used to show it is dismissed.
A couple of notes: