以下兩個示例之間是否存在性能差異:
1.
var slice []int{ ... huge list of items... }
for i:=0; i<len(slice); i { .... do something ....}
2.
var slice []int{ ... huge list of items... }
sliceLen := len(slice)
for i:=0; i<sliceLen; i { .... do something ....}
" for " 陳述句中的條件運算式是在每次迭代時計算還是僅計算一次?
uj5u.com熱心網友回復:
TLDR:幾乎沒有區別
測驗問題的好方法是標準庫提供的基準測驗testing
創建測驗檔案,例如: forcycle_test.go
package perftest
import (
"testing"
)
func BenchmarkLenInside(b *testing.B) {
testData := make([]int, 1000000)
for i := 0; i < b.N; i {
// Benchmarked code start
for j := 0; j < len(testData); j {
doSth(testData[j])
}
// end
}
}
func BenchmarkLenOutside(b *testing.B) {
testData := make([]int, 1000000)
for i := 0; i < b.N; i {
// Benchmarked code start
sliceLen := len(testData)
for j := 0; j < sliceLen; j {
doSth(testData[j])
}
// end
}
}
func doSth(n int) {
_ = n n
}
運行基準測驗
go test -bench .
示例輸出
goos: linux
goarch: amd64
pkg: forperf
BenchmarkLenInside-6 4543 259117 ns/op
BenchmarkLenOutside-6 4620 258069 ns/op
PASS
ok forperf 3.811s
基準函式必須運行目標代碼 bN 次。在基準執行期間,會調整 bN,直到基準函式持續足夠長的時間以進行可靠計時。
正如您在此基準測驗中看到的,當您將len函式作為 for 回圈的一部分撰寫時,它只是比回圈之外的版本稍慢。
| 型別 | bN 計時前 | 每 bN 次迭代的平均時間 |
|---|---|---|
| 連進 | 4543 | 259117 納秒 |
| 出借 | 4620 | 258069 納秒 |
請注意,多次運行會為您提供不同的結果 where len inisA和len outisB
A < B或者A ≈ B甚至A > B是可能的。
uj5u.com熱心網友回復:
“for”陳述句中的條件運算式是在每次迭代時計算還是僅計算一次?
該規范指出,該條件是每次迭代之前評估。
由于值i在每次迭代的變化,它是有意義的條件i<len(slice)和i<sliceLen每次迭代之前評估。
編譯器可以將部分條件運算式求值提升到回圈之外,只要結果程式執行時就好像每次都對運算式求值一樣。例如,編譯器可以在回圈之前加載len(slice)或加載sliceLen到暫存器并在回圈中使用該暫存器。
下面的兩個示例之間是否有任何性能差異
兩個代碼片段都將變數i與從變數中讀取的值進行比較。在第一個片段中,該值是從切片標頭長度欄位中讀取的。如果您不熟悉切片的實作方式,請參閱切片:用法和內部結構。
如果不相同,性能應該相似。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qukuanlian/335650.html
