Scala TypeTags和性能

时间:2015-12-11 07:19:07

标签: scala

关于Java的等价问题有一些答案,但是scala反射(2.11,TypeTags)真的很慢吗?在http://docs.scala-lang.org/overviews/reflection/overview.html有一篇关于它的长篇叙述性文章,这个问题的答案难以提取。

我看到很多关于避免反射的建议,可能其中一些早于2.11的改进,但如果这种方法运行良好,看起来它可以解决JVM类型擦除的衰弱方面,对​​于scala代码。 / p>

谢谢!

1 个答案:

答案 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")
        }
      }
    }