这种反思性的Java例程可以加速吗?

时间:2013-08-19 14:52:40

标签: java reflection benchmarking

我试图在反射性能特征上找到某种确定的答案。在除非你必须“不要使用它”之外,没有什么是真正具体的。也许这没关系,因为用例决定了反射程序运行的好坏程度。

我放手了但是我读过几篇文章,这些文章表明Java 6的反射例程几乎和其他例程一样快,特别是如果你使用-server开关。

我根本没有看到这一点。我在Mac 10.8.4上使用Java 6.

看看我的日常生活。我只使用随机的东西,所以希望编译器/运行时不会以某种方式优化文字。我已经让我的for循环运行了很长时间,我总是得到直接例程大约13-15毫秒的值和反射例程大约590-595毫秒。

import java.lang.reflect.Field;
import java.util.Random;


public class Reflection {

    static final int ITERATIONS = 100000;

    static final String[] STRINGS = { "asdf", "qwer", "dfgh", "scvb", "ertyerty" };

    static final Random random = new Random( System.currentTimeMillis() );

    public static void main( String[] args ) throws Exception {
        for ( int i = 0; true; i++ ) {
            System.out.println( "i=" + i + ", direct=" + testDirectCallSpeed() + ", reflective=" + testReflectiveCallSpeed() );
        }
    }

    static class Blah {
        String a, b, c, d, e, f;
        int g, h, i, j, k, l;
        public String toString() { 
            StringBuilder sb = new StringBuilder( 100 );
            sb.append( super.toString() );
            sb.append( ", a=" ).append( a );
            sb.append( ", b=" ).append( b );
            sb.append( ", c=" ).append( c );
            sb.append( ", d=" ).append( d );
            sb.append( ", e=" ).append( e );
            sb.append( ", f=" ).append( f );
            sb.append( ", g=" ).append( g );
            sb.append( ", h=" ).append( h );
            sb.append( ", i=" ).append( i );
            sb.append( ", j=" ).append( j );
            sb.append( ", k=" ).append( k );
            sb.append( ", l=" ).append( l );
            return sb.toString();
        }
    }

    public static long testDirectCallSpeed() {
        System.gc();
        Blah[] blahs = new Blah[ ITERATIONS ];
        long begin = System.currentTimeMillis();
        Blah blah;
        for ( int i = 0; i < ITERATIONS; i++ ) {
            blah = new Blah();
            blah.a = getString();
            blah.b = getString();
            blah.c = getString();
            blah.d = getString();
            blah.e = getString();
            blah.f = getString();
            blah.g = getInt();
            blah.h = getInt();
            blah.i = getInt();
            blah.j = getInt();
            blah.k = getInt();
            blah.l = getInt();
            blahs[ i ] = blah;
        }
        printRandomBlah( blahs );
        return System.currentTimeMillis() - begin;
    }

    public static long testReflectiveCallSpeed() throws Exception {
        System.gc();
        Blah[] blahs = new Blah[ ITERATIONS ];
        long begin = System.currentTimeMillis();
        Blah blah;
        Class<?> type;
        for ( int i = 0; i < ITERATIONS; i++ ) {
            blah = new Blah();
            for ( Field f : Blah.class.getDeclaredFields() ) {
                type = f.getType();
                if ( String.class == type ) f.set( blah, getString() );
                else if ( int.class == type ) f.setInt( blah, getInt() );
            }
            blahs[ i ] = blah;
        }
        printRandomBlah( blahs );
        return System.currentTimeMillis() - begin;
    }

    public static void printRandomBlah( Blah[] blahs ) {
//      System.out.println( blahs[ random.nextInt( blahs.length ) ] );
    }

    public static int getInt() { return random.nextInt(); }
    public static String getString() { return STRINGS[ random.nextInt( STRINGS.length ) ]; }

}

1 个答案:

答案 0 :(得分:1)

如果你在“testReflectiveCall”的东西中提取所有没有真正调用setter的东西,那几乎是一个不可估量的差异。花费在列表导航数组迭代和元数据查找上的时间花费在反射调用中。

import java.lang.reflect.Field;
import java.util.Random;
public class Reflection {

    static final int ITERATIONS = 100;

    static final String[] STRINGS = { "asdf", "qwer", "dfgh", "scvb", "ertyerty" };

    static final Random random = new Random(System.currentTimeMillis());

    static Field fielda;
    static Field fieldb;
    static Field fieldc;
    static Field fieldd;
    static Field fielde;
    static Field fieldf;
    static Field fieldg;
    static Field fieldh;
    static Field fieldi;
    static Field fieldj;
    static Field fieldk;
    static Field fieldl;

    static {
        try {
            fielda = Blah.class.getField("a");
            fieldb = Blah.class.getField("b");
            fieldc = Blah.class.getField("c");
            fieldd = Blah.class.getField("d");
            fielde = Blah.class.getField("e");
            fieldf = Blah.class.getField("f");
            fieldg = Blah.class.getField("g");
            fieldh = Blah.class.getField("h");
            fieldi = Blah.class.getField("i");
            fieldj = Blah.class.getField("j");
            fieldk = Blah.class.getField("k");
            fieldl = Blah.class.getField("l");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) throws Exception {

        for (int i = 0; true; i++) {
            System.out.println("i=" + i + ", direct=" + testDirectCallSpeed() + ", reflective=" + testReflectiveCallSpeed());
        }
    }

    static class Blah {

        public String a, b, c, d, e, f;
        public int g, h, i, j, k, l;

        public String toString() {

            StringBuilder sb = new StringBuilder(100);
            sb.append(super.toString());
            sb.append(", a=").append(a);
            sb.append(", b=").append(b);
            sb.append(", c=").append(c);
            sb.append(", d=").append(d);
            sb.append(", e=").append(e);
            sb.append(", f=").append(f);
            sb.append(", g=").append(g);
            sb.append(", h=").append(h);
            sb.append(", i=").append(i);
            sb.append(", j=").append(j);
            sb.append(", k=").append(k);
            sb.append(", l=").append(l);
            return sb.toString();
        }
    }

    public static long testDirectCallSpeed() {

        System.gc();
        Blah[] blahs = new Blah[ITERATIONS];
        long begin = System.currentTimeMillis();
        Blah blah;
        for (int i = 0; i < ITERATIONS; i++) {
            blah = new Blah();
            blah.a = getString();
            blah.b = getString();
            blah.c = getString();
            blah.d = getString();
            blah.e = getString();
            blah.f = getString();
            blah.g = getInt();
            blah.h = getInt();
            blah.i = getInt();
            blah.j = getInt();
            blah.k = getInt();
            blah.l = getInt();
            blahs[i] = blah;
        }
        long exectionTime = System.currentTimeMillis() - begin;
        printRandomBlah(blahs);
        return exectionTime;
    }

    public static long testReflectiveCallSpeed() throws Exception {

        System.gc();
        Blah[] blahs = new Blah[ITERATIONS];
        long begin = System.currentTimeMillis();
        Blah blah;
        for (int i = 0; i < ITERATIONS; i++) {
            blah = new Blah();
            fielda.set(blah, getString());
            fieldb.set(blah, getString());
            fieldc.set(blah, getString());
            fieldd.set(blah, getString());
            fielde.set(blah, getString());
            fieldf.set(blah, getString());
            fieldg.set(blah, getInt());
            fieldh.set(blah, getInt());
            fieldi.set(blah, getInt());
            fieldj.set(blah, getInt());
            fieldk.set(blah, getInt());
            fieldl.set(blah, getInt());
            blahs[i] = blah;
        }
        long executionTime = System.currentTimeMillis() - begin;
        printRandomBlah(blahs);
        return executionTime;

    }

    public static void printRandomBlah(Blah[] blahs) {

        // System.out.println(blahs[random.nextInt(blahs.length)]);
    }

    public static int getInt() {

        return random.nextInt();
    }

    public static String getString() {

        return STRINGS[random.nextInt(STRINGS.length)];
    }

}