Я ходил в XNA и видел, что класс Vector3
в нем использует публичные поля вместо свойств. Я попробовал быстрый тест и обнаружил, что при a struct
разница довольно драматична (добавление двух векторов вместе 100 миллионов раз заняло 2.0 с свойствами и 1.4 с полями). Для ссылочного типа разница не кажется такой большой, но она есть.
Так почему это? Я знаю, что свойство скомпилировано в методы get_X
и set_X
, которые повлекут за собой служебные вызовы метода. Однако, разве эти простые геттеры/сеттеры всегда не встраиваются в JIT? Я знаю, что вы не можете гарантировать то, что решает JIT, но, конечно, это довольно высоко в списке вероятности? Что еще есть, что отделяет публичное поле от свойства на уровне машины?
И одна вещь, о которой я задавался вопросом: как автоматическое реализованное свойство (public int Foo { get; set; }
) "лучше" OO-дизайна, чем публичное поле? Или лучше сказал: как эти два разных? Я знаю, что сделать это свойство проще с отражением, но что-нибудь еще? Уверен, что ответ на оба вопроса - одно и то же.
BTW: Я использую .NET 3.5 SP1, который, как я считаю, исправил проблемы, когда методы с structs (или методы structs, я не уверен) не были вставлены, так что это не так. Я думаю, что я использую его по крайней мере, он определенно установлен, но опять же, я использую Vista 64-бит с SP1, который должен иметь DX10.1, за исключением того, что у меня нет DX10.1..
Также: да, я запускал выпускную сборку:)
РЕДАКТИРОВАТЬ: я очень благодарен ребятам за ответы, но я указал, что знаю, что доступ к ресурсу является вызовом метода, но я не знаю, почему, предположительно, внутри метод медленнее, чем прямой доступ к полям.
EDIT 2. Итак, я создал еще один struct
, в котором использовались явные методы GetX(), как я вообще не пропустил свои дни Java), и это было выполнено независимо от того, отключена ли я в (через [MethodImplAttribute(MethodImplOptions.NoInlining)]
) или нет, поэтому вывод: нестатические методы, по-видимому, никогда не встраиваются, даже на структуры.
Я думал, что есть исключения, где JIT может выбрать вызов виртуального метода. Почему это не может произойти в структурах, которые не знают наследования, и поэтому вызов метода может указывать только на один возможный метод, верно? Или это потому, что вы можете реализовать на нем интерфейс?
Это позор, потому что это заставляет меня задуматься об использовании свойств в критичных для производительности материалах, но использование полей заставляет меня чувствовать себя грязным, и я мог бы написать то, что я делаю в C.
РЕДАКТИРОВАТЬ 3: я нашел это, разместив информацию о том же предмете. Его конечный вывод состоит в том, что вызов свойства действительно оптимизировался. Я также мог бы поклясться, что много раз читал, что простые свойства getter/setter будут выровнены, несмотря на то, что они были callvirt
в IL. Так я схожу с ума?
EDIT 4: Рид Копси опубликовал ответ в комментарии ниже:
Re: Edit3 - см. мой обновленный комментарий: Я считаю, что это x86 JIT vs x64 JIT. JIT в x64 не столь зрелый. Я ожидал бы, что MS улучшит это быстро, так как все больше 64-битных систем выходят в интернет каждый день. - Рид Копси
И мой ответ на его ответ:
Спасибо, это ответ! Я пытался форсировать сборку x86, и все методы были одинаково быстрыми и намного быстрее, чем x64. Это на самом деле очень шокирует меня, я понятия не имел, что живу в каменном веке на своей 64-битной ОС. Я включу ваш комментарий в свой ответ, чтобы он стал лучше. - JulianR
Спасибо всем!