2009-03-11 3 views
38

Я ходил в XNA и видел, что класс Vector3 в нем использует публичные поля вместо свойств. Я попробовал быстрый тест и нашел, что для struct разница довольно драматична (добавление двух векторов вместе 100 миллионов раз заняло 2.0 с свойствами и 1.4 с полями). Для ссылочного типа разница не кажется такой большой, но она есть.Почему открытые поля быстрее, чем свойства?

Почему это так? Я знаю, что свойство скомпилировано в методы get_X и set_X, которые будут нести служебные расходы на вызов метода. Тем не менее, разве эти простые геттеры/сеттеры всегда встраиваются в JIT? Я знаю, что вы не можете гарантировать то, что решает JIT, но, конечно, это довольно высоко в списке вероятности? Что еще есть, что отделяет публичное поле от свойства на уровне машины?

И одна вещь, о которой я задавался вопросом: как реализована автоматическая реализация (public int Foo { get; set; }) «лучше» OO-дизайн, чем публичное поле? Или лучше сказал: как эти два разные? Я знаю, что сделать это свойство проще с отражением, но что-нибудь еще? Уверен, что ответ на оба вопроса - одно и то же.

BTW: Я использую .NET 3.5 SP1, который, я считаю, исправил проблемы, когда методы с structs (или методы из структур, я не уверен) не были вставлены, так что это не так. Я думаю, что я использую его по крайней мере, он определенно установлен, но опять же, я использую Vista 64-бит с SP1, который должен иметь DX10.1, за исключением того, что у меня нет DX10.1.

Также: да, я бег релиз сборка :)

EDIT: Я ценю быстрые ответы, ребята, но я указал, что я делать знают, что доступ к свойству является вызовом метода, но я не» t знать, почему, по-видимому, встроенный метод медленнее, чем прямой доступ к полям.

EDIT 2: Так что я создал еще один struct, который используется явный GetX() методы (о том, как я не скучаю по моей Java дней на все) и выполняется так же отключен ли я в-подкладки на нем (через [MethodImplAttribute(MethodImplOptions.NoInlining)]) или нет, так что вывод: нестатические методы, по-видимому, никогда не встраиваются, даже не в структуры.

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

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

EDIT 3: Я нашел this публикации по тому же вопросу. Его конечный вывод состоит в том, что вызов свойства действительно оптимизировался. Я также мог бы поклясться, что я много раз читал, что простые свойства getter/setter будут выровнены, несмотря на то, что они были callvirt в IL. Так сойду с ума?

EDIT 4: Reed Copsey отправил ответ в комментарии ниже:

Re: Edit3 - см мой обновленный комментарий: Я считаю, что это x86 JIT против проблем x64 JIT. JIT в x64 не столь зрелый. Я ожидал бы, что MS улучшит это быстро, так как все больше 64-битных систем выходят в интернет каждый день. - Рид Copsey

И мой ответ на его ответ:

Спасибо, это ответ! Я пытался форсировать сборку x86, и все методы были одинаково быстрыми и намного быстрее, чем x64. Это на самом деле очень шокирует меня, я понятия не имел, что живу в каменном веке на своей 64-битной ОС. Я включу ваш комментарий в свой ответ, чтобы он стал лучше. - JulianR

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

+0

Вопрос: Что произойдет, если поле открыто, но есть свойство. Тогда она включена? – Quibblesome

+0

Не похоже, нет. – JulianR

+1

Re: Edit3 - см. Мой обновленный комментарий: Я считаю, что это x86 JIT vs x64 JIT. JIT в x64 не столь зрелый. Я ожидал бы, что MS улучшит это быстро, так как все больше 64-битных систем выходят в интернет каждый день. –

ответ

15

Edit 2:

У меня был еще один потенциальный мысль здесь:

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

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


Edit 3:

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

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

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


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

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

---- От исходной записи - но обнаружил, что это не был вопрос --------

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

+0

Да, я попытался закрыть все экземпляры VS и запустить .exe в папке Release, но тот же результат (хотя обе версии немного быстрее вне VS). И да, это хорошая причина использовать свойства, даже если вы сначала не заполняете get/set. – JulianR

+0

. Наилучшие примеры использования для типов структур - это те, которые служат для связывания нескольких переменных вместе с клейкой лентой (например, координаты точки).Если предполагается, что структура допускает любую пару целых чисел и сообщает о них как X и Y, на самом деле нет никакого полезного поведения, которую будущая версия этого типа могла бы добавить к аксессурам свойств X и Y без нарушения правил. Лучше иметь структуру, чтобы сказать, что это (поле X и поле Y), чем держать его «секретным». – supercat

3
  • Общественных полей являются прямыми заданиями
  • Свойств являются методами, то больше коды, незначительная, но больше.
+0

Да, я знаю, как я уже сказал, но когда метод геттера/сеттера встроен, разве это не прямой доступ к полю поддержки свойства? – JulianR

+0

Джулиан - да, он должен. Вы были в VS, хотя? Если это так, VS-проект VS отключает многие оптимизации JIT, даже если это сборка релиза. См. Мой комментарий ниже. –

5

Вы должны прочитать эту статью Vance. В нем подробно описывается, почему методы не всегда встроены JIT'er, даже если они выглядят совершенно очевидно, что они должны быть.

http://blogs.msdn.com/vancem/archive/2008/08/19/to-inline-or-not-to-inline-that-is-the-question.aspx

+0

Вот документ, в котором рассматриваются затраты на инкрустирование: как время выполнения, так и стоимость усреднения (с фокусом GC): http://cs.anu.edu.au/~Steve.Blackburn/pubs/papers/writebarrier-ismm- 2002.pdf –

3

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

3

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

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