2014-01-20 17 views
0

我有一個函數來計算塊所花費的時間:Paradoxal定時功能

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),我得到(用於lisibility加空格)

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

它意味着innerpos的總執行時間比outerpos的總執行時間少1000。

什麼!兩者之間有1000倍?而且它說外部呼叫比所有內部功能多花費1000倍的時間?我是否錯過了某些東西或者是否有某處存在泄漏鬼魂的內存?

更新

當我比較執行的數目爲每個塊(numMap),我發現以下內容:

outerpos -> 362878 
innerpos -> 21764 

這是paradoxal。即使intersectPos在其他地方被調用,不應該調用的次數與outerpos被調用的次數一樣多嗎?

編輯

如果我招行numMap(key) = numMap.getOrElse(key, 0f) + 1的時間functinon的頂部,那麼這些數字大致相等。在JVM上的

+0

這些納米結果? –

+1

你不能以這種方式進行計時,並從中學習任何東西。這是JVM上微觀基準標記的經典錯誤。你正在測量類加載時間和JIT編譯(可能取決於很多事情)。在Stack Overflow和更大的Web上都有無數的JVM微基準化處理。在這裏再次重述它是沒有意義的。 –

+0

@RandallSchulz關於microbenchmarking的好處 –

回答

1

nanoTime被認爲是安全的,但不是很準確。這裏有一些很好寫着:

Is System.nanoTime() completely useless?

System.currentTimeMillis vs System.nanoTime

基本上你的測試將計時器的偏差的影響。解決這個問題的一種方法是在相當長的時間內調用time("outerpos")(注意JIT編譯器優化可能會在某個時刻啓動)並且只測量一次開始和結束時間。取平均值並用time("innerpos")重複。這就是我能想到的。仍然不是有史以來最好的測試;)