-
Notifications
You must be signed in to change notification settings - Fork 1.8k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[controls] fix memory leak in Style and AttachedCollection (#13260)
Context: https://github.com/Vroomer/MAUI-master-detail-memory-leak Context: https://github.com/symbiogenesis/Maui.DataGrid/tree/memory-leak Context: #12039 Using the Visual Studio's `.NET Object Allocation Tracking` profiler on the sample above I noticed after using the app and taking snapshots: Snapshot 2: WeakReference<Microsoft.Maui.Controls.BindableObject> Count: 1,545 Bytes: 37,080 Snapshot 10: WeakReference<Microsoft.Maui.Controls.BindableObject> Count: 1,657 Bytes: 39,768 It appears memory usage is slowly growing by about ~2.45KB each time I navigate forward a page then return. f8171b4 introduced a `CleanupTrigger`, but the code has a slight issue: void CleanUpWeakReferences() { if (_targets.Count < _cleanupThreshold) { return; } _targets.RemoveAll(t => !t.TryGetTarget(out _)); _cleanupThreshold = _targets.Count + CleanupTrigger; } Because `_cleanupThreshold` is modified at the bottom of this method, the `_targets` collection increases by 128 in size over time. The result being lots of tiny `WeakReference<T>` objects in memory, but not the actual underlying `T` target. I did a little research to try to find a better collection than `List<WeakReference<T>>`: * https://learn.microsoft.com/dotnet/api/system.runtime.compilerservices.conditionalweaktable-2 * https://source.dot.net/#Microsoft.Extensions.Caching.Memory/MemoryCache.cs * https://source.dot.net/#PresentationFramework/System/Windows/Input/KeyboardNavigation.cs,08271c29723aa10a I did not find one that exactly met our needs, so I wrote a very simple `WeakList<T>`. It cleans up `WeakReference<T>` that are no longer alive after N operations. I set this threshold to 32 to start, we can modify this later if needed. This makes the above samples call it a couple times for large `CollectionView`'s, which seems reasonable. After these changes, I'm able to navigate in the app over and over with stable memory usage: | ID | Objects | Heap Size | | -- | --: | --: | | 1 | 107,885 | 407,645.87 KB | | 2 | 2,267 | 401,126.22 KB | This was after navigating through the app *many* times, and it actually went *down*. Then I found `Microsoft.Maui.Internals.WeakList<T>`, which I did not like quite as much as my implementation. I deleted/replaced its usage adding new unit tests for `WeakList<T>`. Note that I believe I found one other leak, so this doesn't fully solve #12039 yet.
- Loading branch information
1 parent
918d1ce
commit 23b9ae2
Showing
7 changed files
with
153 additions
and
183 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,5 @@ | ||
using System; | ||
using Microsoft.Maui.Devices; | ||
using Microsoft.Maui.Internal; | ||
|
||
namespace Microsoft.Maui.Platform | ||
{ | ||
|
Oops, something went wrong.