dotnet / dotnet/runtime

[API Proposal]: Add ArrayPool<T>.Rent(int minimumLength, bool cleared = false)

Open
#121,156 6 comments 1 reaction 0 assignees View on GitHub
api-suggestion area-System.Buffers
Dominant language
C#
Stars
18.3k
Forks
5.6k
PR merge metrics
PR metrics pending

Description

### Background and motivation

When using the `ArrayPool` API, I sometimes require clean arrays to work with. To achieve this, I must use `Array.Clear` after each `ArrayPool.Rent` call.
While the extra call can be annoying, my worries are actually other ones; many arrays can contain sensitive information, which is why it's a common practice to clear those arrays when returning them to the pool. In fact, this seems to be so common that `ArrayPool.Return` already includes a boolean parameter to determine if the array should be cleared by the pool itself on return.
This produces to me a -probably minor- but still simple to spot performance problem: some arrays could end up being cleared twice. This "double clean" happens when the array is cleared on return, and again when it is cleared after rent (as you can never know for sure if the rented array is cleared or not).

To solve this, I propose to have an additional boolean parameter to `Rent` (or another overload to avoid binary breaking compatibility), making the method `Rent(int minimumLength, bool clear = false)` that determines if the array should be cleared up to `minimumLength` elements (the rest of the length isn't relevant to clear) before renting it.
The advantage of this change is to:

- Ease of use: Renting clear arrays becomes easier. No need to add the following `Array.Clear` after each rent.
- Performance: The pool could internally split zeroed arrays from non-zeroed ones. This would avoid "double cleaning" the arrays, as it can simply rent an array that was cleared during return. Mixing of both zeroed and non-zeroed "subpools" would only happen when one of them is depleted, to avoid allocating new arrays, in this case, returning a zeroed array from a normal rent is a no-op, while returning a non-zeroed array from a zeroed rent requires the pool to clean at minimum the `minimumLength` requested.

Also, as a minor note, maybe something similar could be done to `MemoryPool`, though, being honest, I barely use that API to know about it.

### API Proposal

```csharp
public abstract partial class ArrayPool
{
public virtual T[] Rent(int minimumLength, bool clear);
}
```

### API Usage

```csharp
ArrayPool pool = ArrayPool.Shared;

int[] clearArray = pool.Rent(315, true);
// No need to do Array.Clear(clearArray, 0, 315)

// ... work with sensible data that required a zeroed array ...

pool.Return(clearArray, true);
```

### Alternative Designs

We can already append an `Array.Clear` after each `ArrayPool.Shared.Rent` call, though we lost the possible performance improvement of avoiding double clear.

### Risks

Having two subpools of arrays (clear and unclear) could increase memory overhead, though that can be solved by tweaking the number of pooled elements.

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.