當我對一個修改其輸入的函數進行基準測試時,我必須複製每個基準循環的測試數據,並在我這樣做時暫停計時器。這可能意味着如果我運行go test -bench MyTest -benchtime 1s
測試可能需要2分鐘而不是1秒。如何基準修改其輸入的函數?
我做錯了什麼,或者我只能忍受嗎?
更多背景:
我正在寫一個程序讀取的syslog日誌。我的日誌記錄範例的一部分是記錄消息的第一行包含可讀文本,並且以下行包含「額外信息」,如堆棧跟蹤。因此,我的日誌閱讀器(除其他外)在第一個換行符上拆分了消息,rsyslog將其跳轉到#012
。
下面是該代碼:
// Splits the main line from extra information
func splitMessageExtra(line *string) string {
var prev rune
for i, char := range *line {
if prev == 0 && char == '#' {
prev = char
continue
}
if prev == '#' && char == '0' {
prev = char
continue
}
if prev == '0' && char == '1' {
prev = char
continue
}
if prev == '1' && char == '2' {
extra := (*line)[i+1:]
*line = (*line)[0 : i-3]
return extra
}
prev = 0
}
return ""
}
它最初使用strings.Split
並返回新的字符串,但CPU性能分析表明,它是太緩慢。
這裏是基準功能:
var testMessage = `Feb 10 15:16:20 foo_stats[-] (warning): [foo_stats.postfix, line 166, thread "processor_mta03"]: Skipped line because there is no context:#012Feb 10 15:16:20 mta03 postfix/qmgr[7419]: ABCDEF123: from=<>, size=24431, nrcpt=1 (queue active)`
func BenchmarkSplitMessageExtra(b *testing.B) {
for i := 0; i < b.N; i++ {
b.StopTimer()
msg := string([]byte(testMessage))
b.StartTimer()
splitMessageExtra(&msg)
}
}
這裏有一個跑步無需暫停定時器:
$ go test -bench SplitMessageExtra -benchtime 1s BenchmarkSplitMessageExtra-8 3000000 434 ns/op PASS ok github.com/Hubro/logreader 1.730s
下面是與上面的確切的基準功能的運行:
$ go test -bench SplitMessageExtra -benchtime 1s BenchmarkSplitMessageExtra-8 5000000 385 ns/op PASS ok github.com/Hubro/logreader 100.563s
注意它需要AGES運行。
你會如何解決它?該函數旨在修改輸入,因此在基準中包含分配內存是錯誤的。應該有一種方法來暫停計時器,而不需要大量的大量開銷。 – Hubro
嘗試使用更復雜和更長的'testMessage'。也許這就是你想要的。 – cshu
這不會有什麼區別,目前該函數每秒運行約1000萬次... – Hubro