何时首选分配阵列与租用阵列?

时间:2019-05-20 13:08:30

标签: c# performance memory .net-core garbage-collection

我目前正在设计解决方案,并且发现自己处于有趣的性能场景中。我已经放置了一个非常简单的解决方案来演示这种情况,可以在这里找到:

https://github.com/Mike-EEE/Stash/tree/master/AllocationVsRent

此问题的核心是阵列的分配与租用。在此解决方案中找到的一种方法执行租借,如下所示:

[Benchmark]
public int Rented()
{
    var array = _pool.Rent(2);
    array[0] = 1;
    array[1] = 2;
    var result = array[0] + array[1];
    _pool.Return(array);
    return result;
}

另一个执行分配,如下所示:

[Benchmark(Baseline = true)]
public int Allocated()
{
    var array = new int[2];
    array[0] = 1;
    array[1] = 2;

    var result = array[0] + array[1];
    return result;
}

运行这两个基准测试时,我得到以下结果:

BenchmarkDotNet=v0.11.5, OS=Windows 10.0.17763.475 (1809/October2018Update/Redstone5)
AMD Ryzen 7 2700X, 1 CPU, 8 logical and 4 physical cores
.NET Core SDK=3.0.100-preview5-011568
  [Host]     : .NET Core 3.0.0-preview5-27626-15 (CoreCLR 4.6.27622.75, CoreFX 4.700.19.22408), 64bit RyuJIT
  DefaultJob : .NET Core 3.0.0-preview5-27626-15 (CoreCLR 4.6.27622.75, CoreFX 4.700.19.22408), 64bit RyuJIT


|    Method |      Mean |     Error |    StdDev | Ratio | RatioSD |  Gen 0 | Gen 1 | Gen 2 | Allocated |
|---------- |----------:|----------:|----------:|------:|--------:|-------:|------:|------:|----------:|
|    Rented | 29.563 ns | 0.1736 ns | 0.1450 ns |  5.01 |    0.27 |      - |     - |     - |         - |
| Allocated |  5.825 ns | 0.1440 ns | 0.2522 ns |  1.00 |    0.00 | 0.0077 |     - |     - |      32 B |

尽管Allocated基准测试速度更快,但它确实会调用垃圾回收。而对于Rented基准而言,它速度较慢,但​​没有垃圾回收罚金。

所以我的基本问题是:哪个是首选?即使分配确实会产生垃圾,也可以进行分配吗?双关语,虽然速度更快,但对我来说仍然感觉肮脏。

请注意:我不能使用stackalloc,因为我的场景实际上涉及在两种方法之间进行调用,据我所知,这不能使用该方法。我当然乐意接受任何我想忽略这两个方面的建议。

在此先感谢您的帮助。

1 个答案:

答案 0 :(得分:0)

由于我的场景涉及太多内容,无法进一步说明(此处尝试简化),因此,我正在通过允许最终开发人员确定他们是否需要速度或垃圾来解决此问题。

更多情况下,我正在开发的API首先是零分配,而速度是重要但次要的重点。

在所有其他调用中,该API都是零分配的,并且比我正在测试的现有API更快,此调用除外。因此,默认情况下,我会将其分配为零以与API的其余部分保持一致,但是,如果消费/最终开发人员可以接受垃圾处理,并且希望这几纳秒的时间,那么他们可以轻松地做到这一点。