Yuv*_*dam 168
是的,一点没错.通过反思查找课程的幅度更大.
引用Java关于反射的文档:
由于反射涉及动态解析的类型,因此无法执行某些Java虚拟机优化.因此,反射操作的性能低于非反射操作,并且应避免在性能敏感应用程序中频繁调用的代码段中.
这是一个简单的测试,我在机器上运行5分钟,运行Sun JRE 6u10:
public class Main {
public static void main(String[] args) throws Exception
{
doRegular();
doReflection();
}
public static void doRegular() throws Exception
{
long start = System.currentTimeMillis();
for (int i=0; i<1000000; i++)
{
A a = new A();
a.doSomeThing();
}
System.out.println(System.currentTimeMillis() - start);
}
public static void doReflection() throws Exception
{
long start = System.currentTimeMillis();
for (int i=0; i<1000000; i++)
{
A a = (A) Class.forName("misc.A").newInstance();
a.doSomeThing();
}
System.out.println(System.currentTimeMillis() - start);
}
}
Run Code Online (Sandbox Code Playgroud)
有了这些结果:
35 // no reflection
465 // using reflection
Run Code Online (Sandbox Code Playgroud)
请记住,查找和实例化是一起完成的,在某些情况下,查找可以重构,但这只是一个基本的例子.
即使您只是实例化,您仍然会受到性能影响:
30 // no reflection
47 // reflection using one lookup, only instantiating
Run Code Online (Sandbox Code Playgroud)
再次,YMMV.
Bil*_*l K 85
是的,它慢了.
但请记住该死的#1规则 - PREMATURE OPTIMIZATION是所有邪恶的根源
(好吧,DRY可能与#1并列)
我发誓,如果有人在工作时向我求助并告诉我这一点,我会对他们未来几个月的代码保持警惕.
在您确定需要它之前,您必须永远不会优化,直到那时,只需编写好的,可读的代码.
哦,我也不是说写愚蠢的代码.只是考虑一下你可以做到的最干净的方式 - 没有复制和粘贴等等(仍然要警惕内部循环和使用最符合你需要的集合 - 忽略这些不是"未经优化的"编程,这是"糟糕"的编程)
当我听到这样的问题时,它吓坏了我,但后来我忘了每个人都必须在他们真正得到它之前先学习所有的规则.你花了一个月的时间调试一些"优化"的东西后你会得到它.
编辑:
这个帖子发生了一件有趣的事情.检查#1答案,这是编译器在优化方面有多强大的一个例子.测试完全无效,因为可以完全排除非反射实例化.
课?在你编写一个干净,整齐编码的解决方案并证明它太慢之前,不要进行优化.
Pet*_*rey 36
您可能会发现J a正在优化A a = new A().如果将对象放入数组中,它们的表现就不会那么好.;)以下打印...
new A(), 141 ns
A.class.newInstance(), 266 ns
new A(), 103 ns
A.class.newInstance(), 261 ns
public class Run {
private static final int RUNS = 3000000;
public static class A {
}
public static void main(String[] args) throws Exception {
doRegular();
doReflection();
doRegular();
doReflection();
}
public static void doRegular() throws Exception {
A[] as = new A[RUNS];
long start = System.nanoTime();
for (int i = 0; i < RUNS; i++) {
as[i] = new A();
}
System.out.printf("new A(), %,d ns%n", (System.nanoTime() - start)/RUNS);
}
public static void doReflection() throws Exception {
A[] as = new A[RUNS];
long start = System.nanoTime();
for (int i = 0; i < RUNS; i++) {
as[i] = A.class.newInstance();
}
System.out.printf("A.class.newInstance(), %,d ns%n", (System.nanoTime() - start)/RUNS);
}
}
Run Code Online (Sandbox Code Playgroud)
这表明我的机器差异大约为150 ns.
kdg*_*ory 26
"重要"完全取决于背景.
如果您使用反射基于某个配置文件创建单个处理程序对象,然后花费其余的时间来运行数据库查询,那么它是无关紧要的.如果你通过紧密循环中的反射创建大量对象,那么是的,它是重要的.
通常,设计灵活性(在需要的地方!)应该驱动您使用反射,而不是性能.但是,要确定性能是否是一个问题,您需要分析而不是从讨论论坛获取任意响应.
mel*_*ngs 10
是的,使用Reflection时会出现性能损失,但优化的可能解决方法是缓存该方法:
Method md = null; // Call while looking up the method at each iteration.
millis = System.currentTimeMillis( );
for (idx = 0; idx < CALL_AMOUNT; idx++) {
md = ri.getClass( ).getMethod("getValue", null);
md.invoke(ri, null);
}
System.out.println("Calling method " + CALL_AMOUNT+ " times reflexively with lookup took " + (System.currentTimeMillis( ) - millis) + " millis");
// Call using a cache of the method.
md = ri.getClass( ).getMethod("getValue", null);
millis = System.currentTimeMillis( );
for (idx = 0; idx < CALL_AMOUNT; idx++) {
md.invoke(ri, null);
}
System.out.println("Calling method " + CALL_AMOUNT + " times reflexively with cache took " + (System.currentTimeMillis( ) - millis) + " millis");
Run Code Online (Sandbox Code Playgroud)
将导致:
[java]用查找反射性地调用方法1000000次,耗时5618毫秒
[java]用缓存反复调用方法1000000次需要270毫安
反射很慢,尽管对象分配并不像反射的其他方面那样没有希望.通过基于反射的实例化实现相同的性能需要您编写代码,以便jit可以告诉实例化哪个类.如果无法确定类的标识,则无法内联分配代码.更糟糕的是,转义分析失败,并且对象无法进行堆栈分配.如果幸运的话,如果此代码变热,JVM的运行时分析可能会受到拯救,并且可以动态地确定哪个类占优势并且可以针对该类进行优化.
请注意,此线程中的微基准测试存在严重缺陷,因此请使用一粒盐.迄今为止最缺陷的是彼得·劳里(Peter Lawrey):它确实进行了热身运动以使方法进行了操作,并且它(有意识地)击败逃逸分析以确保分配实际发生.即使那个问题也存在问题:例如,大量的数组存储可能会导致缓存缓存和存储缓冲区,因此如果分配速度非常快,这将最终成为内存基准测试.(虽然得到了正确的结论,但彼得得到了结论:不同之处是"150ns"而不是"2.5x".我怀疑他是为了生活而做这件事.)
小智 7
有趣的是,设置了跳过安全检查的setAccessible(true),成本降低了20%.
没有setAccessible(true)
new A(), 70 ns
A.class.newInstance(), 214 ns
new A(), 84 ns
A.class.newInstance(), 229 ns
Run Code Online (Sandbox Code Playgroud)
使用setAccessible(true)
new A(), 69 ns
A.class.newInstance(), 159 ns
new A(), 85 ns
A.class.newInstance(), 171 ns
Run Code Online (Sandbox Code Playgroud)