Go 一行代碼測量函數的執行時間

Golang Tips 是翻譯的 Phuong Le @func25[1] 陸陸續續的發表的推文,目前已經發表 70 + 了。我徵得 Phuong Le 的同意後,會逐步把這些推翻翻譯過來,發佈到公衆號上。

因爲是推文,可能原作者的內容比較簡單,比如第一個 tip 就一張圖片,我會相應的進行擴充,豐富其內容。 後續也會在 github 建立一個項目,大家都可以參與進行翻譯。

我們可以通過 defer,實現一行代碼來測量某個函數的執行時間:

func main() {
 defer TrackTime(time.Now()) // 一行代碼

 time.Sleep(time.Second)
}

func TrackTime(start time.Time) time.Duration {
 elapsed := time.Since(start)
 fmt.Println("elapsed:", elapsed)

 return elapsed
}

// elapsed: 1.000704416s

這個 defer 的函數 TraceTime 放在函數內需要測量的起始點,它的參數 (start) 在此時就會計算出來,在函數返回的時候,它的函數體就會被調用,這是 end 時間也知道了,這樣就可以巧妙的計算出來函數執行的時間了。

以下是補充材料


我們還可以使用下面的寫法,但是更好更通用些:

func TrackTime(name string) func() {
 start := time.Now()

 return func() {
  fmt.Printf("%s took %v\n", name, time.Since(start))
 }
}



func main() {
 defer TrackTime("main")() // 也是一行代碼
 time.Sleep(time.Second * 2)
}

這個 deferTraceTime 傳入一個輔助信息字符串,方便打日誌的能和其它的測量函數所區分。TraceTime 返回一個類型爲 func() 函數匿名函數,這纔是 defer 真正調用的函數,它會打印出要測量的函數真正花費的時間。

相比較上面的測量方法,這個函數可以傳入輔助字符串,並且不需要自己再調用 time.Now() 獲得開始時間。


另外,我還想補充一個測試性能的時候的輔助庫:hrtime[2])。 一般我們會寫 Benchmark 的測試代碼來測試一段代碼邏輯 (一般是一個函數,但是也可以是多個函數和語句組成的一段代碼邏輯) 的性能,但是有的時候,我們可能想寫一個程序,更靈活的進行測試,甚至希望得到時間花費的分佈情況, hrtime 就是幹這個的,就像它的簡介中所說,它是 Go 語言中的高精度計時與基準測試庫。

首先我們看一下它的使用方法:

package main

import (
    "fmt"
    "time"

    "github.com/loov/hrtime"
)

func main() {
    start := hrtime.Now()
    time.Sleep(1000 * time.Nanosecond)
    fmt.Println(hrtime.Since(start))

    const numberOfExperiments = 4096

    bench := hrtime.NewBenchmark(numberOfExperiments)
    for bench.Next() {
        time.Sleep(1000 * time.Nanosecond)
    }
    fmt.Println(bench.Histogram(10))
}

單純的測量一段代碼的執行時間,和常規的我們使用 time package 方法一樣,你也可以採用前面介紹的方法,實現一行代碼的封裝。

同時,類似標準庫的 Benchmark 的測量性能的方法,你也可以利用 bench := hrtime.NewBenchmark(numberOfExperiments) 生成一個 bench,進行性能測試,最後通過 bench.Histogram(10) 生成直方圖。比如這個例子,我們測試 Sleep 1 微秒時,實際程序會休眠多少微秒。

在我的 Mac mini 的機器上測試,可以看到真正休眠在 5 微秒左右,絕大部分時間落在了 15 微秒以內。

參考資料

[1]

@func25: https://twitter.com/func25

[2]

hrtime: https://github.com/loov/hrtime

本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://mp.weixin.qq.com/s/LJoIHHDB5SflvtOhGZCtLw