为什么 MemoryPool 比 ArrayPool 慢,分配的多?

Why is MemoryPool slower and allocates more than ArrayPool?

我不完全确定我在测试中是否做错了什么,但从我的结果来看,MemoryPool 始终比 ArrayPool 更慢并且分配的内存更多,因为您无论如何都可以将 Array 类型转换为 Memory,这有什么意义使用内存池?

using System.Buffers;
using BenchmarkDotNet.Running;
using BenchmarkDotNet.Attributes;

BenchmarkRunner.Run<test>();

[MemoryDiagnoser]
public class test
{
    [Benchmark]
    public void WithArrayPool()
    {
        ArrayPool<int> pool = ArrayPool<int>.Shared;

        for (int z = 0; z < 100; z++)
        {
            var memory = pool.Rent(2347);
            
            for (int i = 0; i < memory.Length; i++)
            {
                memory[i] = i + 1;
            }

            int total = 0;

            for (int i = 0; i < memory.Length; i++)
            {
                total += memory[i];
            }

            pool.Return(memory);
        }
    }

    [Benchmark]
    public void WithMemoryPool()
    {
        MemoryPool<int> pool = MemoryPool<int>.Shared;

        for (int z = 0; z < 100; z++)
        {
            var rentedArray = pool.Rent(2347);
            var memory = rentedArray.Memory;
            
            for (int i = 0; i < memory.Length; i++)
            {
                memory.Span[i] = i + 1;
            }

            int total = 0;

            for (int i = 0; i < memory.Length; i++)
            {
                total += memory.Span[i];
            }

            rentedArray.Dispose();
        }
    }
}
Method Mean Error StdDev Allocated
WithArrayPool 770.2 us 2.27 us 2.01 us 1 B
WithMemoryPool 1,714.6 us 0.56 us 0.50 us 2,402 B

上面是我的测试代码和结果。内存池实际上只是一般来说速度较慢,还是我遗漏了什么?如果 MemoryPool 实际上更慢,它有什么用例?

谢谢。

关于性能。

memory.Span[i]的重复调用是罪魁祸首。
GitHub 处的源代码显示在 属性 getter.

后面发生了相当多的处理

不要重复调用,而是将调用的结果存储在变量中

var span = memory.Span;

请参阅下面的完整代码块。

现在 Mean 个数字几乎相等。

Method Mean Error StdDev Median Gen 0 Allocated
WithArrayPool 333.4 us 2.34 us 5.15 us 331.0 us - -
WithMemoryPool 368.6 us 7.08 us 5.53 us 366.7 us 0.4883 2,400 B

[Benchmark]
public void WithMemoryPool()
{
    MemoryPool<int> pool = MemoryPool<int>.Shared;

    for (int z = 0; z < 100; z++)
    {
        var rentedArray = pool.Rent(2347);
        var memory = rentedArray.Memory;
        var span = memory.Span; 

        for (int i = 0; i < memory.Length; i++)
        {
            span[i] = i + 1;
        }

        int total = 0;

        for (int i = 0; i < memory.Length; i++)
        {
            total += span[i];
        }

        rentedArray.Dispose();
    }
}

关于分配内存的不同。

这是设计使然。
已经有一个很好的 解释了这一点。