Почему открытые поля быстрее свойств? - PullRequest
38 голосов
/ 11 марта 2009

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

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

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

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

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

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

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

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

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

РЕДАКТИРОВАТЬ 3 : Я нашел это сообщение о том же предмете. Его окончательный вывод заключается в том, что вызов свойства действительно был оптимизирован. Я также мог бы поклясться, что много раз читал, что простые свойства getter / setter будут встроены, несмотря на то, что в IL они равны callvirt. Так я схожу с ума?

РЕДАКТИРОВАТЬ 4 : Рид Копси опубликовал ответ в комментарии ниже:

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

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

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

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

Ответы [ 5 ]

15 голосов
/ 11 марта 2009

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

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

Вы упомянули, что работаете на x64. Я тестировал ту же проблему на x86 и видел ту же производительность при использовании авто-свойств и полей. Однако, если вы посмотрите на Connect и список рассылки / сообщения на форуме, в Интернете будет много ссылок на тот факт, что JIT CLR x64 представляет собой другую кодовую базу и имеет характеристики производительности, весьма отличные от JIT x86. Я думаю, это то место, где 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. Это может привести к изменению показателей производительности.

5 голосов
/ 11 марта 2009

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

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

3 голосов
/ 11 марта 2009

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

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

3 голосов
/ 11 марта 2009

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

3 голосов
/ 11 марта 2009
  • Открытые поля являются прямыми назначениями
  • Свойства - это методы, затем больше кода, незначительный, но больше.
...