关于Java的等价问题有一些答案,但是scala反射(2.11,TypeTags)真的很慢吗?在http://docs.scala-lang.org/overviews/reflection/overview.html有一篇关于它的长篇叙述性文章,这个问题的答案难以提取。
我看到很多关于避免反射的建议,可能其中一些早于2.11的改进,但如果这种方法运行良好,看起来它可以解决JVM类型擦除的衰弱方面,对于scala代码。 / p>
谢谢!
答案 0 :(得分:7)
让我们衡量一下。
我创建了一个简单的class C
,它有一个方法。这种方法所做的就是睡10ms。
我们来调用这个方法
在反思中
直接
看哪个更快,速度有多快。
我已经创建了三个测试。
测试1。通过反射调用。执行时间包括设置反射所需的所有工作。
创建runtimeMirror
,反映类,为方法创建声明,最后一步 - 执行方法。
测试2。不要考虑这个准备阶段,因为它可以重复使用。 我们只计算通过反射调用方法的时间。
测试3。直接调用方法。
<强>结果:强>
从开始反思:在2561ms完成的工作得到101(每次执行设置为1.5秒)
调用方法反射:在1093ms完成的工作得到101(每次执行设置<1ms)
没有反思:在1087ms完成的工作得到101(每次执行设置<1ms)
<强>结论:强> 设置阶段显着增加执行时间。但是没有必要在每次执行时执行设置(这就像类初始化 - 可以完成一次)。因此,如果您以正确的方式使用反射(具有独立的初始阶段),它将显示相关性能并可用于生产。
源代码:
class C {
def x = {
Thread.sleep(10)
1
}
}
class XYZTest extends FunSpec {
def withTime[T](procName: String, f: => T): T = {
val start = System.currentTimeMillis()
val r = f
val end = System.currentTimeMillis()
print(s"$procName job done in ${end-start}ms")
r
}
describe("SomeTest") {
it("rebuild each time") {
val s = withTime("Reflection from start : ", (0 to 100). map {x =>
val ru = scala.reflect.runtime.universe
val m = ru.runtimeMirror(getClass.getClassLoader)
val im = m.reflect(new C)
val methodX = ru.typeOf[C].declaration(ru.TermName("x")).asMethod
val mm = im.reflectMethod(methodX)
mm().asInstanceOf[Int]
}).sum
println(s" got $s")
}
it("invoke each time") {
val ru = scala.reflect.runtime.universe
val m = ru.runtimeMirror(getClass.getClassLoader)
val im = m.reflect(new C)
val s = withTime("Invoke method reflection: ", (0 to 100). map {x =>
val methodX = ru.typeOf[C].declaration(ru.TermName("x")).asMethod
val mm = im.reflectMethod(methodX)
mm().asInstanceOf[Int]
}).sum
println(s" got $s")
}
it("invoke directly") {
val c = new C()
val s = withTime("No reflection: ", (0 to 100). map {x =>
c.x
}).sum
println(s" got $s")
}
}
}