Regex 如何在scala控制台中测量语句的时间?

Regex 如何在scala控制台中测量语句的时间?,regex,scala,Regex,Scala,我使用Scala来衡量java正则表达式引擎的性能。下面的regexp大约在3秒钟内执行,但我无法使用System.currentTimeMillis测量它。(最后一个表达式返回0) 您现在知道为什么最后返回的值是0,而不是scala在执行regexp时花费的毫秒数了吗 def time[A](f: => A) = { val s = System.nanoTime val ret = f println("time: "+(System.nanoTime-s)/1e6+"ms

我使用Scala来衡量java正则表达式引擎的性能。下面的regexp大约在3秒钟内执行,但我无法使用System.currentTimeMillis测量它。(最后一个表达式返回0)

您现在知道为什么最后返回的值是0,而不是scala在执行regexp时花费的毫秒数了吗

def time[A](f: => A) = {
  val s = System.nanoTime
  val ret = f
  println("time: "+(System.nanoTime-s)/1e6+"ms")
  ret
}
将其用于:

scala> time { 10*2 }
time: 0.054212ms
res1: Int = 20

这很有趣!我在创建正则表达式并运行代码的行周围添加了一个
println(“start”)
“end”
,这将打印

start 
end
然后暂停大约3秒钟,然后再打印输出的其余部分

因此,看起来发生的情况是正在创建正则表达式,但在调用
toString
以将其输出到控制台之前,它不会运行。要使测试正常工作,请在计算所用时间之前添加手动
toString
调用

scala> val b = System.currentTimeMillis; val v = new scala.util.matching.Regex("(x+)+y").findAllIn("x"*25); v.toString; System.currentTimeMillis-b
b: Long = 1330789547209
v: scala.util.matching.Regex.MatchIterator = empty iterator
res14: Long = 4881

另外,它应该是
System.currentTimeMillis-b
,而不是反过来…

无法解释的持续时间来自从
findAllIn
返回的迭代器上的REPL调用
toString
。这会依次调用,从而触发搜索

scala> def time[A](a: => A) = {
     |   val now = System.nanoTime
     |   val result = a
     |   val micros = (System.nanoTime - now) / 1000
     |   println("%d microseconds".format(micros))
     |   result
     | }
time: [A](a: => A)A

scala> :power
** Power User mode enabled - BEEP WHIR GYVE **
** :phase has been set to 'typer'.          **
** scala.tools.nsc._ has been imported      **
** global._, definitions._ also imported    **
** Try  :help, :vals, power.<tab>           **

scala> :wrap time
Set wrapper to 'time'

scala> new Regex("(x+)+y").findAllIn("x"*25).toString
3000737 microseconds
res19: String = empty iterator

scala> {new Regex("(x+)+y").findAllIn("x"*25); 0}
582 microseconds
res20: Int = 0
scala>def时间[A](A:=>A)={
|val now=System.nanoTime
|val结果=a
|val micros=(System.nanoTime-now)/1000
|println(“%d微秒”。格式(微秒))
|结果
| }
时间:[A](A:=>A)A
scala>:电源
**电源用户模式已启用-哔哔声**
**:相位已设置为“typer”**
**scala.tools.nsc.\已导入**
**全局。\定义。\也已导入**
**尝试:帮助、:VAL、电源**
scala>:换行时间
将包装器设置为“时间”
scala>newregex(“(x+)+y”).findAllIn(“x”*25).toString
3000737微秒
res19:String=空迭代器
scala>{new Regex(“(x+)+y”).findAllIn(“x”*25);0}
582微秒
res20:Int=0

> > p>这不是你问题的直接答案,但是你可能想考虑使用一个成熟的标杆库,比如


一般来说,在基准测试方面,特别是在JVM上,存在许多缺陷(这是一个很好的讨论)。如果您使用自己的解决方案,就可以避免这些问题。

稍微改进可能包括多次运行。然而,如果您关心的不仅仅是相对速度差异,那么一个合适的基准库就非常重要

def time[A](a: => A, n:Int) = {
    var times = List[Long]()
        for (_ <- 1 to n) {
        val now = System.nanoTime
        val res = a
        times :::= List(System.nanoTime - now)
    }
    val result = times.sum / n
    println("%d microseconds".format(result / 1000))
    result
}
def time[A](A:=>A,n:Int)={
变量时间=列表[长]()

对于(u也可以考虑这种方法返回所应用方法的实际输出以及经过的时间,都是在元组(Scala 2.10+)中

对于任何给定函数
def(n:Int)=(1到n)产品

scala> val (res, time) = f(3).elapsed
res: Int = 6
time: Double = 46.4378

虽然这是一种更简洁的测试时间的方法,但它并没有回答这个特定的问题,因为问题实际上是由被评估的代码没有实际执行OP试图测量的操作引起的。
的+1:wrap
示例,尽管我不确定简单的减法是对小p进行基准测试的最佳方法JVM中的几段代码你是对的,Google的Caliper是一个更全面的工具,它被很好地包装在一个基于SBT的基准测试工具中:是
:wrap
不再出现在REPL中吗?在Scala 2.10.2 for Windows中,我得到
wrap:没有这样的命令。键入:帮助。
是的,
:wrap
被删除:值得一提检查代码行是否包装在对象中;REPL在初始化该对象后访问member.toString(以显示结果)。模板机制很可能选择了不同的求值顺序;或者自定义机制可以这样做。对真正的基准测试有意义我只是想检查算法的复杂度:2n或nk。对于这一点,上面的代码应该足够了
implicit class RichElapsed[A](f: => A) {

  def elapsed(): (A, Double) = {
    val start = System.nanoTime()
    val res = f
    val end = System.nanoTime()

    (res, (end-start)/1e3)
  }

}
scala> val (res, time) = f(3).elapsed
res: Int = 6
time: Double = 46.4378