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];
所以两个参数(maxArrayLength
和 maxArraysPerBucket
)只是用来控制 ArrayPool
实际存储和重用的内容,而不是可以分配多少(这是有道理的,如果有足够的可用内存,通常您不希望应用程序在分配内存时失败)。其他一切都在 GC
的控制之下,因此 ArrayPool
最终不会存储大量不可回收的内存。
传递给 ArrayPool.Create
的选项并不意味着您不能接收大于这些限制的数组。相反,它们用于控制 ConfigurableArrayPool
的分桶算法。第二个参数是桶中槽的最大数量,第一个参数是任何数组的最大大小。此值的上限为 1,048,576
的 internal 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.
我在 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];
所以两个参数(maxArrayLength
和 maxArraysPerBucket
)只是用来控制 ArrayPool
实际存储和重用的内容,而不是可以分配多少(这是有道理的,如果有足够的可用内存,通常您不希望应用程序在分配内存时失败)。其他一切都在 GC
的控制之下,因此 ArrayPool
最终不会存储大量不可回收的内存。
传递给 ArrayPool.Create
的选项并不意味着您不能接收大于这些限制的数组。相反,它们用于控制 ConfigurableArrayPool
的分桶算法。第二个参数是桶中槽的最大数量,第一个参数是任何数组的最大大小。此值的上限为 1,048,576
的 internal 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.