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

Производительность для свойств в .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();
    }
}
4b9b3361

Ответ 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, и все готово.