Skip to content

DefaultPartitionedRateLimiter never disposes NoopLimiter #124557

@kamilzzz

Description

@kamilzzz

Description

DefaultPartitionedRateLimiter never disposes NoopLimiter leading to memory leak and increased CPU usage as it performs its internal work on list of all limiters every 100ms.

There is logic inside Hearbeat() to dispose limiters after some idle period but condition is never true for NoopLimiter.

https://github.com/dotnet/dotnet/blob/f99a0e8bfcabcbb01abc1a9347a933ddc58a3a36/src/runtime/src/libraries/System.Threading.RateLimiting/src/System/Threading/RateLimiting/DefaultPartitionedRateLimiter.cs#L228

Reproduction Steps

Run this application with debugger in Visual Studio:

using System.Threading.RateLimiting;

PartitionedRateLimiter<string> limiter = PartitionedRateLimiter.Create<string, string>(x =>
{
    return RateLimitPartition.GetNoLimiter(x);
});

while (true)
{
    Console.WriteLine("Press any key to generate limiters...");
    Console.ReadLine();

    foreach (var item in Enumerable.Range(0, 100_000))
    {
        _ = await limiter.AcquireAsync(Guid.NewGuid().ToString());
    }
}

Take memory snapshots and observe limiters are created but never disposed.

Expected behavior

NoopLimiter to be disposed.

Actual behavior

NoopLimiter never disposed.

Regression?

No response

Known Workarounds

No response

Configuration

No response

Other information

No response

Metadata

Metadata

Assignees

Type

No type
No fields configured for issues without a type.

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions