Локальные переменные или поля класса?
Сегодня я прочитал пост об улучшении производительности в С# и 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