【问题标题】:ArrayPool create method in C#C#中的ArrayPool创建方法
【发布时间】:2020-06-25 21:22:40
【问题描述】:

我在 C# 中使用 ArrayPool。 我想创建自己的池,最大阵列数为 5,阵列最大大小为 1050000。 我使用了这个 ArrayPool.Create() 方法。 我无法理解一件事-我试图在下面的 sn-p 中从池中租用 10 次,尽管我将 max arrays 指定为 5 ,但为什么它没有显示任何错误。 另外,我将最大长度指定为 1050000。那么我如何才能租用 4200000 的数组而不会出现任何错误?

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

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

【问题讨论】:

  • 您指定租用的最小尺寸,因为它们正在被重复使用,如果您想要更大的尺寸,您需要租用您需要的最小尺寸。还有你要解决的问题是什么。
  • 嘿,我编辑了我的问题并补充说
  • 我已回滚您的编辑。这是一个完全独立的问题,应该作为一个新问题提出

标签: c# buffer compiler-optimization


【解决方案1】:

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

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

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

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

更新基于您的 cmets:

虽然没有与桶数直接对应的参数,但存在间接。桶的数量是使用您传入的最大数组大小来计算的。max buckets is determined 基于 2 的幂和some other logic

【讨论】:

  • 非常感谢。你能看看我所做的编辑,它描述了我想要解决的问题。
  • 这是一个完全不同的问题,您应该回滚您的编辑并发布一个新问题。但我可以马上告诉你(我只是从你的描述中怀疑这一点)你忽略了Stream.Read 的返回结果并假设它填满了你的整个缓冲区。它可以返回从 1 到缓冲区大小的任何值,并且可能以实际值为上限。您需要处理读取的字节数较少的情况(可能总是给定您的缓冲区大小)
  • 我们无法控制要创建的存储桶数量,但只能控制每个存储桶的数组数量,对吧?
  • 另外,不同的存储桶对我们有什么帮助?
  • 桶数由最大数组大小决定。他们采用 log2 并执行一些其他计算来确定。我不能说水桶有什么帮助。但是一些非常聪明的人将其设计为高效,否则拥有一个游泳池就没有意义了。如果您想确定,您可能想在 dotnet github 上提问(或在此处发布新问题)
【解决方案2】:

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

查看Create 方法的源code - 它返回ConfigurableArrayPoolRent 方法会尝试查找与请求匹配的数组,如果没有合适的数组,它将分配一个新的:

// 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 最终不会存储大量不可回收的内存。

【讨论】:

  • 非常感谢。你能看看我所做的编辑,它描述了我想要解决的问题
  • 我们无法控制将要创建的桶的数量,但只能控制每个桶的数组数量,对吧?
  • 另外,不同的桶对我们有什么帮助?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-07-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-11-16
  • 1970-01-01
相关资源
最近更新 更多