|
// See https://aka.ms/new-console-template for more information |
|
using System.Threading.RateLimiting; |
|
using System.Diagnostics; |
|
|
|
await Concurrency(); |
|
// await TokenBucket(); |
|
|
|
async Task Concurrency() |
|
{ |
|
await using var limiter = new ConcurrencyLimiter(new ConcurrencyLimiterOptions( |
|
100, QueueProcessingOrder.OldestFirst, 100 |
|
)); |
|
var totalsw = new Stopwatch(); |
|
totalsw.Start(); |
|
await Task.WhenAll( |
|
Enumerable.Range(0, 10).Select(async idx => |
|
{ |
|
await Task.Yield(); |
|
for (int i = 0; i < 100; i++) |
|
{ |
|
var sw = new Stopwatch(); |
|
sw.Start(); |
|
while (true) |
|
{ |
|
using (var lease = await limiter.WaitAsync(50)) |
|
{ |
|
// Console.WriteLine($"{idx}, {i}, {lease.IsAcquired}"); |
|
if (lease.IsAcquired) |
|
{ |
|
await Task.Delay(100).ConfigureAwait(false); |
|
break; |
|
} |
|
if (lease.TryGetMetadata<TimeSpan>(MetadataName.RetryAfter, out var interval)) |
|
{ |
|
Console.WriteLine($"do delay: {interval}"); |
|
await Task.Delay(interval); |
|
} |
|
else |
|
{ |
|
await Task.Delay(100).ConfigureAwait(false); |
|
} |
|
} |
|
} |
|
sw.Stop(); |
|
Console.WriteLine($"{idx}, {i}, {sw.Elapsed}"); |
|
} |
|
|
|
}) |
|
); |
|
totalsw.Stop(); |
|
Console.WriteLine($"total {totalsw.Elapsed}"); |
|
} |
|
async Task TokenBucket() |
|
{ |
|
await using var limiter = new TokenBucketRateLimiter(new TokenBucketRateLimiterOptions( |
|
200, QueueProcessingOrder.OldestFirst, 100, TimeSpan.FromMilliseconds(1000), 100) |
|
); |
|
var totalsw = new Stopwatch(); |
|
totalsw.Start(); |
|
await Task.WhenAll( |
|
Enumerable.Range(0, 1).Select(async idx => |
|
{ |
|
await Task.Yield(); |
|
for (int i = 0; i < 100; i++) |
|
{ |
|
var sw = new Stopwatch(); |
|
sw.Start(); |
|
while (true) |
|
{ |
|
using (var lease = await limiter.WaitAsync(40)) |
|
{ |
|
// Console.WriteLine($"{idx}, {i}, {lease.IsAcquired}"); |
|
if (lease.IsAcquired) |
|
{ |
|
break; |
|
} |
|
lease.TryGetMetadata<TimeSpan>(MetadataName.RetryAfter, out var interval); |
|
Console.WriteLine($"do delay: {interval}"); |
|
await Task.Delay(interval); |
|
} |
|
} |
|
sw.Stop(); |
|
Console.WriteLine($"{idx}, {i}, {sw.Elapsed}"); |
|
} |
|
|
|
}) |
|
); |
|
totalsw.Stop(); |
|
Console.WriteLine($"total {totalsw.Elapsed}"); |
|
} |