C# длина 1 массив по сравнению с одним значением, производительность и объем памяти - PullRequest
2 голосов
/ 03 мая 2020

Вопрос:

Какова производительность и накладные расходы памяти при использовании массива длиной 1 вместо значения напрямую?

private Item[] item = new Item[1];
   vs.
private Item item;

Использование:

У меня есть абстрактный базовый класс ItemHolder, который наследуется как классами SingleItemHolder и MultipleItemHolder. Первый содержит один элемент в качестве основного значения, а второй содержит список. Чтобы получить доступ к значению, я вижу три возможности:

Добавление двух методов к базовому классу

public abstract Item GetItem();
public abstract Item[] GetItems(int amount);

Недостаток, поскольку у SingleItemHolder есть ненужный метод для получения нескольких элементов при наличии только одного для каждого определения.
Другим методом будет реализация только второго метода и передача одного значения в виде массива длины 1

public override Item[] GetItems()
{
    return new[] { storedItem };
}

или сохранение одного значения в виде массива длины 1 на первом месте

private Item[] item = new Item[1];
public override Item[] GetItems()
{
    return item;
}

Держатели как для нескольких предметов, так и для одного предмета используются одинаково часто и довольно часто в целом. Методы, о которых идет речь, вполне могут называться десятки раз за игровой кадр со всего игрового мира. Поэтому мне интересно, какая версия была бы наиболее эффективной или, если быть более общим, какая разница в накладных расходах для массива длины 1 над одним значением.

Ответы [ 2 ]

2 голосов
/ 03 мая 2020

Просто короткая заметка. В мире. NET большой проблемой производительности является G C, который может легко заблокировать приложение на 50-100 мс. Скорее всего, вы не увидите большой разницы в чтении данных из объекта или массива с одним значением. Но вы, вероятно, получите штраф, если вам нужно много создавать такой объект. Вы наверняка должны избегать создания объектов из кода получателя.

Я думаю, что эта статья может быть полезна: https://michaelscodingspot.com/avoid-gc-pressure/. Также рассмотрите использование какого-либо инструмента профиля, чтобы проверить, сколько времени на самом деле это займет. Я предпочитаю использовать PerfView от MS. Это может занять некоторое время, чтобы начать использовать его, но вы, безусловно, получите выгоду в результате.

1 голос
/ 03 мая 2020

Какова производительность и затраты памяти при использовании массива длиной 1 вместо значения напрямую?

Это полностью зависит от того, как оптимизация компилятора, JiT-компилятор и сокращение доступа к индексам относятся к этому массиву сегодня. По сути, все это указатель. Процесс не заботится о том, указывает ли он на функцию, единственное int или начало массива int. Помимо перехода к функции индексатора и, возможно, проверки работоспособности индексатора, не должно быть никакого влияния на производительность. И даже этот один доступ к индексатору может быть сокращен или, по крайней мере, встроен.

теоретически возможно , что жертвы увидят ваш new int[1] и решат, что базовый c int сделает там. JiT может даже сделать это, если размер определяется только во время выполнения. Однако это маловероятно.

Если вам нужен массив там, вам нужен массив там. Странный случай, когда он иногда равен 1, не о чем беспокоиться. Даже если массив размера 1 как-то распространен, наличие пути с базисом c int будет микрооптимизацией. Это просто подпадает под скорость разгона: https://ericlippert.com/2012/12/17/performance-rant/

Если у вас две функциональные перегрузки - одна принимает int, а другая - int[] - вы должны, вероятно, только кодировать из int[] версии. Довольно просто связать версию int с вызовом версии массива.

...