Оптимизация компилятора Java

Является ли компилятор Java достаточно умным, чтобы оптимизировать цикл ниже, извлекая

Double average = new Double( totalTime / callCount ); 

из цикла?

public double computeSD( Set values, int callCount, long totalTime ) {
  double diffs = 0.0d; 
  for( Iterator i=values.iterator(); i.hasNext(); ) {
    double value = ( ( Double )i.next() ).doubleValue(); 
    Double average = new Double( totalTime / callCount ); 
    diffs += ( value – average.doubleValue() ) * ( value – average.doubleValue() );
  } 
  double variance = diffs / callCount;
  return Math.sqrt( variance );
}

5 ответов

Java не будет и не может извлечь его из цикла. Любое использование ключевого слова "new" всегда приводит к созданию нового объекта. Вы бы лучше использовать Double.valueOf()

Смотрите Javadoc для Double.valueOf(double):

"Возвращает экземпляр Double, представляющий указанное двойное значение. Если новый экземпляр Double не требуется, этот метод обычно следует использовать в предпочтении перед конструктором Double(double), так как этот метод, вероятно, даст значительно лучшую производительность пространства и времени за счет кэширование часто запрашиваемых значений. "

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

Однако, используя valueOf все еще не ответ для вас!

valueOf это все еще вызов метода, и вызовы метода не оптимизируются. Будет звонить valueOf каждая итерация цикла. Просмотрите ваш метод и посчитайте вызовы метода. Сейчас это 6, в том числе hasNext а также new Double, который похож на вызов метода. Все это будет происходить каждый раз, и никакая оптимизация Java не изменит это. Вам лучше рефакторинг, чтобы удалить как можно больше вызовов методов из цикла.

Ничто не мешает компилятору байт-кода (java->bytecode) выполнить оптимизацию. Когда я работал в Symantec и разработал Java IDE, при написании компилятора мы попытались внести некоторые оптимизации в наш компилятор, но сказали, что никто (во внешнем мире), похоже, не заинтересован, и акцент был сделан на Just In Time (JIT). компилятор, который примерно такой же, как HotSpot в современных виртуальных машинах Sun.

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

Таким образом, компилятор source->bytecode, вероятно, не оптимизирует его, но виртуальная машина, вероятно, делает это. Если у вас есть что-то вроде Android, то он, вероятно, не выполняет оптимизацию времени выполнения.

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

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

Если вы используете doubleтем не менее, это гораздо более вероятно, будет оптимизировано (например, с использованием метода движения инвариантного кода цикла).

Если вы действительно хотите быть уверены, ответы на этот вопрос расскажут вам, как увидеть нативный код, который создает JIT-компилятор.

На самом деле, нет. Компилятор просто записывает байт-код. Если что-то оптимизирует код, это будет виртуальная машина Java, и это, вероятно, зависит от платформы, условий реализации и выполнения...

Другие вопросы по тегам