Skip to content

Commit 61179f3

Browse files
Kahbazihalter73
authored andcommitted
Improve performance for QueuePolicy in ConcurrencyLimiter (#13947)
1 parent ab5b5a4 commit 61179f3

File tree

2 files changed

+30
-17
lines changed

2 files changed

+30
-17
lines changed

src/Middleware/ConcurrencyLimiter/src/QueuePolicies/QueuePolicy.cs

Lines changed: 29 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -10,49 +10,57 @@ namespace Microsoft.AspNetCore.ConcurrencyLimiter
1010
{
1111
internal class QueuePolicy : IQueuePolicy, IDisposable
1212
{
13-
private readonly int _maxConcurrentRequests;
14-
private readonly int _requestQueueLimit;
13+
private readonly int _maxTotalRequest;
1514
private readonly SemaphoreSlim _serverSemaphore;
1615

1716
private object _totalRequestsLock = new object();
17+
1818
public int TotalRequests { get; private set; }
1919

2020
public QueuePolicy(IOptions<QueuePolicyOptions> options)
2121
{
22-
_maxConcurrentRequests = options.Value.MaxConcurrentRequests;
23-
if (_maxConcurrentRequests <= 0)
22+
var queuePolicyOptions = options.Value;
23+
24+
var maxConcurrentRequests = queuePolicyOptions.MaxConcurrentRequests;
25+
if (maxConcurrentRequests <= 0)
2426
{
25-
throw new ArgumentException(nameof(_maxConcurrentRequests), "MaxConcurrentRequests must be a positive integer.");
27+
throw new ArgumentException(nameof(maxConcurrentRequests), "MaxConcurrentRequests must be a positive integer.");
2628
}
2729

28-
_requestQueueLimit = options.Value.RequestQueueLimit;
29-
if (_requestQueueLimit < 0)
30+
var requestQueueLimit = queuePolicyOptions.RequestQueueLimit;
31+
if (requestQueueLimit < 0)
3032
{
31-
throw new ArgumentException(nameof(_requestQueueLimit), "The RequestQueueLimit cannot be a negative number.");
33+
throw new ArgumentException(nameof(requestQueueLimit), "The RequestQueueLimit cannot be a negative number.");
3234
}
3335

34-
_serverSemaphore = new SemaphoreSlim(_maxConcurrentRequests);
36+
_serverSemaphore = new SemaphoreSlim(maxConcurrentRequests);
37+
38+
_maxTotalRequest = maxConcurrentRequests + requestQueueLimit;
3539
}
3640

37-
public async ValueTask<bool> TryEnterAsync()
41+
public ValueTask<bool> TryEnterAsync()
3842
{
3943
// a return value of 'false' indicates that the request is rejected
4044
// a return value of 'true' indicates that the request may proceed
4145
// _serverSemaphore.Release is *not* called in this method, it is called externally when requests leave the server
4246

4347
lock (_totalRequestsLock)
4448
{
45-
if (TotalRequests >= _requestQueueLimit + _maxConcurrentRequests)
49+
if (TotalRequests >= _maxTotalRequest)
4650
{
47-
return false;
51+
return new ValueTask<bool>(false);
4852
}
4953

5054
TotalRequests++;
5155
}
5256

53-
await _serverSemaphore.WaitAsync();
57+
Task task = _serverSemaphore.WaitAsync();
58+
if (task.IsCompletedSuccessfully)
59+
{
60+
return new ValueTask<bool>(true);
61+
}
5462

55-
return true;
63+
return SemaphoreAwaited(task);
5664
}
5765

5866
public void OnExit()
@@ -69,5 +77,12 @@ public void Dispose()
6977
{
7078
_serverSemaphore.Dispose();
7179
}
80+
81+
private async ValueTask<bool> SemaphoreAwaited(Task task)
82+
{
83+
await task;
84+
85+
return true;
86+
}
7287
}
7388
}

src/Middleware/ConcurrencyLimiter/src/QueuePolicies/StackPolicy.cs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,6 @@ internal class StackPolicy : IQueuePolicy
2121

2222
private readonly object _bufferLock = new Object();
2323

24-
private readonly static ValueTask<bool> _trueTask = new ValueTask<bool>(true);
25-
2624
private int _freeServerSpots;
2725

2826
public StackPolicy(IOptions<QueuePolicyOptions> options)
@@ -40,7 +38,7 @@ public ValueTask<bool> TryEnterAsync()
4038
if (_freeServerSpots > 0)
4139
{
4240
_freeServerSpots--;
43-
return _trueTask;
41+
return new ValueTask<bool>(true);
4442
}
4543

4644
// if queue is full, cancel oldest request

0 commit comments

Comments
 (0)