Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Avoid draining the ArrayPool with undisposed JsonDocuments #2178

Merged
merged 2 commits into from Jul 26, 2023

Conversation

stephentoub
Copy link
Collaborator

My understanding is this code is likely going to be overhauled to not use JsonDocument at all, but in the meantime we can make a small tweak to significantly improve throughput. JsonDocument.Parse creates a JsonDocument backed by one or more ArrayPool arrays; those arrays are returned when the instance is disposed. If it's never disposed, the arrays are never returned to the pool. That means that creating but not disposing lots of JsonDocument instances ends up incurring the cost (and contention) of searching the ArrayPool but ends up falling back to allocating anyway.

The problem is that JsonClaimSet isn't disposable and so the underlying JsonDocument is never disposed. As a patch until the code is overhauled, we can use JsonElement.Clone(), which creates a new JsonDocument not backed by ArrayPool arrays... we can then dispose of the original in order to return the arrays to the pool.

This still isn't ideal, as we're doing more allocating and copying than we'd like, but it ends up being much better than without.

My understanding is this code is likely going to be overhauled to not use JsonDocument at all, but in the meantime we can make a small tweak to significantly improve throughput. JsonDocument.Parse creates a JsonDocument backed by one or more ArrayPool arrays; those arrays are returned when the instance is disposed.  If it's never disposed, the arrays are never returned to the pool. That means that creating but not disposing lots of JsonDocument instances ends up incurring the cost (and contention) of searching the ArrayPool but ends up falling back to allocating anyway.

The problem is that JsonClaimSet isn't disposable and so the underlying JsonDocument is never disposed. As a patch until the code is overhauled, we can use JsonElement.Clone(), which creates a new JsonDocument not backed by ArrayPool arrays... we can then dispose of the original in order to return the arrays to the pool.

This still isn't ideal, as we're doing more allocating and copying than we'd like, but it ends up being much better than without.
@brentschmaltz brentschmaltz merged commit ddbf141 into AzureAD:dev7x Jul 26, 2023
1 check passed
@brentschmaltz
Copy link
Member

@stephentoub merged this as this will allow us to find other issues.
Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants