0
考慮以下應用程序,旨在衡量goroutine
創建延遲。假設我們正在運行GOMAXPROCS=2
。爲什麼會導致goroutine創建時間的差異?
package main
import "fmt"
import "time"
const numRuns = 10000
type timeRecord struct{
Ts time.Time
Msg string
}
var timeStamps []timeRecord
func threadMain(done chan bool) {
timeStamps = append(timeStamps, timeRecord{time.Now(), "Inside thread"})
done <- true
}
func main() {
timeStamps = make([]timeRecord, 0, numRuns*2)
done := make(chan bool)
dummy := 0
for i := 0; i < numRuns; i++ {
timeStamps = append(timeStamps, timeRecord{time.Now(), "Before creation"})
go threadMain(done)
<-done
}
// Regularize
regularizedTime := make([]time.Duration, numRuns*2)
for i := 0; i < len(timeStamps) ; i++ {
regularizedTime[i] = timeStamps[i].Ts.Sub(timeStamps[0].Ts)
}
// Fake timetraced
fmt.Printf("%6d ns (+%6d ns): %s\n", 0, 0, timeStamps[0].Msg)
for i := 1; i < len(timeStamps) ; i++ {
fmt.Printf("%8d ns (+%6d ns): %s\n", regularizedTime[i], (regularizedTime[i] - regularizedTime[i-1]).Nanoseconds(), timeStamps[i].Msg)
}
}
我的服務器上,這大致一致的中位數260 ns的增量輸出從Before creation
到Inside thread
。現在考慮主要方法的以下變化。
timeStamps = make([]timeRecord, 0, numRuns*2)
done := make(chan bool)
dummy := 0
for i := 0; i < numRuns; i++ {
timeStamps = append(timeStamps, timeRecord{time.Now(), "Before creation"})
go threadMain(done)
for j := 0; j < 1000; j++ {
dummy += j
}
<-done
}
在這種變化中,在同一時間增量需要大約890 納秒。
顯然,確切的數字是機器的具體數字,但數字之間的差異是好奇的。從邏輯上講,如果我在「創建之前」和「內部線程」之間測量,在go
聲明之後添加額外的邏輯似乎不應該增加這個時間,但它確實如此。
有沒有人有一個好主意,爲什麼時間增加沒有發生在預期的位置?
因爲'GOMAXPROCS = 2',我期待第二個goroutine可以真正的並行運行。 – merlin2011
第二個goroutine可以以真正的並行運行,但當前的Go運行時只能在某些安全點進行安排。嘗試在'go threadMain(done)'之後添加'runtime.Gosched()'以強制它在for循環之前進行調度。當然,在這種情況下,go sceduler可能會在運行線程之間進行次優分配。如果你有一個真正的程序執行不好,因爲它試圖填寫一個錯誤報告。 – kostya