что быстрее? - PullRequest
       19

что быстрее?

2 голосов
/ 22 февраля 2011

Мне было интересно, что из следующего будет выполнено быстрее, просто из любопытства. Язык - Java.

int num = -500;
int num2 = 0;

while( Math.abs(num) > num2 )
    num2 ++;

или

int num = -500;
int num2 = 0;
num = Math.abs(num);

while( num > num2 )
    num2 ++;

По сути, мне интересно, вызывается ли 'Math.abs' для каждой итерации цикла while, или происходит некоторая оптимизация кода в фоновом режиме?

Спасибо!

Ответы [ 7 ]

5 голосов
/ 22 февраля 2011

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

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

3 голосов
/ 22 февраля 2011

Да, Math.abs(num) вызывается для каждой итерации, потому что Java никогда не может сказать или угадать, что возвращаемое значение только зависит от параметра.

Для Java метод является"равно" Math.random().

Так что в первом примере используется больше процессорного времени.

1 голос
/ 28 апреля 2011

Из любопытства я выполнил ненаучный тест, который дал следующие результаты:

Для сравнения:

  • Количество прогревов ([1]): 1000
  • Количество итераций ([1]): 1500
  • Количество удаленных выбросов ([1]): 300
  • Столбики ошибок, показывающие CI с95% пригодности [1] для каждого решения и уровня масштабирования

Информация о хосте:

  • Версия Java: 1.6.0_21
  • Поставщик Java: Sun MicrosystemsInc.
  • Аргументы Java VM: -Xmx1024m;-Dfile.encoding = Cp1252
  • Архитектура ОС: amd64
  • Имя ОС: Windows 7
  • Версия ОС: 6.1
  • Доступные ядра: 2
  • Свободная память, доступная для JVM (байты): 122182232
  • Максимальная память (байты): 954466304
  • Общее количество используемой памяти (байты): 124125184
0 голосов
/ 22 февраля 2011

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

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

  2. , если он не работаеттогда очевидно, что второй быстрее.

Так что я думаю, вам не стоит беспокоиться о подобных вещах.

0 голосов
/ 22 февраля 2011
class AbsTest {

   public static void main(String[] args) {
       int num = -2000000000;
       int num2 = 0;



       long then = System.currentTimeMillis();
       while( Math.abs(num) > num2 )
           num2 ++;

       long then2 = System.currentTimeMillis();
       num = Math.abs(num);
       num2 = 0;

       while( num > num2 )
           num2 ++;

       long now = System.currentTimeMillis();
       System.out.println(then2 - then); // first time
       System.out.println(now - then2); // second time

   }

}

результат:

C:\Documents and Settings\glowcoder\My Documents>java AbsTest
2953
1828

C:\Documents and Settings\glowcoder\My Documents>
0 голосов
/ 22 февраля 2011

Java-код

package test;

public class SpeedTest 
{
    public void first()
    {
        int num = -500;
        int num2 = 0;

        while( Math.abs(num) > num2 )
            num2 ++;
    }

    public void second()
    {
        int num = -500;
        int num2 = 0;
        num = Math.abs(num);

        while( num > num2 )
            num2 ++;
    }
}

Байт-код

Compiled from "SpeedTest.java"
public class test.SpeedTest extends java.lang.Object{
public test.SpeedTest();
  Code:
   0:   aload_0
   1:   invokespecial   #8; //Method java/lang/Object."<init>":()V
   4:   return

public void first();
  Code:
   0:   sipush  -500
   3:   istore_1
   4:   iconst_0
   5:   istore_2
   6:   goto    12
   9:   iinc    2, 1
   12:  iload_1
   13:  invokestatic    #15; //Method java/lang/Math.abs:(I)I
   16:  iload_2
   17:  if_icmpgt       9
   20:  return

public void second();
  Code:
   0:   sipush  -500
   3:   istore_1
   4:   iconst_0
   5:   istore_2
   6:   iload_1
   7:   invokestatic    #15; //Method java/lang/Math.abs:(I)I
   10:  istore_1
   11:  goto    17
   14:  iinc    2, 1
   17:  iload_1
   18:  iload_2
   19:  if_icmpgt       14
   22:  return
}

Из вышеперечисленного оба они по существу принимают ~ 20 инструкций.Если вы очень разборчивы, то первый - быстрый.

Причина различий в том, что вы вычисляете и сохраняете результат при втором подходе.Который вам нужно снова всплыть при сравнении.В первом случае вы непосредственно сравниваете значение регистра сразу после Math.absотсюда две дополнительные инструкции.


Обновление

As pointed out by @ide and @bestsss:

Количество инструкций в байт-коде на самом деле не коррелирует с количеством их фактического вызова.,Плюс есть HotSpot, чтобы оживить ситуацию (например, оптимизацию мертвого кода).

Как и в этом примере, Math.abs() вызывается с фиксированным значением -500.Таким образом, HotSpot JVM может оптимизировать его.

Подробнее см. В комментариях ниже.

0 голосов
/ 22 февраля 2011

Второй должен выполнять функцию абсолютного значения каждый проход цикла while. Конечно, это верно только в том случае, если Java больше не оптимизирует для хранения результатов операций, подобных этой, и я считаю, что это так. Java давно не имела такой оптимизации, теперь она использует JIT.

Итак, чтобы ответить на ваш вопрос, первый будет быстрее.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...