Каковы (если таковые имеются) последствия наличия объекта или обнуляемого типа в качестве поля в структуре - PullRequest
0 голосов
/ 27 октября 2009

Из соображений производительности я использую структуры в нескольких случаях.

Если у меня в качестве члена в структуре есть объект или обнуляемый тип (другая структура, но обнуляемая), это отрицательно влияет на производительность. Потеряю ли я ту самую выгоду, которую пытаюсь получить?

Редактировать

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

Я не хочу звучать абразивно или неблагодарно, но как мне сделать свой вопрос более простым?

Влияет ли наличие объекта в качестве члена структуры на производительность или сводит на нет выгоды?

Ответы [ 5 ]

3 голосов
/ 27 октября 2009

Ну, C # - странный зверь, когда речь идет о части производительности struct vs classes.

Проверьте эту ссылку: http://msdn.microsoft.com/en-us/library/y23b5415(VS.71).aspx

Согласно Microsoft вы должны использовать структуру только тогда, когда размер экземпляра меньше 16 байт. Андрей прав. Если вы не передадите структуру, вы можете увидеть выигрыш в производительности. Семантика типа значения имеет высокую производительность (и временную память, в зависимости от того, что вы делаете), теряя при передаче их.

Что касается коллекций, то если вы используете неуниверсальную коллекцию, бокс и распаковка типа значения (в данном случае struct) будут иметь более высокие издержки производительности, чем ссылочный тип (то есть класс). Тем не менее, также верно, что структуры распределяются быстрее, чем классы.

Хотя структура и класс имеют один и тот же синтаксис, их поведение сильно отличается. Это может заставить вас совершить много ошибок, которые трудно отследить. Например, статические конструкторы в структуре не будут вызываться, когда вы вызываете ее public (скрытый конструктор) или оператор не будет работать со структурами.

Обнуляемые типы сами по себе реализованы со структурами. Но у них есть штраф. Даже каждая операция типа Nullable выделяет больше IL.

Ну, на мой взгляд, struct хорошо использовать для таких типов, как DateTime или Guids. Если вам нужен неизменный тип, используйте struct в противном случае, не используйте. Преимущества производительности не так велики. Точно так же даже накладные расходы не так велики. Поэтому, в конце концов, это зависит от ваших данных, которые вы храните в структуре, а также от того, как вы их используете.

2 голосов
/ 27 октября 2009

Лично я бы больше беспокоился о простом неправильном использовании структур; то, что вы описали, звучит как объект (класс) для меня.

В частности, я бы беспокоился о том, чтобы ваша структура была слишком большой; когда вы передаете структуру (между переменными, между методами и т. д.), она получает copyied . Если это большой жирный зверь с множеством полей (некоторые из которых сами являются зверями), то эта копия займет больше места в стеке и больше процессорного времени. В отличие от передачи ссылки на объект, который принимает постоянный размер / время (ширина для вашей архитектуры x86 / x64).


Если мы говорим о базовых обнуляемых типах, таких как классические "значения"; Nullable<T> конечно имеет накладные расходы; реальные вопросы:

  • это слишком много
  • это дороже, чем проверка, которую я все еще должен сделать для "магического числа" и т. Д.

В частности, все операторы и операторы на Nullable<T> получают дополнительный код - например:

int? a = ..., b = ...;
int? c = a + b;

действительно больше похож на:

int? c = (a.HasValue && b.HasValue) ?
              new Nullable<int>(a.GetValueOrDefault() + b.GetValueOrDefault())
            : new Nullable<int>();

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

2 голосов
/ 27 октября 2009

Нет, вы не потеряете выгоду обязательно. Одна из областей, в которой вы видите выигрыш в производительности от использования структуры, - это когда вы быстро создаете много объектов в цикле и не должны передавать эти объекты каким-либо другим методам. В этом случае у вас все будет хорошо, но не видя некоторого кода, невозможно сказать.

0 голосов
/ 17 августа 2012

Ни обнуляемые типы, ни типы неизменяемых классов не будут создавать проблемы в структуре. Однако при использовании изменяемых типов классов обычно следует придерживаться одного из двух подходов:

  1. Состояние, представленное изменяемым полем или свойством класса, должно быть * идентификатором *, а не * изменяемой символикой * изменяемого объекта, на который есть ссылка. Например, предположим, что структура имеет поле типа `Car`, которое содержит ссылку на красный автомобиль с идентификатором транспортного средства # 24601. Предположим далее, что кто-то копирует структуру, а затем окрашивает транспортное средство, обозначенное синим цветом. Ссылка на объект была бы уместной, если бы при таких обстоятельствах было бы желательно, чтобы структура содержала ссылку на синий автомобиль с идентификатором # 24601. Было бы неуместно, если кто-то хотел бы, чтобы структура все еще содержала ссылку на красный автомобиль (который должен был бы иметь какой-то другой идентификатор, так как номер автомобиля № 24601 синий).
  2. Код в структуре создает изменяемый экземпляр класса, выполняет все мутации, которые когда-либо будут выполняться с этим экземпляром (возможно, копирование данных из переданного экземпляра), и сохраняет его в закрытом поле после завершения всех мутаций. Как только ссылка на экземпляр сохраняется в поле, структура никогда не должна снова изменять этот экземпляр и не подвергать его никакому коду, который мог бы его изменить.

Обратите внимание, что два подхода предлагают очень разную семантику; никогда не должно быть трудного выбора между ними, так как при любых обстоятельствах, когда одно уместно, другое было бы совершенно неуместно. В некоторых случаях могут существовать другие подходы, которые будут работать несколько лучше, но в целом следует определить, включает ли состояние структуры идентичность или изменяемые характеристики любых вложенных изменяемых классов, и использовать один из шаблонов выше в зависимости от ситуации.

0 голосов
/ 27 октября 2009

Nullable<T> по сути является кортежем флагов T и bool, указывающих, является ли он null или нет. Таким образом, его эффект производительности точно такой же: с точки зрения размера, вы получаете это дополнительное bool (плюс любое дополнение, которое оно сочтет необходимым).

Для ссылок на ссылочные типы особых последствий нет. Это просто размер ссылки на объект (обычно sizeof(IntPtr), хотя я не думаю, что на это есть определенная гарантия). Конечно, GC также должен время от времени прослеживать эти ссылки, но ссылка внутри struct не является чем-то особенным в этом отношении.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...