Написание эффективного кода и оптимизация памяти - PullRequest
3 голосов
/ 15 июня 2011

У меня есть эти два фрагмента кода (написанные на Java), который более эффективен?

int foo(){

   int result;
   for(int i = 0; i < n;i++){
      SomeObject a,b,c;
      a = new SomeObject();
      b = new SomeObject();
      c = new SomeObject();
      //do something with a,b,c
      //and derive result
   }
   return result;
}

или

int foo(){

   int result;
   SomeObject a,b,c;
   a = new SomeObject();
   b = new SomeObject();
   c = new SomeObject();

   for(int i = 0; i < n;i++){
      a.flush(); //reset object do not create new though
      b.flush(); //reset object do not create new though
      c.flush(); //reset object do not create new though
      //do something with a,b,c
      //and derive result
   }
   return result;
}

Во втором фрагменте я переместил локальныйпеременные вне цикла, поэтому эффективно он создает только один их экземпляр.Это улучшает что-нибудь?Логично, что это имеет смысл, когда переменные находятся внутри цикла.Но сможет ли сборщик мусора эффективно очистить объекты?

РЕДАКТИРОВАТЬ: Обновлен отрывок, касающийся создания объектов.

Ответы [ 5 ]

4 голосов
/ 15 июня 2011

Вы переместили переменные , но это не объекты . Предполагая, что вы присваиваете различные значения a, b и c на каждой итерации цикла, вы вообще не сократили выделение памяти - вы просто излишне расширили диапазон переменных.

Если вам не нужно изменять значения a, b и c в цикле, то это другой вопрос, и было бы лучше назначить их вне цикла, а не на каждая итерация.

Главное - понять разницу между объектами и переменными . В частности, создание «новых» переменных на каждой итерации цикла фактически ничего не стоит.

РЕДАКТИРОВАТЬ: Хорошо, с обновленным вопросом, ясно, это разница в том, сколько объектов создано. Однако, в зависимости от того, что именно происходит во второй форме, все еще может быть более предпочтительным: это, безусловно, легче понять, и это не зависит от деталей того, что делает операция flush. С другой стороны, если создание экземпляра SomeObject стоит дорого (например, он генерирует криптографические ключи), то лучше оптимизировать его.

Короче говоря: это зависит. Сначала напишите наиболее читаемый код, измерьте его и сравните с вашими требованиями к производительности. Переходите к менее очевидному коду только тогда, когда есть очевидная выгода.

3 голосов
/ 15 июня 2011

Как написано, они одинаковы. В обоих случаях память для ссылок SomeObject выделяется в кадре стека функции, один раз, когда функция начинает выполняться.

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

Но обратите внимание, что будет существенная разница, если один или несколько объектов будут инициализированы с new и созданный объект одинаков на каждой итерации цикла и многоразово. Тогда было бы гораздо лучше избегать ненужного создания и удаления одного и того же объекта на каждой итерации цикла.

Изменить для обновленного вопроса

FWIW, я не согласен с Джоном Скитом в этой детали: учитывая обновленный вопрос, всегда будет предпочтительным создавать объекты вне цикла и повторно использовать их на каждой итерации. Если другой код в методе настолько сложен, что делает его нежелательным, то метод, а не цикл, нуждается в рефакторинге.

1 голос
/ 15 июня 2011

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

Код для ясности сначала, эффективностьвторой (компилятор все равно умнее вас)

1 голос
/ 15 июня 2011

Сборка мусора эффективно очищает объект, однако это не означает, что это нулевая стоимость. Во втором примере вы должны учитывать, что у вас должны быть изменяемые объекты, которые могут быть сброшены () обратно в исходное состояние, что опять же не по нулевой цене.

Ответ на большинство вопросов производительности: напишите код как можно более понятным и простым, и результат также будет иметь хорошую производительность, которой обычно достаточно. Если у вас есть проблемы с производительностью, профилируйте ваше приложение, чтобы увидеть, что может потребоваться изменить.

0 голосов
/ 15 июня 2011

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

...