本书未发布
Go 性能优化细节
函数调用
C 函数调用,参数6个之内用的是寄存器,大于6个则会用栈存储多余的参数。返回只能有一个,因为返回值也是用的一个寄存器。
Go 函数调用,参数都放在栈存储。返回值也支持多个。interface{} 和 interface 区别
- interface{} 和C语言的
*void
不同,不能代表任意类型。举个例子: - interface{} 不带方法(空接口);interface带方法。
- 类型断言:运行时类型判断,快速通过结构体内的hash。
- 动态派发(类型转换):在运行期间选择具体多态操作(方法或者函数)执行的过程,它是面向对象语言中的常见特性。调用接口类型的方法时,如果编译期间不能确认接口的类型,Go 语言会在运行期间决定具体调用该方法的哪个实现。
- 结构体调用:
- 指针式调用:比结构体调用性能更优。原因是动态派发在结构体上的表现非常差。
直接调用 | 动态派发 |
---|---|
指针 | ~3.03ns |
结构体 | ~3.09ns |
type TestStruct struct{}
func NilOrNot(v interface{}) bool {
return v == nil
}
func main() {
var s *TestStruct
fmt.Println(s == nil) // #=> true
fmt.Println(NilOrNot(s)) // #=> false
}
interface{} 的底层数据结构是 eface.
type eface struct {
_type *_type
data unsafe.Pointer
}
type _type struct {
size uintptr
ptrdata uintptr
hash uint32
tflag tflag
align uint8
fieldAlign uint8
kind uint8
equal func(unsafe.Pointer, unsafe.Pointer) bool
gcdata *byte
str nameOff
ptrToThis typeOff
}
interface的底层数据结构 iface
type iface struct { // 16 字节
tab *itab
data unsafe.Pointer
}
type itab struct { // 32 字节
inter *interfacetype
_type *_type
hash uint32
_ [4]byte
fun [1]uintptr
}
defer 性能优化
堆上分配 < 栈上分配 < 开放编码
With normal (stack-allocated) defers only: 35.4 ns/op
With open-coded defers: 5.6 ns/op
Cost of function call alone (remove defer keyword): 4.4 ns/op
- 函数的
defer
数量少于或者等于 8 个; - 函数的
defer
关键字不能在循环中执行; - 函数的
return
语句与defer
语句的乘积小于或者等于 15 个;