函數參數與全域變數的效能影響
在Go 程式領域,經常出現這樣的問題:函數參數是否應該優先考慮超越全域變數以獲得最佳效能?
考慮函數checkFiles,它將排除模式的切片作為參數:
func checkFiles(path string, excludedPatterns []string) { // ... }
由於exceptedPatterns 在整個函數執行過程中保持不變,有些人可能會建議將其設為全域變數,以透過消除重複的參數傳遞來優化效能。
但是,這種最佳化是不必要的在 Go 中,由於其有效處理切片參數。切片是包含元資料(長度和容量)並指向底層資料結構的輕量級結構。當切片作為函數參數傳遞時,僅複製元數據,而不複製整個後備數組。這稱為“寫時複製”語義。因此,透過函數參數存取 exceptedPatterns 與將其作為全域變數存取同樣有效。
此外,按值傳遞參數通常會導致編譯器進行最佳化,例如快取。另一方面,全域變數需要更複雜的處理,這可能會阻礙最佳化。
基準測試表明,將切片作為函數參數傳遞和訪問全局切片之間沒有顯著的性能差異:
package main import ( "testing" ) var gslice = make([]string, 1000) func global(s string) { for i := 0; i < 100; i++ { _ = s _ = gslice // Access global-slice } } func param(s string, ss []string) { for i := 0; i < 100; i++ { _ = s _ = ss // Access parameter-slice } } func BenchmarkParameter(b *testing.B) { for i := 0; i < b.N; i++ { param("hi", gslice) } } func BenchmarkGlobal(b *testing.B) { for i := 0; i < b.N; i++ { global("hi") } } func main() { testing.Main(m.Run, m.init, m.cleanup, m.installFlags) }
基準測試結果表明兩種方法的執行速度幾乎相同:
BenchmarkParameter-8 20000000 80.2 ns/op BenchmarkGlobal-8 20000000 79.9 ns/op
總而言之,對於以下用例問題,建議將exceptedPatterns 作為函數參數傳遞,因為它可以簡化程式碼,增強可讀性,並提供與Go 中的全域變數相當的效能。
以上是Go 效能:函數參數與全域變數:是否存在真正的速度差異?的詳細內容。更多資訊請關注PHP中文網其他相關文章!