2013-10-10 2 views
1

Я хочу использовать рефлексию или интроспекцию в java для замены инструкциями «IF-ELSE», я хочу знать, насколько это дорогостоящие заявления «Reflexion» VS «IF-ELSE»? и что более эффективно, если я использую цикл с aprox 700 000 итераций?Насколько дорогим является рефлексия или интроспекция в java

+0

Почему вы не испытываете это самостоятельно? –

+0

Проведите несколько тестов и оцените результаты. –

ответ

1

См Effective Java, пункт 53: Предпочитают интерфейсы для отражения страдающей

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

+0

Спасибо за ваш ответ – kakashy

0

Проблема с условиями, как вы могли бы знать, что они калечат предсказуемость особенности процессоров. Это означает, что предварительная выборка фактически превратится в недостаток, если это неверно. Это то, что происходит в современных процессорах, когда они не знают, что может быть результатом сравнения, поэтому они ставка. В заявлении IF-ELSE процессор имеет 50% вероятность правильного предсказания следующей команды, которая должна быть выполнена. Если нам повезет, мы выполняем больше инструкций за цикл, если мы этого не делаем, мы получаем среду штрафа за ~ 16 циклов, чтобы процессор мог восстановиться из-за неправильной предварительной выборки.

Это говорит о продолжении размышлений. Отражение - это среднее значение, для вас важна производительность. В большинстве случаев отражение и адресный вызов - C_reflection = 3*C_address_call. В Java это еще хуже, и у меня нет официальных данных об этом. Самая большая проблема - разрешение имен/адресов/доступности.

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

Мы тестируем 2 класса, 3 теста. В общей сложности 10M calls/test | 5M вызовов в классе:

  1. Условный
  2. Reflection
  3. Common Interface

И это число в секундах:

Условия - 0,022333

Отражение - 3.02087

Интерфейс - 0,012547

Так общий интерфейс является победителем в вашем случае, второй приходит условный вызов почти вдвое время выполнения (для указанных выше причин). И последний с чрезвычайно заметной разницей приходит к размышлению.

Вот код тестовой *:

import java.lang.reflect.InvocationTargetException; 

public class JavaReflectionTest { 

    public interface ClassInterface { 
     public void execute(); 
     public String getCount(); 
    } 


    public static class ClassOne implements ClassInterface { 

     int count = 0; 

     public String getCount(){ 
      return String.valueOf(count); 
     } 

     public void execute(){ 
      count++; 
     } 
    } 

    public static class ClassTwo implements ClassInterface { 

     int count = 0; 

     public String getCount(){ 
      return String.valueOf(count); 
     } 

     public void execute(){ 
      count++; 
     } 
    } 


    public static void main(String[] args) throws SecurityException, NoSuchMethodException, 
                IllegalArgumentException, IllegalAccessException, 
                InvocationTargetException, ClassNotFoundException, InterruptedException { 

     ClassOne one = new ClassOne(); 
     ClassTwo two = new ClassTwo(); 
     ClassInterface ione = new ClassOne(); 
     ClassInterface itwo = new ClassTwo(); 
     long stopT; 
     long startT; 
     int i; 
     int mod; 

     //Warm up 
     for(i=0;i<350000;i++){ 
      one.execute(); 
      two.execute(); 
      ione.execute(); 
      itwo.execute(); 
      one.getClass().getMethod("execute").invoke(one,null); 
      two.getClass().getMethod("execute").invoke(two,null); 
     } 

     //Test conditional call 
     one = new ClassOne(); 
     two = new ClassTwo(); 
     Thread.sleep(1000); 
     startT=System.nanoTime(); 
     for(i=0;i<10000000;i++){ 
      mod=i%2; 
      if(mod==0) 
       one.execute(); 
      else 
       two.execute(); 
     } 
     stopT=System.nanoTime(); 
     System.out.println("Conditions - " + ((stopT-startT)/1000000000.0f)+ " Calls 1: " + one.getCount() + " Calls 2: " + two.getCount()); 

     //Test reflection 
     one = new ClassOne(); 
     two = new ClassTwo(); 
     Thread.sleep(1000); 
     startT = System.nanoTime(); 
     for(i=0;i<5000000;i++){ 
      mod=i%2; 
      one.getClass().getMethod("execute").invoke(one,null); 
      two.getClass().getMethod("execute").invoke(two,null); 
      mod=i%2; 
     } 
     stopT=System.nanoTime(); 
     System.out.println("Reflection - " + ((stopT-startT)/1000000000.0f)+ " Calls 1: " + one.getCount() + " Calls 2: " + two.getCount()); 

     //Test common interface 
     ione = new ClassOne(); 
     itwo = new ClassTwo(); 
     Thread.sleep(1000); 
     startT = System.nanoTime(); 
     for(i=0;i<5000000;i++){ 
      mod=i%2; 
      ione.execute(); 
      itwo.execute(); 
      mod=i%2; 
     } 
     stopT=System.nanoTime(); 
     System.out.println("Interface - " + ((stopT-startT)/1000000000.0f) + " Calls 1: " + ione.getCount() + " Calls 2: " + itwo.getCount()); 

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