Reputation: 27592
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
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
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
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