Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/355.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/performance/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
解释Java反射性能:为什么它惊人地快?_Java_Performance_Reflection_Interface - Fatal编程技术网

解释Java反射性能:为什么它惊人地快?

解释Java反射性能:为什么它惊人地快?,java,performance,reflection,interface,Java,Performance,Reflection,Interface,我见过其他线程说java反射性能比使用非反射调用慢10-100倍 我在1.6中的测试表明情况并非如此,但我发现了一些其他有趣的事情,需要有人向我解释 我有实现接口的对象。我做了三件事1)使用对对象的引用我将该对象转换到接口并通过接口调用该方法2)使用对实际对象的引用直接调用该方法,3)通过反射调用该方法。我看到#1接口调用最快,紧随其后的是#3反射,但我注意到直接方法调用最慢,相差很大 我不明白,我本以为直接调用会最快,然后接口,然后反射会慢得多 Blah和ComplexClass与主类位于不同

我见过其他线程说java反射性能比使用非反射调用慢10-100倍

我在1.6中的测试表明情况并非如此,但我发现了一些其他有趣的事情,需要有人向我解释

我有实现接口的对象。我做了三件事1)使用对对象的引用我将该对象转换到接口并通过接口调用该方法2)使用对实际对象的引用直接调用该方法,3)通过反射调用该方法。我看到#1接口调用最快,紧随其后的是#3反射,但我注意到直接方法调用最慢,相差很大

我不明白,我本以为直接调用会最快,然后接口,然后反射会慢得多

Blah和ComplexClass与主类位于不同的包中,它们都有一个doSomething(intx)方法,该方法实现接口并只打印整数x

以下是我的结果(以毫秒为单位的次数,结果非常相似/多次试验): 直接调用方法:107194 直接从对象转换到接口调用方法:89594 通过反射调用方法:90453

这是我的密码:

public class Main
{

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args)
    {
        Blah x = new Blah();
        ComplexClass cc = new ComplexClass();
        test((Object) x, cc);
    }

    public static void test(Object x, ComplexClass cc)
    {
        long start, end;
        long time1, time2, time3 = 0;
        int numToDo = 1000000;
        MyInterface interfaceClass = (MyInterface) x;

        //warming up the cache
        for (int i = 0; i < numToDo; i++)
        {
            cc.doSomething(i); //calls a method directly
        }

        start = System.currentTimeMillis();
        for (int i = 0; i < numToDo; i++)
        {
            cc.doSomething(i); //calls a method directly
        }
        end = System.currentTimeMillis();
        time1 = end - start;

        start = System.currentTimeMillis();
        for (int i = 0; i < numToDo; i++)
        {
            interfaceClass.doSomething(i); //casts an object to an interface then calls the method
        }
        end = System.currentTimeMillis();
        time2 = end - start;


        try
        {
            Class xClass = x.getClass();
            Class[] argTypes =
            {
                int.class
            };
            Method m = xClass.getMethod("doSomething", argTypes);
            Object[] paramList = new Object[1];
            start = System.currentTimeMillis();
            for (int i = 0; i < numToDo; i++)
            {
                paramList[0] = i;
                m.invoke(x, paramList); //calls via reflection
            }
            end = System.currentTimeMillis();
            time3 = end - start;

        } catch (Exception ex)
        {
        }

        System.out.println("calling a method directly: " + time1);
        System.out.println("calling a method directly from an object cast to an interface: " + time2);
        System.out.println("calling a method through reflection: " + time3);
    }
公共类主
{
/**
*@param指定命令行参数
*/
公共静态void main(字符串[]args)
{
Blah x=新的Blah();
ComplexClass cc=新的ComplexClass();
测试((对象)x,cc);
}
公共静态无效测试(对象x,ComplexClass cc)
{
漫长的开始,漫长的结束;
长时间1,时间2,时间3=0;
int numToDo=1000000;
MyInterface interfaceClass=(MyInterface)x;
//预热缓存
对于(int i=0;i
将所有测试放在同一个程序中是一个微基准标记错误-Java性能有一定的预热。这是最重要的失败

把你的测试放在不同的程序中,然后运行测试几次,这样你就能感觉到热身什么时候结束以及统计意义

还有一个包含内部循环的巨大方法。Hotspot似乎比以前更擅长处理这个问题,但它仍然不太好


您应该会发现,使用
-server
调用虚拟方法(即使是由不同的类加载器加载)在紧循环中,会得到完全优化。因此,说直接调用比反射调用快多少没有多大意义。

首先,反射在最新的JDK中快得多。其次,我预计热点编译器将优化所有这些调用,使其大致与代码一致。它可以对r进行运行时分析使您反复调用同一个函数,这样它就可以优化反射(和虚拟函数调用).与接口示例相同。

我的测试表明,如果java能够内联函数,直接调用可以非常快。内联直接调用比反射调用快200-300倍。在ubuntu 12.10、Jdk 1.6.35、CPU Xeon E5-2620上测试

Java每天都在变得越来越智能

import java.lang.reflect.Method;

public class Main 
{
    static class Test
    {
        int i=0;
        public void set(int value){
            this.i = value;
        }
    }

public static void main( String[] args) throws Exception
{
    Test test = new Test();
    int max = 10000000;

    long direct = System.currentTimeMillis();
    for( int i=0; i<max; i++){
        Integer io = new Integer(i*i);
        test.set(io);
    }
    System.out.println("Direct : " + (System.currentTimeMillis() - direct));

    Method method = Test.class.getMethod("set", Integer.TYPE);
    long reflection = System.currentTimeMillis();        
    for( int i=0; i<max; i++){
        Integer io = new Integer(i*i);
        method.invoke(test, io );
    }
    System.out.println("Reflection : " + ( System.currentTimeMillis() - reflection));

}
}
import java.lang.reflect.Method;
公共班机
{
静态类测试
{
int i=0;
公共无效集(int值){
这个。i=值;
}
}
公共静态void main(字符串[]args)引发异常
{
测试=新测试();
int max=10000000;
long direct=System.currentTimeMillis();

对于(int i=0;iWHy CW?这是一个有效的非主观编程相关问题?为什么投票要结束?!我把标题变成了一个问题,问那些除非有标记否则看不到问题的人。但是,社区维基??你说有一个包含内部循环的巨大方法是什么意思?你是说测试方法本身太大了吗这是一个问题吗?什么是-服务器?我明白你的观点,每个测试都不在它们自己的方法中。虽然我有一种感觉,我会看到类似的结果。我可能会在得到这些结果后发表一篇单独的文章。你有一个大的测试方法,它会循环数百万次。-服务器是速度更快的switch(但会增加启动时间,并且不一定存在,尤其是在Windows JRE上)。测试应该在其自己的进程中。为每个测试重新运行程序。