Skip to content

[release/10.0] Fix NoopLimiter disposal in DefaultPartitionedRateLimiter Heartbeat - #133647

Open
github-actions[bot] wants to merge 3 commits into
release/10.0from
backport/pr-127582-to-release/10.0
Open

github-actions[bot] wants to merge 3 commits into
release/10.0from
backport/pr-127582-to-release/10.0

Conversation

@github-actions

@github-actions github-actions Bot commented Sep 10, 2026 •

Copy link
Copy Markdown
Contributor

Backport of #127582 to release/10.0

/cc @agocke @copilot

Customer Impact

  • Customer reported
  • Found internally

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.

Regression

  • Yes
  • No

Looks like this code existed all the way back to at least .NET 7.

Testing

New unit tests added, change validated by user.

Risk

Low

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
Successfully started running 3 pipeline(s).
13 pipeline(s) were filtered out due to trigger conditions.
There may be pipelines that require an authorized user to comment /azp run to run.

@dotnet-policy-service

Copy link
Copy Markdown
Contributor

Tagging subscribers to this area: @JulieLeeMSFT, @VSadov
See info in area-owners.md if you want to be subscribed.

…127582)

Fixes `DefaultPartitionedRateLimiter` so that `NoopLimiter` partitions
are evicted and disposed by the Heartbeat timer, which previously never
happened because `NoopLimiter.IdleDuration` always returns `null`.

## Changes Made

- Introduced a `LimiterEntry` wrapper that tracks a
`LastAccessTimestamp` (updated on each `Acquire`/`WaitAsync` call)
alongside the `RateLimiter` instance.
- Added `GetIdleDuration(LimiterEntry)` helper that falls back to the
elapsed time since last access for `NoopLimiter` (whose `IdleDuration`
is always `null`), and returns `null` for all other limiter types that
return `null` (preserving the existing "do not evict" contract).
- Updated the Heartbeat eviction check to use the `is TimeSpan
idleDuration && idleDuration > s_idleTimeLimit` pattern (with `??
TimeSpan.Zero` for the under-lock re-check), correctly handling the
nullable `TimeSpan?` return — `null` skips eviction, matching the
original pattern.
- Used `Volatile.Read`/`Volatile.Write` for atomic 64-bit timestamp
access on 32-bit platforms.
- Added a `RateLimiterHelper.GetElapsedTime(long)` overload to avoid
`.GetValueOrDefault()` at call sites.
- Added tests covering `NoopLimiter` eviction via Heartbeat and
verifying that non-`NoopLimiter` partitions with `IdleDuration == null`
are not evicted while active.

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: VSadov <8218165+VSadov@users.noreply.github.com>
Co-authored-by: Vladimir Sadov <vsadov@microsoft.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
@github-actions
github-actions Bot force-pushed the backport/pr-127582-to-release/10.0 branch from 78e27af to 85f3f55 Compare September 14, 2026 17:58
@rbhanda rbhanda added the Servicing-approved Approved for servicing release label Sep 14, 2026
@rbhanda rbhanda added this to the 10.0.13 milestone Sep 14, 2026
@akoeplinger

Copy link
Copy Markdown
Member

@agocke fyi there are build failures

@agocke

agocke commented Sep 29, 2026

Copy link
Copy Markdown
Member

@copilot please fix conflicts

Co-authored-by: agocke <515774+agocke@users.noreply.github.com>

Copilot AI commented Sep 29, 2026

Copy link
Copy Markdown
Contributor

@copilot please fix conflicts

The branch already includes the current release/10.0 base in merge commit a0b17fa, so there are no unresolved merge conflicts. I also fixed the reported compile errors in 64e4fb1ff.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area-System.Threading Servicing-approved Approved for servicing release

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants