Когда предпочтительнее выделять, чем арендовать массив? - PullRequest
2 голосов
/ 20 мая 2019

Я сейчас разрабатываю решение и попал в интересный сценарий производительности. Я поместил очень простое решение, демонстрирующее этот сценарий, который можно найти здесь:

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 голосов
/ 23 мая 2019

Так как в моем сценарии слишком много информации, чтобы объяснить дальше (пытаясь упростить его здесь), Я решаю эту проблему, разрешая конечному разработчику решить, хотят ли они скорости или мусора.

Для небольшого контекста, разрабатываемый мной API - это в первую очередь нулевое распределение и скорость как важный, но вторичный фокус.

Во всех других вызовах API имеет нулевое распределение и работает быстрее, чем существующий API, с которым я тестирую, за исключением этого вызова. Таким образом, по умолчанию я сделаю это нулевым распределением, чтобы оно соответствовало остальной части API, но если потребитель / конечный разработчик в порядке с мусором и хочет эти несколько дополнительных наносекунд, они могут легко позволить это вместо этого.

...