Regex 如何在scala控制台中测量语句的时间?
我使用Scala来衡量java正则表达式引擎的性能。下面的regexp大约在3秒钟内执行,但我无法使用System.currentTimeMillis测量它。(最后一个表达式返回0) 您现在知道为什么最后返回的值是0,而不是scala在执行regexp时花费的毫秒数了吗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
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