Подтвердить что ты не робот

Почему открытые поля быстрее, чем свойства?

Я ходил в 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

Спасибо всем!

4b9b3361

Ответ 1

Изменить 2:

У меня была другая мысль:

Вы упомянули, что вы работаете на x64. Я тестировал эту же проблему на x86 и видел такую ​​же производительность при использовании auto-properties vs. fields. Однако, если вы посмотрите вокруг сообщений Connect и рассылки/сообщений на форуме, есть много ссылок онлайн о том, что x64 CLR JIT - это другая база кода и имеет очень разные характеристики производительности для x86 JIT. Я предполагаю, что это одно место, где x64 все еще отстает.

Кроме того, FYI, объект struct/method/etc, установленный в .net 3.5sp1, был на стороне x86, и был тот факт, что вызовы методов, которые занимали структуры как параметр, никогда не были бы встроены в x86 до .net3. 5sp1. Это довольно неуместно для обсуждения в вашей системе.


Изменить 3:

Другое: что XNA использует поля. Я на самом деле был на Game Fest, где они объявили XNA. Рико Мариани рассказал, где он поднял многие те же моменты, что и в своем блоге. Кажется, у XNA были похожие идеи, когда они разработали некоторые из основных объектов. См:

http://blogs.msdn.com/ricom/archive/2006/09/07/745085.aspx

В частности, проверьте пункт № 2.


Что касается того, почему автоматические свойства лучше, чем общедоступные поля:

Они позволяют вам изменять реализацию в v2 вашего класса и добавлять логику в процедуру get/set свойства по мере необходимости, не изменяя интерфейс для ваших конечных пользователей. Это может оказать глубокое влияние на вашу способность поддерживать вашу библиотеку и код с течением времени.

---- Из оригинального сообщения - но обнаружил, что это не проблема --------

Запустили ли вы сборку релиза вне VS? Это может быть одним из объяснений того, почему вещи не оптимизируются. Часто, если вы работаете в VS, даже оптимизированная версия сборки, хост-процесс VS отключает многие функции JIT. Это может привести к изменению показателей производительности.

Ответ 3

  • Открытые поля - это прямые назначения
  • Свойства - это методы, затем больше кода, несущественные, но более.

Ответ 4

XNA должен настроить таргетинг на XBox 360, а JIT в .NET Compact Framework не такой сложный, как его настольный аналог..NET CF JIT'er не будет встроить методы свойств.

Ответ 5

Доступ к полю - это просто ссылка на память, тогда как использование свойства вызывает вызов метода и включает служебные служебные вызовы функции. Причина использования свойств, а не полей, заключается в том, чтобы изолировать ваш код от изменений и обеспечить лучшую степень детализации доступа. Не подвергая ваше поле напрямую, вы больше контролируете, как осуществляется доступ. Использование автоматических полей позволяет получить типичное поведение getter/setter, но создает возможность изменять это без последующей необходимости распространения изменений на другие части кода.

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