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

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,因为我的场景实际上涉及在两个方法之间进行调用,并且据我所知,这不能使用该方法。我绝对乐于接受任何建议,无论我在这里寻求两全其美的建议。

预先感谢您的协助。

最佳答案

由于我的场景涉及的内容太多,无法进一步解释(在这里尽量保持简单),因此我通过允许最终开发人员决定他们想要速度还是垃圾来解决此问题。

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

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

关于c# - 何时首选分配与租用阵列?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/56221675/

10-16 06:30