矛盾的计时功能

时间:2014-01-20 18:04:26

标签: scala scope timing

我有一个计算块中花费时间的函数:

import collection.mutable.{Map => MMap}
var timeTotalMap = MMap[String, Long]()
var numMap = MMap[String, Float]()
var averageMsMap = MMap[String, Float]()
def time[T](key: String)(block: =>T): T = {
  val start = System.nanoTime()
  val res = block
  val total = System.nanoTime - start
  timeTotalMap(key) = timeTotalMap.getOrElse(key, 0L) + total
  numMap(key) = numMap.getOrElse(key, 0f) + 1
  averageMsMap(key) = timeTotalMap(key)/1000000000f/numMap(key)
  res
}

我正在计算一个函数以及在一个地方调用它的位置。

time("outerpos") { intersectPos(a, b) }

并且函数本身以:

开头
def intersectPos(p1: SPosition, p2: SPosition)(implicit unify: Option[Identifier] =None): SPosition
    = time("innerpos") {(p1, p2) match {
   ...
}

当我显示每个键的纳米时间(timeTotalMap)时,我得到(为隐形添加空格)

outerpos->  37 870 034 714
innerpos->      53 647 956

这意味着innerpos的总执行时间比外包的总执行时间小1000。

什么!两者之间有一个因素1000?它说外部呼叫比所有内部功能多花费1000倍?我错过了什么,或者某个地方是否有泄漏鬼魂?

更新

当我比较每个块的执行次数(numMap)时,我发现以下内容:

outerpos -> 362878
innerpos -> 21764

这是矛盾的。即使在其他地方调用intersectPos,它的调用次数是否应该与外部调用的次数一样大?

修改

如果我将行numMap(key) = numMap.getOrElse(key, 0f) + 1移到时间函数的顶部,则这些数字大致相等。

1 个答案:

答案 0 :(得分:1)

JVM上的

nanoTime被认为是安全的,但不是很准确。以下是一些好的读物:

Is System.nanoTime() completely useless?

System.currentTimeMillis vs System.nanoTime

基本上,您的测试会受到计时器不准确的影响。解决这个问题的一种方法是在相当长的时间内调用time("outerpos")(注意JIT编译器优化可能会在某个时刻启动)并仅测量一次开始和结束时间。取平均值并重复time("innerpos")。这就是我能想到的。仍然不是最好的测试;)