Major Memory Leak on Maccatalyst in .NET 9 & 10 Compared to .NET8
- Dominant language
- C#
- Stars
- 23.3k
- Forks
- 2k
- Avg merge
- 1d 15h
- Merged PRs (30d)
- 290
Description
### Description
Hello,
I have a Maui-Blazor Hybrid application that I recently updated from .NET8 to .NET10. My app is a device dashboard that is constantly updating and displays images, plots (using Plotly.Blazor) and data in real time. When I did this update, I noticed the .net10.0-maccatalyst deployment of my app was suddenly leaking memory at a much faster rate than when it was built for .net8.0-maccatalyst. In order to try and narrow down where the leak was coming from, I checked:
- When I deployed the exact same code as a pure Blazor Server application, without the Maui wrapper, I do not see the same memory leak on MacOS or Windows.
- When I deploy the exact same code as a Maui Windows application, I do not see the same memory leak.
I also ran a test where I took the exact same application code and built the Maui-Maccatalyst app for 3 different target frameworks: .net8-maccatalyst, .net9-maccatalyst and .net10-maccatalyst. I then ran the 3 apps simultaneously for 5 hours. At the end of the 5 hours, the memory usage for each version was:
.NET8 --> 445 MB
.NET9 --> 18.34 GB (!)
.NET10 --> 17.88 GB (!)
The only delta between these 3 deployments was the target framework, and the versions of the below workloads & packages:
Workload / Package Name | .NET8 Deployment Version | .NET9 Deployment Version | .NET10 Deployment Version
-- | -- | -- | --
.NET SDK | 8.0.416 | 9.0.300 | 10.0.103
Maui SDK | 8.0.100 | 9.0.120 | 10.0.20
maccatalyst | 8.0.400 | 26.0.9785/9.0.100 | 26.2.10197/10.0.100
Microsoft.Maui.Controls | 8.0.100 | 9.0.120 | 10.0.30
Microsoft.AspNetCore.Components.WebView.Maui | 8.0.100 | 9.0.120 | 10.0.30
Microsoft.Extensions.Configuration.Abstractions | 8.0.0 | 9.0.9 | 10.0.2
Microsoft.AspNetCore.Components.Web | 8.0.14 | 9.0.9 | 10.0.2
Microsoft.JSInterop | 8.0.14 | 9.0.9 | 10.0.2
CommunityToolkit.Maui | 8.0.1 | 12.3.0 | 14.0.0
CommunityToolkit.Maui.Core | 8.0.1 | 12.3.0 | 14.0.0
I have attempted a number of strategies to try and profile my app's memory when running via maccatalyst, to see what structures are dominating the leak, but to no real avail so far. I can't get `dotnet-trace` or `dotnet-gcdump` to attach to the app when running in maccatalyst, even with setting `DOTNET_DiagnosticPorts`. The JetBrains dotTrace tool will not attach to it either. The Xcode "Leaks" instrument will attach and collect memory data, but its extremely low-level and opaque -- pretty much all I can see there are a bunch of leaked `Malloc` mostly from `do_icall` and I can't figure out what .NET objects they represent.
I know this is not much specific to go on -- I'll continue to try and narrow down this issue, but please let me know if you have any suggestions of what I can try or what information I can provide.
### Steps to Reproduce
I don't have a great way to reproduce all the leakage that is happening with my application, but the behavior is observable on a smaller level by doing this:
On MacOS
1. Create a new Maui Blazor Hybrid app using the template from .NET8 SDK
2. Create a new Maui Blazor Hybrid app using the template from .NET10 SDK
3. Modify the `Counter.razor` in each app such that when the button is clicked, it will start a continuous task in which the counter is incremented and `InvokeAsync(StateHasChanged)` is called in a loop until cancelled.
4. Run the MacOS configuration of both apps, and record the initial memory usage from Activity Monitor.
5. Click the button to start incrementing counter in both apps at close to the same time.
6. Let the apps run for a few hours. Observe that the rate of memory increase on the .NET10 app is greater than the rate of increase for the .NET8 app. For me, after a little over an hour, the .NET10 app had grown by 7.7MB and the .NET8 app by only 5.3MB
### Link to public reproduction project repository
_No response_
### Version with bug
10.0.30
### Is this a regression from previous behavior?
Yes, this used to work in .NET MAUI
### Last version that worked well
.NET 8 (Please specify exact version)
### Affected platforms
macOS
### Affected platform versions
net9.0-maccatalyst, net10.0-maccatalyst
### Did you find any workaround?
_No response_
### Relevant log output
```shell
```
Contributor guide
Research direction
Start with the .NET 8 and .NET 10 MAUI Blazor Hybrid templates and modify Counter.razor to run the continuous StateHasChanged loop described in the report. Compare memory growth in the macOS configurations using Activity Monitor, then narrow the regression to the MAUI, Blazor WebView, or Mac Catalyst layer with a reproducible case. Done means the regression is isolated and its memory growth is corrected or documented with supporting evidence.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- csharp
- Domain
- mobile-dev
- Issue type
- Bug
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Active
- Clarity
- Needs clarification
- Newbie friendliness
- 35/100