一、高性能
-
使用sync.pool解决频繁创建的context对象,在百万并发的场景下能大大提供访问性能和减少GC
// ServeHTTP conforms to the http.Handler interface. // 每次的http请求都会从sync.pool中获取context,用完之后归还到pool中 func (engine *Engine) ServeHTTP(w http.ResponseWriter, req *http.Request) { c := engine.pool.Get().(*Context) c.writermem.reset(w) //重置 responsewriter c.Request = req c.reset() //重置使用过的context各个属性 engine.handleHTTPRequest(c) engine.pool.Put(c) } // 这里给pool指定了一个创建新对象的函数,注意不是所有的请求共用一个context,context在高并发场景下可能会分配多个,但是远远小于并发协程数量。 sync.pool.new是可能并发调用的,所以内部的逻辑需要保障线程安全 func New(opts ...OptionFunc) *Engine { ... engine.RouterGroup.engine = engine engine.pool.New = func() any { return engine.allocateContext(engine.maxParams) } return engine.With(opts...) } //每次http请求都需要分配一个context,这个初始context初始化了两个数组的最大容量 func (engine *Engine) allocateContext(maxParams uint16) *Context { v := make(Params, 0, maxParams) skippedNodes := make([]skippedNode, 0, engine.maxSections) return &Context{ engine: engine, params: &v, skippedNodes: &skippedNodes} }
-
前缀树路由(类似httprouter的路由,提升性能近40倍)
gin在v1.0版本开始放弃了
github.com/julienschmidt/httprouter
,重新实现了一套路由;对比gin新实现的路由基本上采用了httprouter的逻辑,但是和框架结合的更加完整,比如说把httprouter中router的能力提到了engine中。 -
json序列化优化
gin提供了四种可选的json序列化方式,默认情况下会使用encoding/json
/github.com/gin-gonic/gin@v1.10.0/internal/json -- go_json.go ("github.com/goccy/go-json") -- json.go ("encoding/json") -- jsoniter.go ("github.com/json-iterator/go") -- sonic.go ("github.com/bytedance/sonic")
需要在编译期间指定tag来决定使用哪种序列化工具
go run -tags={ go_json|jsoniter