函数参数与全局变量的性能影响
在 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中文网其他相关文章!