Scala 类型标签和性能 [英] Scala TypeTags and performance

查看:71
本文介绍了Scala 类型标签和性能的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

There are some answers around for equivalent questions about Java, but is scala reflection (2.11, TypeTags) really slow? there's a long narrative write-up about it at http://docs.scala-lang.org/overviews/reflection/overview.html, where the answer to this question is hard to extract.

我看到很多关于避免反射的建议,其中一些可能早于 2.11 的改进,但如果它运行良好,它看起来可以解决 JVM 类型擦除的不利方面,对于 Scala 代码.

I see a lot of advice floating around about avoiding reflection, maybe some of it predating the improvements of 2.11, but if this works well it looks like it can solve the debilitating aspect of the JVM's type erasure, for scala code.

谢谢!

推荐答案

让我们来衡量一下.我创建了一个简单的 class C,它有一个方法.这种方法所做的只是休眠 10 毫秒.让我们调用这个方法

Let's measure it. I've created simple class C that has one method. All what this method do is sleep for 10ms. Let's invoke this method

  • 在反思中

  • within reflection

直接

看看哪个更快,有多快.

And see which is faster and how fast it is.

我创建了三个测试.

测试 1. 通过反射调用.执行时间包括设置反射所需完成的所有工作.创建runtimeMirror,反射类,创建方法声明,最后一步——执行方法.

Test 1. Invoke via reflection. Execution time include all work that necessary to be done for setup reflection. Create runtimeMirror, reflect class, create declaration for method, and at last step - execute method.

测试 2.不要考虑这个准备阶段,因为它可以重复使用.我们只是通过反射来计算方法调用的时间.

Test 2. Do not take into account this preparation stage, as it can be re-used. We are calculate time of method invoking via reflection only.

测试 3. 直接调用方法.

结果:

从开始的反思:在 2561 毫秒内完成的工作得到了 101(每次执行设置需要 1.5 秒)

Reflection from start : job done in 2561ms got 101 (1,5seconds for setup each execution)

调用方法反射:在 1093 毫秒内完成的工作得到了 101 个(每次执行设置 <1 毫秒)

Invoke method reflection: job done in 1093ms got 101 ( < 1ms for setup each execution)

无反射:在 1087 毫秒内完成的工作得到了 101(每次执行设置 <1 毫秒)

No reflection: job done in 1087ms got 101 ( < 1ms for setup each execution)

结论:设置阶段会显着增加执行时间.但是不需要在每次执行时执行设置(这就像类初始化 - 可以完成一次).因此,如果您以正确的方式使用反射(使用单独的 init 阶段),它会显示相关性能并可用于生产.

Conclusion: Setup phase increase execution time dramatically. But there are no need to perform setup on each execution (this is like class initialization - can be done once). So if you use reflection in right way(with separated init stage) it shows relevant performance and can be used for production.

源代码:

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

这篇关于Scala 类型标签和性能的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆