java中的反思或内省有多贵

时间:2013-10-10 14:24:51

标签: java performance if-statement introspection

我想在java中使用reflexion或introspection来替换“IF - ELSE”语句,我想知道那么昂贵的是“Reflexion”VS“IF - ELSE”语句吗?如果我使用aprox 700.000迭代进行循环,那么效率会更高吗?

3 个答案:

答案 0 :(得分:1)

参见Effective Java,Item 53:首选接口到反射

性能受损。反射方法调用要慢得多 普通方法调用。 确切地说要慢多少,因为 工作中有很多因素。在我的机器上,速度差异可以是 小到两倍或大到五十倍。

答案 1 :(得分:0)

我找到this documentation,我了解风险

答案 2 :(得分:0)

正如您可能知道的那样,条件问题是它们削弱了处理器的可预测性特征。 这意味着如果错误,预取实际上会变成缺点。 当今天的处理器不知道比较的结果可能是什么时会发生这种情况,所以他们下注。 在IF-ELSE语句中,处理器有50%的概率正确预测下一条要执行的指令。 如果我们幸运的话,我们每个周期执行更多指令,如果不是,我们会得到一个约16个周期的中等惩罚,以便处理器从错误的预取中恢复。

那说让我们继续思考。 反思意味着,IF表现对您很重要。在大多数框架中,反射与地址调用是C_reflection = 3*C_address_call。在Java中它更糟糕,我真的没有官方数据。最大的问题是名称/地址/可用性解析。

那说,让我们去现实世界,看看一些数字。我们现在可以理解,证明甚至预测结果。

我们测试了2个班级,3个考试。总共10M电话/测试|每班5M电话:

  1. 条件
  2. 反射
  3. 通用界面
  4. 这些是以秒为单位的数字:

    条件 - 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());
    
        }
    }
    
    • 在创建性能测试之前,我们需要确保编译器尽可能少地优化/修改我们的代码,这解释了测试中您可能看不到直观的一些语句。