25. 04. 2018
Android reflection in general has been considered to be painfully slow. But it is actually not that bad at all! We needed to evaluate performance of Field.set() and Field.get() for your open source project joogar ORM and we were really surprised by the results.
Without reflection are both read and write of object attribute one of the fastest operations in Java. It’s just about copying 4 bytes (8 for 64 bit VM) in memory. It’s hard to imagine that reflection performance could be competitive in this case. You are right, it is not, but let’s compare Field.set() and Field.get() with other common native operations.
Methodology
We created simple Android app with small benchmarks for this 7 operations:
- Assign object’s atribute value (
object.attribute = value;
) - Assign object’s atribute value with reflection (
field.set(object, value);
) - Read object’s atribute value with reflection (
field.get(object);
) - Primitive type autoboxing (
integerVariable = intVariable;
) - String concatenation (
stringVariable + intVariable;
) - New object creation (
new MyClass();
) - Logging (
Log.i("MyTag", "Log for performance test.");
)
Measurements
At first we compared simple value assign with Field.set(). Reflection was 18x slower! That’s a really bad result, which makes it almost totally unusable. We gave it one more chance and compared its performance with other operations we used in object-relation mapping code. Check the table bellow where all values are presented relatively as multiple of native property write time.
HTC One m7 | HTC Evo 3D | Nexus 7 2013 | LG G3 | |
---|---|---|---|---|
Android | 4.4.3 | 4.0.3 | 5.0.0 | 5.0.0 |
Native write | 1x | 1x | 1x | 1x |
Reflection write | 20x | 32x | 31x | 71x |
Reflection read | 23x | 34x | 14x | 31x |
Autoboxing | 133x | 140x | 26x | 64x |
Concat | 897x | 1 046x | 119x | 259x |
Object | 158x | 172x | 22x | 64x |
Logging | 602x | 607x | 728x | 1 289x |
As you can see, the performance of reflection Field.set() and Field.get() is very similar. Very slow reflection write on LG G3 is quite surprising – maybe some hardware related issue?
Autoboxing is very slow on Dalvik, but little faster than reflection on ART. As for ART we can state that having autoboxing in your code is very similar to using Field.set() or Field.get(), for Dalvik we can consider Autoboxing to be 4x – 7x slower than reflection attribute write/read. Not bad results for reflection.
String concatenation is a real performance killer! Concatenation is 4-8x faster on ART but still significantly slower than read/write reflection. You should be really careful with it and use StringBuilder when possible.
Creating new Object is very similar to Autoboxing. Not surprisingly, internally it has to be almost identical operation.
Another performance killer is logging. It is 18x – 30x slower than reflection read/write on both ART and Dalvik. Avoid logs in production code!
Conclusion about reflection
Reflection is much more slower than compiled code. There is no discussion about that but compared with other trivial operations it is not that serious. Use reflection with care and measure its impact on your code performance, if you write time-critical part of your app. When compared with other standard Java constructs reflection is not a performance killer, it is just a little bit slower than native code.