Локальные переменные или поля класса?

Сегодня я прочитал пост об улучшении производительности в С# и Java.

Я все еще застрял на этом:


19. Не злоупотребляйте переменными экземпляра

Производительность может быть улучшена с помощью локальных переменных. Код в примере 1 будет выполняться быстрее, чем код в примере 2.

Example1:

public void loop() {
    int j = 0;
    for ( int i = 0; i<250000;i++){
        j = j + 1;
    }
}

Пример 2:

int i;
public void loop() {
    int j = 0;
    for (i = 0; i<250000;i++){
        j = j + 1;
    }
}

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

Это просто любопытство, я не пытаюсь поместить переменную 'i' в область видимости класса: p Это правда, что быстрее использовать локальные переменные? Или, может быть, в каком-то случае?

Ответ 1

  • Стек быстрее, чем куча.

    void f()
    {
        int x = 123; // <- located in stack
    }
    
    int x; // <- located in heap
    void f()
    {
        x = 123  
    }
    
  • Не забывайте принцип локальных данных. Локальные данные должны быть лучше кэшированы в кэше ЦП. Если данные близки, они будут полностью загружены в кеш процессора, а ЦП не должен получать их из памяти.

Ответ 2

Производительность зависит от количества шагов, необходимых для получения переменной. Локальные адреса переменных известны во время компиляции (они являются известным смещением в стеке), для доступа к члену, который вы загружаете для объекта 'this', чтобы получить адрес фактического объекта, прежде чем вы сможете получить адрес переменной-члена.

Ответ 3

Даже если это произойдет, в этих случаях будет практически не измеримая разница. В первом случае, вероятно, есть некоторая оптимизация на уровне реестра процессора, но опять же:

  • это почти нерелевантно
  • и что более важно, часто непредсказуемо.

В терминах памяти это точно то же самое, нет никакой разницы.

В первом случае это вообще лучше: поскольку вы объявляете переменную, она была немедленно использована, которая обычно используется в хорошем шаблоне, поскольку она

  • легко понять (сферы ответственности)
  • простой рефакторинг

Ответ 4

Я подозреваю, что очень мало различий, однако в том случае, когда переменная является членом объекта, каждый доступ требует косвенности через this (эффективно), тогда как локальная переменная не имеет значения.

В более общем плане, объект не нуждается в члене i, он используется только в контексте цикла, поэтому сделать его локальным для его использования лучше в любом случае.

Ответ 5

Я проверил расчет с 500 000 итераций, где я использовал около 20 переменных локально и один, который делает это с полями. Локальный переменный тест составлял около 20 миллисекунд, а один с полями составлял около 30 миллисекунд. Значительное увеличение производительности при использовании локальных переменных.

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

Ответ 6

В С# другая незначительная разница - это количество сгенерированных инструкций MSIL (я думаю, это похоже на Java).

Для загрузки поля экземпляра требуется две инструкции:

ldarg.0                 // load "this" reference onto stack
ldfld   MyClass.myField // find the field and load its value

... но для загрузки локальной переменной требуется только одна команда:

ldloc.0                 // load the value at index 0 from the list of local variables