Reputation: 19002
What is the performance difference of calling a method using reflection vs. calling the method directly?
Context details: I have a class, with some string properties and for certain properties I have to set the values to Lower case or to Upper case (and a bit of logic related to that).
I have two options:
Of course with option 2. my code would much more readable and easy to maintain, but the question is about performance. I will have some millions (around 2-3) of instances and I would go with the reflection option, if the performance impact is not bigger than 20 seconds.
Does anyone here have any experience with that?
Upvotes: 3
Views: 6634
Reputation: 5233
It's difficult to give a set figure because it will depend on many aspects of your system, so I wrote a class to check this.
The results surprised me, it seems for my system that for simply calling a method via reflection vs statically calling the method, static calling is between 10,000 for a non empty method and 1000,000 times faster for an empty method.
I used both just in case the java compiler/vm was optimising away an empty method call.
The code is below, also available in this gist - https://gist.github.com/piersy/23b4814eec806b584266
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class TestReflection {
public static long INC = 0;
public static final int COUNT = 100000000;
private static class Dummy {
public void doSomething(String s1, String s2, String s3) {
INC++;
}
}
public static void main(String[] args) throws NoSuchMethodException {
Dummy obj = new Dummy();
Method method = obj.getClass().getMethod("doSomething", String.class, String.class, String.class);
String s1 = "string1";
String s2 = "string2";
String s3 = "string3";
//warmup
runReflection(obj, method, s1, s2, s3, COUNT / 10);
runStatic(obj, s1, s2, s3, COUNT/10);
///realtest
long reftime = System.nanoTime();
runReflection(obj, method, s1, s2, s3, COUNT);
reftime = System.nanoTime() - reftime;
long time = System.nanoTime();
runStatic(obj, s1, s2, s3, COUNT);
time = System.nanoTime() - time;
System.out.println(reftime);
System.out.println(time);
//1000 *1000 *1000 nanoseconds in a second
System.out.println(reftime / (1000 *1000 *1000));
System.out.println(time / (1000 *1000 *1000));
System.out.println((double)reftime/ (double)time );
System.out.println("percentage speed decrease from using reflection:"+(((double)reftime/(double)time)-1)*100);
}
private static void runReflection(Dummy obj, Method method, String s1, String s2, String s3, int count) {
for (int i = 0; i < count; i++) {
try {
method.invoke(obj, s1, s2, s3);
} catch (IllegalArgumentException e) {
} catch (IllegalAccessException e) {
} catch (InvocationTargetException e) {
}
}
}
private static void runStatic(Dummy obj, String s1, String s2, String s3, int count) {
for (int i = 0; i < count; i++) {
obj.doSomething(s1,s2,s3);
}
}
}
Upvotes: 3
Reputation: 2520
Lets start with some drawbacks of Reflection from the Oracle Docs
Drawbacks of Reflection
Reflection is powerful, but should not be used indiscriminately. If it is possible to perform an operation without using reflection, then it is preferable to avoid using it. The following concerns should be kept in mind when accessing code via reflection.
Performance Overhead Because reflection involves types that are dynamically resolved, certain Java virtual machine optimizations can not be performed. Consequently, reflective operations have slower performance than their non-reflective counterparts, and should be avoided in sections of code which are called frequently in performance-sensitive applications.
Security Restrictions Reflection requires a runtime permission which may not be present when running under a security manager. This is in an important consideration for code which has to run in a restricted security context, such as in an Applet.
Exposure of Internals Since reflection allows code to perform operations that would be illegal in non-reflective code, such as accessing private fields and methods, the use of reflection can result in unexpected side-effects, which may render code dysfunctional and may destroy portability. Reflective code breaks abstractions and therefore may change behavior with upgrades of the platform.
So you can take it for sure that performance would be an issue once you start scaling up. But if you can live with the performance overhead which an intuition says should not be more than 20 seconds for Uppercase/LowerCase operations and being hugely scalable is not a concern you can use it. But beware that intuitions on performance are usually always wrong. So you would want to test for sure.
Do look up Aspect Oriented Programming for the task you want.
My opinion: Use a AOP framework.
Upvotes: 0
Reputation: 43817
In general, yes, reflection is slower. If by millions of instances you mean millions of calls then yes, in some cases you could incur more than a 20 second overhead. In some causes you may not incur the additional overhead as the compiler will be able to optimize it out. You will either have to give a lot more details about how exactly you plan on using reflection or run it yourself. My GUT says that across 3 million calls you will NOT incur more than 20 seconds overhead however that is very much a gut feeling.
Upvotes: 1