MBZ
MBZ

Reputation: 27592

Performance of Set and Get using Reflection

Does setting and getting an object attribute using reflection (java.lang.reflect.Field get and set functions) rather than calling the set and get of the object itself, result in any significant performance differences?

Upvotes: 10

Views: 6237

Answers (3)

noFearOfBeer
noFearOfBeer

Reputation: 87

I ran a slightly modified version:

public class Test {

    private static class Data {

        public double _value;

        public void setValue(double value) {
            _value = value;
        }
    }

    public static final int LOOP_COUNT = 100_000_000;

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

        Data d = new Data();

        Random testing = new Random(5);
        long start = System.currentTimeMillis();
        for (int i = 0; i < LOOP_COUNT; ++i) {
            d.setValue(testing.nextDouble());
        }
        System.err.println(System.currentTimeMillis() - start);

        Field field = Data.class.getDeclaredField("_value");

        testing = new Random(5);
        start = System.currentTimeMillis();
        for (int i = 0; i < LOOP_COUNT; ++i) {
            field.setDouble(d, testing.nextDouble());
        }
        System.err.println(System.currentTimeMillis() - start);

        testing = new Random(5);
        field.setAccessible(true); // Optimization
        start = System.currentTimeMillis();
        for (int i = 0; i < LOOP_COUNT; ++i) {
            field.setDouble(d, testing.nextDouble());
        }
        System.err.println(System.currentTimeMillis() - start);
    }
}

Result (on Java 1.8.0_121 and my PC):

2714
2741
2625

Seems like reflection is actually faster. Did not expect this...

Upvotes: 1

Aubin
Aubin

Reputation: 14853

Yes, the benchmark is easy to write in 15 minutes.

Generated code is better, even if you cache the reflective accessors, I have tried it.

Here it is under Java 7 64 bits:

import java.lang.reflect.Field;

class Data {
   public double _value;
   public double getValue()               { return _value; }
   public void   setValue( double value ) { _value = value; }
}

public class Reflect {
   public static final int LOOP_COUNT = 100_000_000;
   public static void main( String[] args ) throws Throwable {
      Data d = new Data();
      long start = System.currentTimeMillis();
      for( int i = 0; i < LOOP_COUNT; ++i ) {
         d.setValue( i );
      }
      System.err.println( System.currentTimeMillis() - start );
      Field field = Data.class.getDeclaredField( "_value" );
      start = System.currentTimeMillis();
      for( int i = 0; i < LOOP_COUNT; ++i ) {
         field.set( d, new Double( i ));
      }
      System.err.println( System.currentTimeMillis() - start );

      field.setAccessible( true ); // Optimization
      start = System.currentTimeMillis();
      for( int i = 0; i < LOOP_COUNT; ++i ) {
         field.set( d, new Double( i ));
      }
      System.err.println( System.currentTimeMillis() - start );
   }
}

Result:

20
37381
1677

Ratio is near 1870 w/o accessible flag set. Setting it makes ratio drop to 83.

Upvotes: 7

Stephen C
Stephen C

Reputation: 718778

Yes it does make a significant performance difference, and there are lots on benchmarking results on the web to support this.

For example: http://www.cowtowncoder.com/blog/archives/2007/02/entry_32.html - which seems to be saying that a reflective call to a get or set method is ~50 times slower than accessing / updating the field directly. (And getting / setting using Field methods is slower still.)

Now these results are rather old, and (apparently) the performance of reflection has been improved in recent HotSpot JVMs. Even so, a rough rule of thumb is "an order of magnitude or more slower".

Upvotes: 0

Related Questions