本文转载请联系码农桃花源公众号。大家好,我是小X,曹达最近开了围棋课程,小X跟曹达一起围棋。本系列将讨论从课程中学到的一些有启发性的东西,拨开乌云,带你回到Go。之前写过一篇《成为 Go Contributor》,讲的是如何给Go提交一个错别字的PR,熟悉一下整个流程。当然,它离真正的Contributor还很远。开课前,曹达讲了他在Go夜读中提到的对Go的tls的性能优化,他在课上讲的很详细。本文将带你了解他优化了什么,以及如何看优化效果。第一次提到的pr就在这里,后来搬到了新的地方。前后做了一些代码简化,最后看起来很舒服。优化前,每个tls连接都有一个writebuffer,但是活跃连接数很少,大量内存空闲。这可以使用sync.Pool进行优化。Conn使用sync.Pool来缓存[]byte,顺便kill掉连接上的一个outBuf字段:fileschanged总体变化不大,效果还不错。虽然一开始就给出了_test文件,但是并不能很好的体现性能提升。所以后来曹达写了一个简单的客户端和服务端来实际测试。我在开发机上测试了一下,优化还是比较明显的。这是使用pprof查看性能优化的另一个很好的例子。客户端代码如下:packagemainimport("crypto/tls""fmt""io/ioutil""net/http""os""strconv""sync""go.uber.org/ratelimit")funcmain(){url:=os.Args[3]connNum,err:=strconv.ParseInt(os.Args[1],10,64)iferr!=nil{fmt.Println(err)return}qps,err:=strconv.ParseInt(os.Args[2],10,64)iferr!=nil{fmt.Println(err)return}bucket:=ratelimit.New(int(qps))varlsync.MutexconnList:=make([]*http.Client,connNum)fori:=0;;i++{bucket.Take()i:=igofunc(){l.Lock()ifconnList[i%len(connList)]==nil{connList[i%len(connList)]=&http.Client{Transport:&http.Transport{TLSClientConfig:&tls.Config{InsecureSkipVerify:true},IdleConnTimeout:0,MaxIdleConns:1,MaxIdleConnsPerHost:1,},}}conn:=connList[i%len(connList)]湖。Unlock()ifresp,e:=conn.Get(url);e!=nil{fmt.Println(e)}else{deferresp.Body.Close()ioutil.ReadAll(resp.Body)}}()}}逻辑比较简单,就是向固定连接数、固定QPS的服务器发送请求。服务端代码如下:packagemainimport("fmt""net/http"_"net/http/pprof")varcontent=make([]byte,16000)funcsayhello(wrhttp.ResponseWriter,r*http.Request){wr.Header()["Content-Length"]=[]string{fmt.Sprint(len(content))}wr.Header()["Content-Type"]=[]string{"application/json"}wr.Write(content)}funcmain(){gofunc(){http.ListenAndServe(":3333",nil)}()http.HandleFunc("/",sayhello)err:=http.ListenAndServeTLS(":4443","server.crt","server.key",nil)iferr!=nil{fmt.Println(err)}}逻辑也很简单,搭建了一个tls服务器,注册了一个sayhello接口。启动服务器后,先用1.15测试(1.17之前的版本都可以,草大的改动还没收进去)测试:gorunserver.go#1000connections,100QPSgorunclient.go1000100https://localhost:4443查看内存配置文件服务器。后面会用到--base命令来比较前后两个profile文件的区别。pprof的命令如下:gotoolpprof--http=:8000http://127.0.0.1:3333/debug/pprof/heapGo1.15memprofile看看这个大“平顶山”,有那个味道(平顶山的意思是可以进行优化,如果是那没办法使用特别窄的提示)~因为这个pr已经到1.17了,我们再用1.17测试一下:go1.17rc1runserver.gogo1.17rc1runclient.go1000100https://localhost:4443Go1.17memprofileforuse--base命令比较,需要保存profile文件:curlhttp://127.0.0.1:3333/debug/pprof/heap>mem.1.14curlhttp://127.0.0.1:3333/debug/pprof/堆>内存。1.17最后对比一下优化前后的区别:gotoolpprof-http=:8000--basemem.1.15mem.1.17--base优化效果还是很明显的。再来看菜单栏中的view->top:view->top整体优化从最终提交来看还是挺简单的,但是要根据自己的知识储备去发现问题并优化就相当困难了。我们平时要多积累相关的优化经验,这样才能在关键时候顶一下。像pprof的使用,需要自己多练习。好了,今天就到这里啦~我是小X,下次见~参考[1]tls的性能优化:https://www.bilibili.com/video/BV1Z64y1m7uc[2]这里:https://go-review.googlesource.com/c/go/+/263277[3]位置:https://go-review.googlesource.com/c/go/+/267957
