Производительность для свойств в .NET.
Я где-то читал, что наличие публичных свойств предпочтительнее наличия публичных членов в классе.
-
Это только из-за абстарации и модульности? Есть ли какие-либо другие причины превышения?
-
Доступ к свойствам включается в вызовы функций компилятором. Что касается свойств без резервного хранилища (например, public string UserName { get; set; }
), какова будет накладная производительность по сравнению с прямым доступом к членству? (Я знаю, что это обычно не имеет значения, но в некоторых моих кодах свойства доступны миллионы раз.)
Edit1:
Я проверил некоторый тестовый код над целыми членами и свойствами, а публичные члены были примерно в 3-4 раза быстрее, чем свойства. (~ 57 мс. Против ~ 206 мс. В Debug и 57 против 97 в Release было наиболее распространенным значением запуска). Для 10 миллионов чтений и записей оба достаточно малы, чтобы не оправдывать изменение чего-либо.
код:
class TestTime1
{
public TestTime1() { }
public int id=0;
}
class TestTime2
{
public TestTime2() { }
[DefaultValue(0)]
public int ID { get; set; }
}
class Program
{
static void Main(string[] args)
{
try
{
TestTime1 time1 = new TestTime1();
TestTime2 time2 = new TestTime2();
Stopwatch watch1 = new Stopwatch();
Stopwatch watch2 = new Stopwatch();
watch2.Start();
for (int i = 0; i < 10000000; i++)
{
time2.ID = i;
i = time2.ID;
}
watch2.Stop();
watch1.Start();
for (int i = 0; i < 10000000; i++)
{
time1.id = i;
i = time1.id;
}
watch1.Stop();
Console.WriteLine("Time for 1 and 2 : {0},{1}",watch1.ElapsedMilliseconds,watch2.ElapsedMilliseconds);
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
Console.In.ReadLine();
}
}
Ответы
Ответ 1
Это только из-за абстарации и модульности? Есть ли какие-либо другие причины превышения?
Не то, чтобы я знал; эти причины сами по себе достаточно убедительны. Но, возможно, кто-то еще вскочит на это.
Доступ к свойствам включается в вызовы функций компилятором. Для свойств без резервного хранилища (например, public string UserName {get; set;}), какими будут издержки на производительность по сравнению с прямым доступом к элементу? (Я знаю, что это не должно меняться, но в некоторых из моего кода доступ к свойствам осуществляется миллионы раз.)
В полученном промежуточном языке доступ к ресурсу переводится в вызов метода. Однако, как говорится в слове, это только промежуточный язык: он скомпилирован Just-In-Time до другого. Этот шаг перевода также включает в себя оптимизации, такие как встраивание тривиальных методов, таких как простые аксессоры свойств.
Я бы ожидал (но вам нужно будет проверить, чтобы убедиться), что JITter позаботится о таких аксессуарах, поэтому не должно быть разницы в производительности.
Ответ 2
Выполнение теста 20 раз подряд, гарантируя, что оптимизация JIT включена в сборке Release:
Time for 1 and 2 : 47,66
Time for 1 and 2 : 37,42
Time for 1 and 2 : 25,36
Time for 1 and 2 : 25,25
Time for 1 and 2 : 27,25
Time for 1 and 2 : 25,25
Time for 1 and 2 : 26,25
Time for 1 and 2 : 25,25
Time for 1 and 2 : 25,25
Time for 1 and 2 : 25,25
Time for 1 and 2 : 25,25
Time for 1 and 2 : 25,25
Time for 1 and 2 : 25,25
Time for 1 and 2 : 25,25
Time for 1 and 2 : 25,25
Time for 1 and 2 : 25,25
Time for 1 and 2 : 25,25
Time for 1 and 2 : 25,25
Time for 1 and 2 : 25,25
Time for 1 and 2 : 25,25
Да, JITter хорошо разбирается в аксессуарах свойств. Perf не является проблемой и никогда не должен рассматриваться.
Ответ 3
Не беспокойтесь о производительности. Это настолько незначительно, что вы не должны рассматривать ослабление инкапсуляции класса; это была бы преждевременная оптимизация наихудшего типа.
Ответ 4
Это в основном для целей абстракции (позже вы можете добавить проверку, не нарушая существующий код, или требуя перекомпиляции).
Даже при использовании автоматических свойств все еще есть поле поддержки, сгенерированное компилятором, и будет выполняться как таковое.
Ответ 5
Убедитесь, что вы используете Ctrl-F5 вместо F5; в противном случае отладчик все равно будет подключаться, а некоторые оптимизации могут работать не так, даже в режиме деблокирования. По крайней мере, случай на моей машине: F5 дает похожие результаты тому, что вы опубликовали, тогда как Ctrl-F5 дает равные результаты.
Ответ 6
1) Его принципы инкапсуляции, но другие функции .NET используют такие свойства, как привязка данных.
2) Я не уверен, что согласен с этим, Я всегда слышал, что если свойство является прямым get/set его так же быстро, как и стандартный доступ к полю - компилятор делает это это для вас.
Обновление:, похоже, немного, компилируется для вызова метода, но JIT-оптимизирован. В любом случае, такая проблема производительности не будет иметь значимого влияния на ваш код. Однако обратите внимание, что руководство по реализации свойств заключается в том, чтобы сделать их максимально легкими, они не ожидаются, что вызывающие абоненты будут дорогими.
Ответ 7
После того, как я разместил сообщение this, я понял, что он в основном скрывает внутреннюю работу вашего объекта.
Ответ 8
Я уже спрашивал тот же вопрос.
Я предполагаю, что вы используете VS2008, используете 64-битную ОС и имеете компиляцию в "Любой процессор"? Если это так, свойства не встраиваются компилятором x64 JIT. Они работают на 32-битных, делая их идентичными по производительности публичным полям.
Ответ 9
Если вам нужен конкретный пример того, что свойства необходимы для того, что вы не можете делать с регулярными переменными-членами, подумайте о наследовании: если класс использует открытый элемент, производные от этого класса не могут выполнить проверку или другие параметры getter/поведение сеттера. Они застряли в переменной как есть, и если они хотят сделать что-то другое, они должны: 1) игнорировать существующую переменную-член и создать новое свойство, 2) добавить новое свойство и 3) переопределить каждый метод, который или ссылается на переменную-член, чтобы вместо этого использовать свойство. Мало того, что это излишне больше работы, если человек, пишущий производный класс, не имеет доступа к источнику, может быть почти невозможным.
Если базовый класс использует свойства вместо переменных-членов, это просто вопрос добавления проверки или другого поведения к функции get/set, и все готово.