Go反射性能瓶颈如何通过零拷贝技术实现优化?
摘要:原文:https:www.yt-blog.top38912 做Go开发的,肯定少不了用反射——解析Tag、拿字段偏移、获取类型信息,ORM、序列化、配置绑定这些地方都要用到。 但是官方的reflect包性能真的不太行,解析一个字段或
原文:https://www.yt-blog.top/38912/
做Go开发的,肯定少不了用反射——解析Tag、拿字段偏移、获取类型信息,ORM、序列化、配置绑定这些地方都要用到。
但是官方的reflect包性能真的不太行,解析一个字段或Tag要花几十到几百万纳秒,调得多了,直接成性能瓶颈。
很多人只知道「反射慢」,但不知道慢在哪。咱们今天就从runtime层面分析一下,顺便搞个零拷贝的优化方案。
一、先从底层说起
要搞清楚反射的性能问题,得先知道Go底层是怎么回事。
从Go1.14开始,runtime里几个核心类型的内存布局就没变过。这是个关键点。
Go的反射包就是基于runtime层的abi实现的。
reflect/type.go
// TypeOf returns the reflection [Type] that represents the dynamic type of i.
// If i is a nil interface value, TypeOf returns nil.
func TypeOf(i any) Type {
return toType(abi.TypeOf(i))
}
其实reflect.Type就是一个接口,上面代码里的toType()把它转成了reflect.rtype。
// rtype is the common implementation of most values.
// It is embedded in other struct types.
type rtype struct {
t abi.Type
}
func toRType(t *abi.Type) *rtype {
return (*rtype)(unsafe.Pointer(t))
}
所以最后拿到的是个abi.Type实例,reflect.rtype只是给它包了一层,提供个友好的接口。也可以换成别的类型专用结构体,但本质上都是对abi.Type的封装。
