C#中的ArrayPool创建方法

ArrayPool create method in C#

我在 C# 中使用 ArrayPool。 我想创建自己的池,其中数组的最大数量为 5,数组的最大大小为 1050000。 我使用了这个 ArrayPool.Create() 方法。 我无法理解一件事 - 我试图在下面的代码片段中从池中租用 10 次,虽然我将最大数组指定为 5,但为什么它没有显示任何错误。 另外,我将最大长度指定为 1050000.Then 我如何能够毫无错误地租用 4200000 数组?

        byte[] buffer;
        ArrayPool<byte> pool = ArrayPool<byte>.Create(1050000, 5);

        for (int i = 0; i < 10; i++)
        {
            buffer = pool.Rent(4200000);
        }

Documentation 没有为 Rent 方法定义异常(尽管至少有一个可以抛出的异常 - ArgumentOutOfRangeException 对于负数组大小)。

查看来源code for the Create method - it returns ConfigurableArrayPool。它的 Rent 方法将尝试找到一个与请求匹配的数组,如果没有合适的数组,它只会分配一个新的:

// The request was for a size too large for the pool.  Allocate an array of exactly the requested length.
// When it's returned to the pool, we'll simply throw it away.
buffer = new T[minimumLength];

所以两个参数(maxArrayLengthmaxArraysPerBucket)只是用来控制 ArrayPool 实际存储和重用的内容,而不是可以分配多少(这是有道理的,如果有足够的可用内存,通常您不希望应用程序在分配内存时失败)。其他一切都在 GC 的控制之下,因此 ArrayPool 最终不会存储大量不可回收的内存。

传递给 ArrayPool.Create 的选项并不意味着您不能接收大于这些限制的数组。相反,它们用于控制 ConfigurableArrayPool 的分桶算法。第二个参数是桶中槽的最大数量,第一个参数是任何数组的最大大小。此值的上限为 1,048,576internal constant,它已经比您的 1,050,000.

当您从数组池中Rent时,算法将尝试在buckets/slots之一中定位一个数组。这些桶(及其内部插槽)的数量受您传入的值的限制。如果池没有请求的 minimum 大小的数组,因为所有插槽正在使用中,或者因为请求的大小大于最大值,它将 分配 一个新的(不合并)和 return 那。

简而言之,当您请求的数组大于传递给 Create 方法的(上限)大小时,您将进行分配并收到一个不参与池的数组。使用此数组调用 Return 不会将其放回池中;相反 it will be "dropped".

但请记住,这些规则仅适用于内置数组池。您(或其他人)可以编写一个实现来限制 returned 数组的大小甚至抛出 - 尽管我认为那些 可能 不被认为是好的-表现良好(至少没有支持文档)。

根据您的评论更新

虽然没有直接对应桶数的参数,但间接。桶的数量是使用您传入的最大数组大小计算的。 max buckets is determined based on powers of 2 and some other logic.