Scala的REPL是交互式测试某些代码片段的绝佳场所。最近,我一直在使用REPL进行一些性能比较,以重复执行操作并相对地测量挂钟时间。
以下是我最近创建的一个例子,以帮助回答SO问题[1] [2]:
// Figure out the perfomance difference between direct method invocation and reflection-based method.invoke
def invoke1[T,U](obj:Any, method:Method)(param:T):U = method.invoke(obj,Seq(param.asInstanceOf[java.lang.Object]):_*) match {
case x: java.lang.Object if x==null => null.asInstanceOf[U]
case x => x.asInstanceOf[U]
}
def time[T](b: => T):(T, Long) = {
val t0 = System.nanoTime()
val res = b
val t = System.nanoTime() - t0
(res,t )
}
class Test {
def op(l:Long): Long = (2 until math.sqrt(l).toInt).filter(x=>l%x==0).sum
}
val t0 = new Test
val method = classOf[Test].getMethods.find(_.getName=="op").get
def timeDiff = {
val (timeDirectCall,res) = time { (0 to 1000000).map(x=>t0.op(x)) }
val (timeInvoke, res2) = time { (0 to 1000000).map(x=>{val res:Long=invoke1(t0,method)(x);res}) }
(timeInvoke-timeDirectCall).toDouble/timeDirectCall.toDouble
}
//scala> timeDiff
//res60: Double = 2.1428745665357445
//scala> timeDiff
//res61: Double = 2.1604176409796683
在另一个案例中,我一直在生成随机数据点的MM来比较开源项目的并发模型。 REPL非常适合在没有代码编译测试周期的情况下使用不同的配置。
我知道常见的基准测试陷阱,例如JIT优化和热身需求。
我的问题是:
使用时是否需要考虑REPL特定元素 它执行宏观基准比较微观?
这些测量相对于彼此使用时是否可靠?也就是说他们可以回答这个问题:A
比B
更快吗?
相同代码的预删除执行是jit的良好预热 编译器?
还有其他问题需要注意吗?
[1] Scala reflection: How to pass an object's method as parameter to another method
答案 0 :(得分:6)
这是一个很好的问题。我无法想象为什么有人贬低它。
其中一条评论完全错误的事实表明REPL需要在scala-lang.org的常见问题或教程中占有一席之地。快速搜索后,我找不到描述性文件。
答案是肯定的,REPL符合您的期望。
Here is an old page关于为什么这个问题很有趣:REPL感觉很动态,但实际上是静态编译的。它“横跨两个世界”,因为链接页面的临时评论表明了这一点。
REPL将每一行编译成自己的包装对象。每个这样的对象都从交互式会话的历史中导入符号,这是代码神奇地引用回前一行的方式。所有东西都被编译,因此当它运行时,它可以在JVM上本地运行,可以这么说;没有额外的解释层。这是REPL的杀手级设计功能。
这就是为什么你的问题的答案是肯定的,你的代码以编译代码的速度运行。调用方法不需要重新编译所有历史记录。
Here's another old link显示其他人对时间和微基准测试有同样的疑问。
目前有an open issue可以自定义REPL如何包装代码行。微博标记是一个有趣的用例,其中代码可以包含在任意框架中以进行基准测试。那将很快到来。
基准框架应该注意热身。由于提交给REPL的每个表达式都是单独编译的(虽然是由相同的编译器),你会注意到第一次可以调用一个方法,而第二次调用一个方法(通过scalac模数内联)。
警告:
使用-Yrepl-class-based
或小心不要将计算放在包装对象的静态初始值设定项中。
Here is some sample confusion和here is the same question,隐藏得更少。