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

Я искал в 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 ..

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

РЕДАКТИРОВАТЬ: Я ценю быстрые ответы, ребята, но я указал, что я знаю, что доступ к свойству является вызовом метода, но я не знаю, почему, по-видимому, встроенный метод медленнее, чем прямой доступ к полю.

РЕДАКТИРОВАТЬ 2: Итак, я создал другой struct который использовал явные методы GetX() (о том, как я вообще не скучаю по своим дням в Java) и выполнял те же действия, независимо от того, отключил ли я встроенные функции (через [MethodImplAttribute(MethodImplOptions.NoInlining)]) или нет, так что вывод: нестатические методы, по-видимому, никогда не используются, даже на структурах.

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

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

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

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

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

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

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

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

5 ответов

Решение

Изменить 2:

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

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

Кроме того, к вашему сведению, структура / метод / и так далее, исправленная в.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. Это может привести к изменению показателей производительности.

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

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

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

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

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

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

Другие вопросы по тегам