-
Notifications
You must be signed in to change notification settings - Fork 5.2k
Description
Describe the bug
We had to abort our upgrade to NET6.0 due to performance concerns. The upgraded apps were using significantly higher CPU. I've finally gotten around to identifying the cause and replicating it in a sample project.
The symptom is increasing CPU utilisation throughout the day. We have multiple blazor apps which are run all day, so this is a noticable issue to us.
This appears to be caused by asyncronous code (e.g. System.Threading.Timer, async / await) being used whilst an active ClientWebSocket connection is open. When these two elements are in play a large number of calls are made to "Install Timer" in the browser, and this number increases logarithmically throughout the day. Note: I'm using the Chrome Performance tab to verify this; profiling for a short period of time and then searching for the number of calls to "Install Timer".
Say you had a component set up a timer to do something every 500ms:
public partial class Index
{
private Timer _timer;
public Index()
{
_timer = new System.Threading.Timer(_ =>
{
Console.WriteLine("In timer, doing stuff.");
}, null, 0, 500);
}
}
Ignoring the fact that the timer is never diposed, the above code causes no issues. You can head into the Chrome Performance profiler (or whatever browser you prefer), and notice that there are a reasonable number of calls to "Install Timer". There's more than expected in my example beacuse I tried to turn off BrowserLink and failed, but I digress. 55 is a reasonable number.
Now add on a ClientWebSocket Connection wrapped in a service:
public class ApiService
{
public ApiService()
{
var websocket = new ClientWebSocket();
Task.Run(async () =>
{
await websocket.ConnectAsync(
new Uri("wss://websocket-echo.glitch.me"),
CancellationToken.None);
Console.WriteLine("Connected.");
});
}
}
Again - ordinarily this code would be fine (and without the Timer in our component, it is fine). Unfortunately when both of the above snippets are used our System.Threading.Timer is now exhibiting serious performance issues.
Profiling the app for 10 seconds every minute results in the below number of calls to "Install Timer".
00:30:00->00:40:00: 422 calls.
01:30:00->01:40:00: 1548 calls.
02:30:00->02:40:00: 2823 calls.
03:30:00->03:40:00: 4023 calls.
4023 "Install Timer" calls over 10 seconds, for a Timer that does something every 500ms?
You can start to visually see the performance issue develop when comparing the below pic, execution times are quite a bit thicker than the previous example.
To Reproduce
https://github.com/m-chandler/blazor-timers-net6.0
Exceptions (if any)
N/A
Further technical details
- ASP.NET Core version: NET 6.0
- The IDE (VS / VS Code/ VS4Mac) you're running on, and its version: VS 2022 Pro
- Include the output of
dotnet --info:
dotnet --info Output
.NET SDK (reflecting any global.json):
Version: 6.0.100
Commit: 9e8b04bbff
Runtime Environment:
OS Name: Windows
OS Version: 10.0.19043
OS Platform: Windows
RID: win10-x64
Base Path: C:\Program Files\dotnet\sdk\6.0.100\
Host (useful for support):
Version: 6.0.0
Commit: 4822e3c3aa
.NET SDKs installed:
5.0.302 [C:\Program Files\dotnet\sdk]
5.0.403 [C:\Program Files\dotnet\sdk]
6.0.100-rc.1.21463.6 [C:\Program Files\dotnet\sdk]
6.0.100 [C:\Program Files\dotnet\sdk]
.NET runtimes installed:
Microsoft.AspNetCore.App 5.0.12 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.AspNetCore.App 6.0.0-rc.1.21452.15 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.AspNetCore.App 6.0.0 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.NETCore.App 5.0.12 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.NETCore.App 6.0.0-rc.1.21451.13 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.NETCore.App 6.0.0 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.WindowsDesktop.App 5.0.12 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
Microsoft.WindowsDesktop.App 6.0.0-rc.1.21451.3 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
Microsoft.WindowsDesktop.App 6.0.0 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
To install additional .NET runtimes or SDKs:
https://aka.ms/dotnet-download

