Mar*_*los 7 java reflection performance benchmarking
我知道有很多主题都在讨论反射性能.
甚至官方Java文档都说反射速度较慢,但我有这个代码:
public class ReflectionTest {
public static void main(String[] args) throws Exception {
Object object = new Object();
Class<Object> c = Object.class;
int loops = 100000;
long start = System.currentTimeMillis();
Object s;
for (int i = 0; i < loops; i++) {
s = object.toString();
System.out.println(s);
}
long regularCalls = System.currentTimeMillis() - start;
java.lang.reflect.Method method = c.getMethod("toString");
start = System.currentTimeMillis();
for (int i = 0; i < loops; i++) {
s = method.invoke(object);
System.out.println(s);
}
long reflectiveCalls = System.currentTimeMillis() - start;
start = System.currentTimeMillis();
for (int i = 0; i < loops; i++) {
method = c.getMethod("toString");
s = method.invoke(object);
System.out.println(s);
}
long reflectiveLookup = System.currentTimeMillis() - start;
System.out.println(loops + " regular method calls:" + regularCalls
+ " milliseconds.");
System.out.println(loops + " reflective method calls without lookup:"
+ reflectiveCalls+ " milliseconds.");
System.out.println(loops + " reflective method calls with lookup:"
+ reflectiveLookup + " milliseconds.");
}
Run Code Online (Sandbox Code Playgroud)
}
我认为这不是一个有效的基准,但至少应该显示出一些差异.我执行它等待看到反射正常调用比常规调用慢一点.
但这印刷了这个:
100000 regular method calls:1129 milliseconds.
100000 reflective method calls without lookup:910 milliseconds.
100000 reflective method calls with lookup:994 milliseconds.
Run Code Online (Sandbox Code Playgroud)
只是为了注意,首先我在没有那些sysout的情况下执行它,然后我意识到一些JVM优化只是让它变得更快,所以我添加了这些printls以查看反射是否仍然更快.
没有sysout的结果是:
100000 regular method calls:68 milliseconds.
100000 reflective method calls without lookup:48 milliseconds.
100000 reflective method calls with lookup:168 milliseconds.
Run Code Online (Sandbox Code Playgroud)
我在互联网上看到,在旧的JVM上执行的相同测试使得没有查找的反射比常规调用慢两倍,并且速度超过了新的更新.如果有人可以执行它并说我错了,或者至少告诉我是否有不同于过去的东西使它更快.
按照说明,我运行每个循环分离,结果是(没有sysouts)
100000 regular method calls:70 milliseconds.
100000 reflective method calls without lookup:120 milliseconds.
100000 reflective method calls with lookup:129 milliseconds.
Run Code Online (Sandbox Code Playgroud)
Dun*_*nes 12
永远不要在相同的"运行"中对不同的代码进行性能测试.JVM具有各种优化,这意味着尽管最终结果是相同的,但内部执行方式可能会有所不同.更具体地说,在测试期间,JVM可能已经注意到您正在调用Object.toString并且已经开始内联对Object.toString的方法调用.它可能已经开始执行循环展开.或者在第一个循环中可能存在垃圾收集,但第二个或第三个循环中没有垃圾收集.
要获得更有意义但仍然不完全准确的图片,您应该将测试分成三个单独的程序.
我的电脑上的结果(没有打印,每次打印1,000,000次)
所有三个循环都在同一程序中运行
1000000个常规方法调用:490毫秒.
没有查找的1000000反射方法调用:393毫秒.
循环的1000000反射方法调用:978毫秒.
循环在单独的程序中运行
1000000个常规方法调用:475毫秒.
没有查找的1000000反射方法调用:555毫秒.
循环的1000000反射方法调用:1160毫秒.
Brian Goetz撰写了一篇关于microbenchmarks的文章值得一读.在进行测量之前,看起来你没有采取任何措施来加热JVM(意味着让它有机会进行任何内联或其他优化),因此非反射测试可能仍然没有变暖 - 然而,这可能会扭曲你的数字.
归档时间: |
|
查看次数: |
5366 次 |
最近记录: |