2014-02-14 5 views
0

Я попытался следующий код:Почему вызов функции быстрее, чем вызов функции?

public class Test { 
    public static void main(String[] args) { 
     int x = 9, y = 9, z = 0; 
     long startTime = System.currentTimeMillis(); 
     // System.out.println("loop one start time = " + startTime); 
     for (int i = 0; i < 10000; i++) { 
      for (int j = 0; j < 10000; j++) { 
       z = x + y; 
      } 
     } 
     System.out.println("loop one use time = " + (System.currentTimeMillis() - startTime) + ",z = " + z); 

     startTime = System.currentTimeMillis(); 
     // System.out.println("loop two start time = " + startTime); 
     for (int i = 0; i < 10000; i++) { 
      for (int j = 0; j < 10000; j++) { 
       z = sum(x, y); 
      } 
     } 
     System.out.println("loop two use time = " + (System.currentTimeMillis() - startTime) + ",z = " + z); 

    } 

    public static int sum(int x, int y) { 
     int t; 
     t = x + y; 
     return t; 
    } 
} 

Вывод на консоль:

loop one use time = 216,z = 18 
loop two use time = 70,z = 18. 

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


Update: Я обменялся две петли, теперь цикл один занимает меньше времени !!

loop two use time = 219,z = 18 
loop one use time = 69,z = 18 
+4

Быстрый вопрос - какой результат, если вы поменяете две петли вокруг кода? –

+4

Возможный дубликат [Как написать правильный микро-тест в Java?] (Http://stackoverflow.com/questions/504103/how-do-i-write-a-correct-micro-benchmark-in-java) - потому что, как вы измеряете, вряд ли что-нибудь пригодится. –

+0

Не удается подтвердить на моем ПК - одно время использования = 2, z = 18 цикл два времени использования = 5, z = 18. :-) – Smutje

ответ

1

Writing a correct micro-benchmark очень трудолюбивый и подверженный ошибкам. Я бы предложил делать микро-тесты только с уже имеющейся библиотекой, например, например. Caliper, который специально предназначен для этого.

Вашего микро-тест имеет довольно много недостатков, что приведет к непредсказуемым результатам:

  1. Вы не делаете ни одного разминки.
  2. Вы сравниваете оба подхода в своем основном методе, тем самым давая компилятору JIT более трудное время для оптимизации кода.
  3. Код "z = x + y;" доходит до "z = 9 + 9;" и никогда не изменяется во время цикла, поэтому цикл может быть полностью оптимизирован до простого выражения «z = 18».

Во всяком случае, вот код для соответствующего теста сделано с суппорту:

@VmOptions("-server") 
public class Test { 

    @Benchmark 
    public int timeSum1(long reps) { 
     int dummy = 0; 
     int x = 9, y = 9; 
     for (int j = 0; j < reps; j++) { 
      dummy = x + y; 
     } 
     return dummy; 
    } 

    @Benchmark 
    public int timeSum2(long reps) { 
     int dummy = 0; 
     int x = 9, y = 9; 
     for (int j = 0; j < reps; j++) { 
      dummy = sum(x, y); 
     } 
     return dummy; 
    } 

    public static int sum(int x, int y) { 
     int t; 
     t = x + y; 
     return t; 
    } 
} 

Вы можете посмотреть на результаты для этого теста здесь:

Результаты ожидаются: оба подхода берут примерно одно и то же время, потому что они могут быть встроены компилятором JIT. Выполнение с -server обоих подходов по-прежнему занимает примерно одно и то же время, но оптимизировано немного лучше.

0

от чтения комментариев, которые я получил эту идею, попробуйте ниже код

public class Test { 
    public static void main(String[] args) { 
     int x = 9, y = 9, z = 0; 
     for (int i = 0; i < 10000; i++) { 
      for (int j = 0; j < 10000; j++) { 
       z = x + y; 
       // z = sum(x, y); 
      } 
     } 
     long startTime = System.currentTimeMillis(); 
     // System.out.println("loop one start time = " + startTime); 
     for (int i = 0; i < 10000; i++) { 
      for (int j = 0; j < 10000; j++) { 
       z = x + y; 
      } 
     } 
     System.out.println("loop one use time = " 
       + (System.currentTimeMillis() - startTime) + ",z = " + z); 

     startTime = System.currentTimeMillis(); 
     // System.out.println("loop two start time = " + startTime); 
     for (int i = 0; i < 10000; i++) { 
      for (int j = 0; j < 10000; j++) { 
       z = sum(x, y); 
      } 
     } 
     System.out.println("loop two use time = " 
       + (System.currentTimeMillis() - startTime) + ",z = " + z); 

    } 

    public static int sum(int x, int y) { 
     int t; 
     t = x + y; 
     return t; 
    } 
} 

какой результат покажет, что обе петли имеют то же самое время, потому что JVM разогревается свои внутренние функции и готовы служить на его пальцах. :)

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

Смежные вопросы