2014-03-22 3 views
2

Сегодня я столкнулся с довольно удивительным поведением в java, or медленнее, чем and!Почему "или" медленнее, чем "и" в Java?

Я даже сделал тестовый пример, который вы можете видеть внизу. Теперь я удивляюсь, почему это происходит? Я делаю что-то неправильно или это происходит только на моем компьютере? Я не вижу причин, по которым or должен быть медленнее, чем and специально с этой значительной разницей. Я хочу проверить это явление на некоторых других языках, вы вообще не знаете об этом?

public class TestClass { 

    public static void main(String[] args) { 

     long[] or = new long[10]; 
     long[] and = new long[10]; 
     long lStartTime, lEndTime, difference = 0; 
     for (int idx = 0; idx < 10; idx++) { 

      lStartTime = System.nanoTime(); 
      for (int i= 0; i < 1000000000; i++) { 
       int j = i | i+1 ; 
      } 
      lEndTime = System.nanoTime(); 
      difference = lEndTime - lStartTime; 
      System.out.println("Elapsed milliseconds: " + difference/1000000); 
      or[idx] = difference; 

      lStartTime = System.nanoTime(); 
      for (int i= 0; i < 1000000000; i++) { 
       int j = i & i+1 ; 
      } 
      lEndTime = System.nanoTime(); 
      difference = lEndTime - lStartTime; 
      System.out.println("Elapsed milliseconds: " + difference/1000000); 
      and[idx] = difference; 
      System.out.println("------------------------------------"); 

     } 

     long tmp = 0; 
     for (long l : or) { 
      tmp += l; 
     } 
     tmp /= 10; 
     System.out.println("Elapsed milliseconds for or: " + tmp/1000000); 
     tmp = 0; 
     for (long l : and) { 
      tmp += l; 
     } 
     tmp /= 10; 
     System.out.println("Elapsed milliseconds for and: " + tmp/1000000); 
    } 
} 

результаты:

Elapsed milliseconds: 1600 
Elapsed milliseconds: 1332 
------------------------------------ 
Elapsed milliseconds: 1609 
Elapsed milliseconds: 1335 
------------------------------------ 
Elapsed milliseconds: 1609 
Elapsed milliseconds: 1335 
------------------------------------ 
Elapsed milliseconds: 1542 
Elapsed milliseconds: 1314 
------------------------------------ 
Elapsed milliseconds: 1705 
Elapsed milliseconds: 1324 
------------------------------------ 
Elapsed milliseconds: 1559 
Elapsed milliseconds: 1315 
------------------------------------ 
Elapsed milliseconds: 1526 
Elapsed milliseconds: 1314 
------------------------------------ 
Elapsed milliseconds: 1568 
Elapsed milliseconds: 1340 
------------------------------------ 
Elapsed milliseconds: 1551 
Elapsed milliseconds: 1318 
------------------------------------ 
Elapsed milliseconds: 1574 
Elapsed milliseconds: 1321 
------------------------------------ 
Elapsed milliseconds for or: 1584 
Elapsed milliseconds for and: 1325
+0

Я думаю, что это разные изменения. но 'AND' заполняется, а' OR' проверяет каждый бит, ... –

+0

@ AdrianPreuss- Я не понимаю, «я думаю, что это изменилось, переместившись», не могли бы вы объяснить? – mok

+0

Проверьте функцию http://en.wikipedia.org/wiki/Bitwise_operator –

ответ

4

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

Вот соответствующий тест делается в скобе (последний мерзавец версии необходимо для компиляции):

public class BitwiseOperatorPerformance { 
    @Benchmark 
    public int timeOr(int reps){ 
     int dummy = 0; 
     for (int i = 0; i < reps; i++) { 
      dummy |= i+1; 
     } 
     return dummy; 
    } 
    @Benchmark 
    public int timeAnd(int reps){ 
     int dummy = 0; 
     for (int i = 0; i < reps; i++) { 
      dummy &= i+1; 
     } 
     return dummy; 
    } 
} 

И вот результат теста: link

ДРОН-, что на производительность Операторы AND и OR точно такие же.

+0

Действительно полезно, я должен узнать об этом. – mok

5

побитовое ИЛИ не медленнее, чем побитовое И!

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

for (int idx = 0; idx < 10; idx++) { 

    lStartTime = System.nanoTime(); 
    for (int i= 0; i < 1000000000; i++) { 
     int j = i & i+1 ; 
    } 
    lEndTime = System.nanoTime(); 

    difference = lEndTime - lStartTime; 
    System.out.println("Elapsed milliseconds: " + difference/1000000); 
    and[idx] = difference; 

    lStartTime = System.nanoTime(); 
    for (int i= 0; i < 1000000000; i++) { 
     int j = i | i+1 ; 
    } 
    lEndTime = System.nanoTime(); 

    difference = lEndTime - lStartTime; 
    System.out.println("Elapsed milliseconds: " + difference/1000000); 
    or[idx] = difference; 

    System.out.println("------------------------------------"); 
} 

Я склонен предположить, что JVM применяет какие-то оптимизации выполнения во втором фрагменте.

+0

Я полностью согласен. Я пробовал как immibs и ... сказал. Но что случилось в моем тесте? – mok

+0

@mok: Как я уже говорил в нижней части ответа, я склонен предположить, что JVM применяет некоторую оптимизацию во время второго фрагмента. Помимо этого, я не думаю, что в вашем тесте есть что-то не так, только с вашими выводами из этого теста. –

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