dotnet / dotnet/maui

Major Memory Leak on Maccatalyst in .NET 9 & 10 Compared to .NET8

Open
#34,249 7 comments 0 reactions 0 assignees View on GitHub
t/bug
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

Open the contributing 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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.