最近在了解反射优化的东西,做了一个 cglib,java 的反射 api 和直接调用的性能比较
public class SampleBean {
public String echo(String name) {
return name;
}
}
测试代码:
FastClass fastClass = FastClass.create(SampleBean.class);
FastMethod fastMethod = fastClass.getMethod(SampleBean.class.getMethod("echo", String.class));
SampleBean myBean = new SampleBean();
long start = System.currentTimeMillis();
for (int i = 0; i < 1000000; i++) {
fastMethod.invoke(myBean, new Object[]{"haha"+i});
//fastMethod.invoke(myBean, new Object[]{"haha"});
}
System.out.println("fastmethod:" + (System.currentTimeMillis() - start));
start = System.currentTimeMillis();
Method m = SampleBean.class.getMethod("echo", String.class);
for (int i = 0; i < 1000000; i++) {
m.invoke(myBean, "haha"+i);
//m.invoke(myBean, "haha");
}
System.out.println("reflect:"+(System.currentTimeMillis() - start));
start = System.currentTimeMillis();
for (int i = 0; i < 1000000; i++) {
myBean.echo("haha"+i);
//myBean.echo("haha");
}
System.out.println("normal:"+(System.currentTimeMillis() - start));
输出: fastmethod:196 reflect:139 normal:72 上面一段代码如果跑被注释掉的那一行时间会更短: fastmethod:38 reflect:33 normal:25 个人猜测,百万次调用参数不变,是不是被优化了?
public class SampleBean {
public String echo(String name, int age) {
//改一下,方法稍微复杂点
List<String> names = new ArrayList<>(100);
for (int i = 0; i < 100; i++) {
names.add(name+i);
}
List<Integer> ages = new ArrayList<>(100);
for (int i = 0; i < 100; i++) {
ages.add(age+i);
}
return name+"--"+age;
}
}
测试代码:
FastClass fastClass = FastClass.create(SampleBean.class);
FastMethod fastMethod = fastClass.getMethod(SampleBean.class.getMethod("echo", String.class, int.class));
SampleBean myBean = new SampleBean();
myBean.setValue("Hello cglib!");
long start = System.currentTimeMillis();
for (int i = 0; i < 1000000; i++) {
fastMethod.invoke(myBean, new Object[]{"haha"+i, 12});
}
System.out.println("fastmethod:" + (System.currentTimeMillis() - start));
start = System.currentTimeMillis();
Method m = SampleBean.class.getMethod("echo", String.class, int.class);
for (int i = 0; i < 1000000; i++) {
m.invoke(myBean, "haha"+i, 12);
}
System.out.println("reflect:" + (System.currentTimeMillis() - start));
start = System.currentTimeMillis();
for (int i = 0; i < 1000000; i++) {
myBean.echo("haha"+i, 12);
}
System.out.println("normal:" + (System.currentTimeMillis() - start));
这段代码输出: fastmethod:5533 reflect:4779 normal:4691 结果是 cglib 不如 java 自己的反射 api 快?!!! 直接调和反射差的也不多,是我的这段测试有问题吗?请教一下关于反射优化的问题,谢谢。
1
sagaxu 2017-04-04 20:18:20 +08:00
你可以单独把"haha"+i 拿出来测一下性能, int 转 String ,再做一个 String 的拼接,是个比较重的操作
|
2
sagaxu 2017-04-04 20:19:46 +08:00
而且你的测试代码都没有经过 JIT 预热,预热之后再测会更准确
|
3
misaka19000 2017-04-04 20:20:01 +08:00 via Android
javap 看一下有什么区别
|
4
twogoods OP @sagaxu 拼字符串的过程大家都有应该关系不大吧,我是单纯好奇 JDK 自己的实现已经比 cglib 都好了
|
5
unique 2017-04-04 23:31:28 +08:00 1
这里有更详细的测试,或许可以帮到你 https://github.com/neoremind/dynamic-proxy
|