[SignalR] Avoid initial memory allocation in ChannelBasedSemaphore
- Dominant language
- C#
- Stars
- 38.4k
- Forks
- 10.9k
- Avg merge
- 2d 6h
- Merged PRs (30d)
- 290
Description
## Summary
The initial memory allocation should be avoided in `ChannelBasedSemaphore`
## Motivation and goals
Some developers could just give `HubConnectionContextOptions.MaximumParallelInvocations` a large value (such as `int.MaxValue`) to ensure their single client can make as many parallel invocations as possible.
Unfortunately , `ChannelBasedSemaphore` will always [allocate](https://github.com/dotnet/aspnetcore/blob/dce793fda55ebc9b32eb69ff01023a618ed06942/src/SignalR/server/Core/src/Internal/ChannelBasedSemaphore.cs#L20) `'enough'` memory according to `HubConnectionContextOptions.MaximumParallelInvocations` on first invocation, even if there is only one invocation here, and the whole program may crash or have high cpu and memory usage without a friendly warning. This behavior increases the costs of diagnostics.
This is a sample message for an event about this error in `Event Viewer` in Win10
```
Faulting application name: SignalRTest.exe, version: 1.0.0.0, time stamp: 0x634eda42
Faulting module name: coreclr.dll, version: 7.0.22.51805, time stamp: 0x634ed04e
Exception code: 0xc0000005
Fault offset: 0x000000000013b93e
Faulting process id: 0x820c
Faulting application start time: 0x01d9682ee7ded2d7
Faulting application path: C:\Users\anoba\source\repos\SignalRTest\SignalRTest\bin\Debug\net7.0\SignalRTest.exe
Faulting module path: C:\Program Files\dotnet\shared\Microsoft.NETCore.App\7.0.0\coreclr.dll
Report Id: a686bc6b-6375-4553-b5b3-0b26dc5403dc
Faulting package full name:
Faulting package-relative application ID:
```
---
By the way, will [this](https://github.com/dotnet/aspnetcore/blob/dce793fda55ebc9b32eb69ff01023a618ed06942/src/SignalR/server/Core/src/HubConnectionHandler.cs#L204) cause an inconsistent result for available invocation quotas? I didn't see any `Release` corresponding the result of `TryAcquire`.
## In scope
This is my immature idea. Maybe we can use the `Interlocked` to implement `TryAcquire`, and use the combination of `Interlocked` and `Channel` for `WaitAsync` and `RunAsync` ?
Contributor guide
Assessment
This issue has not been assessed yet.