go程序調(diào)試、分析與優(yōu)化_第1頁
go程序調(diào)試、分析與優(yōu)化_第2頁
go程序調(diào)試、分析與優(yōu)化_第3頁
go程序調(diào)試、分析與優(yōu)化_第4頁
go程序調(diào)試、分析與優(yōu)化_第5頁
已閱讀5頁,還剩22頁未讀, 繼續(xù)免費閱讀

付費下載

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)

文檔簡介

1、Go程序調(diào)試、分析與優(yōu)化八月 25, 20159條評論Brad Fitzpatrick在YAPC Asia 2015(Yet Anotherl Conference)上做了一次技術(shù),題為:GoDebugging, Profiling, and Optimization。個人感覺這篇中價值最大的是BradFitz現(xiàn)場演示的一個有關(guān)如何對Go程序進行調(diào)試、分析和優(yōu)化的 Demo,將上傳到了他個人在的repo中,但)。于 是打算在這不知為何,repo中的代碼似乎與repo里talk.md中的說明不甚一致(btw,我并沒有看里按照Brad的思路重新走一遍demo的演示流程(所有演示代碼在這里可以到)。

2、一、實驗環(huán)境$uname -aLinux pc-tony 3.13.0-61-generic #100precise1-Ubuntu SMP Wed Jul 2015 x86_64 x86_64 x86_64 GNU/Linux29 12:06:40注意:在Darwin或Windows下,profile的結(jié)果可能與這里有很大不同(甚至完全不一樣的輸出和瓶頸熱點)。$erergo1.5 linux/amd64$ go env GOARCH=amd64GOBIN=/home1/tonybai/.bin/go15/bin GOEXE=GOHOSTARCH=amd64GOHOSTOS=linux GO

3、OS=linuxGOPATH=/home1/tonybai/proj/GoProjects GORACE=GOROOT=/home1/tonybai/.bin/go15 GOTOOLDIR=/home1/tonybai/.bin/go15/pkg/tool/linux_amd64 GO15VENDOREXPERIMENT=1CC=gccGOGCCFLAGS=-fPIC -m64 -pthread -fmessage-length=0 CXX=g+CGO_ENABLED=1代碼基于的/bradfitz/talk-yapc-asia-2015。二、待優(yōu)化程序(step0)待優(yōu)化程序,也就是原始程序

4、,放在step0中:/go-debug-profile-optimization/step0/demo.gopackage mainimport (fmtlog net/http regexp)varvisitorsfunc handleHi(w http.ResponseWriter, r *http.Request)if match, _ := regexp.MatchString(w*$, r.FormValue(color) !match http.Error(w, Optional color is invalid, http.SreturnusBadRequest)visitors

5、+w.Header().Set(Content-Type, text/html charset=utf-8) w.Write(byte(e!You are visitor number + fmt.Spr(visitors)+!)func main()log.Prf(Starting on port 8080)http.HandleFunc(/hi, handleHi)log.Fatal(http.ListenAndServe(:8080,nil)$gorun demo.go2015/08/25 09:42:35 Starting on port 8080在瀏覽器輸入:一切順利的話,頁面會顯示

6、:e!You are visitor number 1!三、添加測試代碼按照talk.md中的說明,brad repo中demo中根本沒有測試代碼(commit2427d0faa12ed1fb05f1e6a1e69307c11259c2b2)。于是我根據(jù)作者的意圖,新增了demo_test.go,采用TesndleHi_Recorder和TesndleHi_TestServer對HandleHi進試:/go-debug-profile-optimization/step0/demo_test.gopackage mainimport (bufio net/httpnet/http/httpte

7、st stringstesting)func TesndleHi_Recorder(t *testing.T) rw := httptest.NewRecorder()handleHi(rw, req(t, GET / HTTP/1.0rnrn) if !strings.Contains(rw.Body.String(), visitort.Errorf(Unexpected output: %s, rw.Body)number) func req(t *testing.T, v string) *http.Request req, err := http.ReadRequest(bufi i

8、f err != nil t.Fatal(err)return reqReader(strings.NewReader(v)func Tests := deferndleHi_TestServer(t *testing.T) httptest.NewServer(http.HandlerFunc(handleHi) ts.Close()res, err := http.Get(ts.URL) if err != nil t.Error(err) returnif g, w := res.Header.Get(Content-Type), text/html charset=utf-8g !=

9、wt.Errorf(Content-Type = %q want %q,g,w)slurp, err := ioutil.ReadAll(res.Body) defer res.Body.Close()if err != nil t.Error(err) returnt.Logf(Got: %s, slurp)$ go test -v= RUNPASS:= RUNPASS:Tes TesTesTesndleHi_Recorder ndleHi_Recorder (0.00s)ndleHi_TestServerndleHi_TestServer (0.00s)demo_test.go:45: G

10、ot: e!You are visitor number2! PASSok_/home1/tonybai/proj/opensource/experiments/go-debug-profile-optimization/step00.007s測試通過!至此,step0使命結(jié)束。四、Race Detector(競態(tài)分析)并發(fā)設(shè)計使得程序可以更好更有效的利用現(xiàn)代處理器的多。但并發(fā)設(shè)計很容易引入競態(tài),導致嚴重bug。Go程序中競態(tài)就是當多個goroutine并發(fā)某共享數(shù)據(jù)且未使用同步機制時,且至少一個goroutine進行了寫操作。不過go工具自帶race分析功能。在分析優(yōu)化step0中demo代

11、碼 前,先要保證demo代碼中不存在競態(tài)。工具的使用方法就是在go test后加上-race標志,在step0目錄下:$ go test -v -race= RUNPASS:= RUNPASS:Tes TesTesTesndleHi_Recorder ndleHi_Recorder (0.00s)ndleHi_TestServerndleHi_TestServer (0.00s)demo_test.go:45: Got: e!You are visitor number2! PASSok_/home1/tonybai/proj/opensource/experiments/go-debug-p

12、rofile-optimization/step01.012s-race通過做運行時分析做競態(tài)分析,雖然不存在誤報,但卻存在實際有競態(tài),但工具沒發(fā)現(xiàn)的情況。接下來改造一下測試代碼,讓test并發(fā)起來:向step1(copy自step0)中demo_test.go中添加一個test method:/go-debug-profile-optimization/step1/demo_test.go func Tests := deferndleHi_TestServer_Parallel(t *testing.T) httptest.NewServer(http.HandlerFunc(handle

13、Hi) ts.Close()var wg sync.WaitGroupfor i := 0 iwg.Add(1) 2 i+ gofunc()deferwg.Done()res, err := http.Get(ts.URL) if err != nil t.Error(err) returnif g, w := res.Header.Get(Content-Type),text/htmlcharset=utf-8g!= w t.Errorf(Content-Type = %q want %q,g, w)slurp, err := ioutil.ReadAll(res.Body) defer r

14、es.Body.Close()if err != nil t.Error(err) returnt.Logf(Got: %s, slurp)()wg.Wait()執(zhí)行競態(tài)test:$ go test -v -race= RUNPASS:= RUNPASS:Tes TesTesTesndleHi_Recorder ndleHi_Recorder (0.00s)ndleHi_TestServerndleHi_TestServer (0.00s)demo_test.go:46: Got: e!You are visitornumber2!= RUNTesndleHi_TestServer_Paral

15、lel= WARNING: DATA RACERead by goroutine 22:_/home1/tonybai/proj/opensource/ optimization/step1.handleHi()/home1/tonybai/proj/opensource/ optimization/step1/demo.go:17 +0 xf5net/http.HandlerFunc.ServeHTTP()/experiments/go-debug-profile-/experiments/go-debug-profile-/tmp/workdir/go/src/net/http/serve

16、r.go:1422 +047 net/http/httptest.(*waitGroupHandler).ServeHTTP()/tmp/workdir/go/src/net/http/httptest/server.go:200 +0 xfe net/http.serverHandler.ServeHTTP()/tmp/workdir/go/src/net/http/server.go:1862 +0206 net/http.(*conn).serve()/tmp/workdir/go/src/net/http/server.go:1361 +0 x117cPrevious write by

17、 goroutine 25:_/home1/tonybai/proj/opensource/ optimization/step1.handleHi()/home1/tonybai/proj/opensource/ optimization/step1/demo.go:17 +0111net/http.HandlerFunc.ServeHTTP()/experiments/go-debug-profile-/experiments/go-debug-profile-/tmp/workdir/go/src/net/http/server.go:1422 +047 net/http/httptes

18、t.(*waitGroupHandler).ServeHTTP()/tmp/workdir/go/src/net/http/httptest/server.go:200 +0 xfe net/http.serverHandler.ServeHTTP()/tmp/workdir/go/src/net/http/server.go:1862 +0206 net/http.(*conn).serve()/tmp/workdir/go/src/net/http/server.go:1361 +0 x117cGoroutine 22 (running) created at:net/http.(*Ser

19、ver).Serve()/tmp/workdir/go/src/net/http/server.go:1910+0464Goroutine 25 (running) created at: net/http.(*Server).Serve()/tmp/workdir/go/src/net/http/server.go:1910=+0464 PASS: TesndleHi_TestServer_Parallel (0.00s)demo_test.go:71: Got: e!You are visitor number3!demo_test.go:71: Got: e!You are visito

20、r number4! PASSFound 1 exit sFAILdata raus 66)_/home1/tonybai/proj/opensource/experiments/go-debug-profile-optimization/step11.023s工具發(fā)現(xiàn)demo.go第17行:visitors+是一處潛在的競態(tài)條件。visitors被多個goroutine但未采用同步機制。既然發(fā)現(xiàn)了競態(tài)條件,就需要fix it。有多種fix方法可選:1、使用channel 2、使用Mutex3、使用atomicBrad使用了atomic:/go-debug-profile-optimizati

21、on/step1/demo.go var visitors64 / must be acsed atomicallyfunc handleHi(wif match, _http.ResponseWriter, r *http.Request):= regexp.MatchString(w*$, r.FormValue(color) !matchhttp.Error(w, Optional color is invalid, http.SreturnusBadRequest)visitNum := atomic.Add64(&visitors, 1)w.Header().Set(Content-

22、Type, text/html charset=utf-8)w.Write(byte(e!You are visitor number +fmt.Spr(visitNum) + !) 再做一次測試:$ go test -v -race= RUNPASS:= RUNPASS:Tes TesTesTesndleHi_Recorder ndleHi_Recorder (0.00s)ndleHi_TestServerndleHi_TestServer (0.00s)demo_test.go:46: Got: e!Youarevisitornumber2!= RUNTesndleHi_TestServe

23、r_Parallel PASS: TesndleHi_TestServer_Parallel (0.00s)demo_test.go:71: Got: e!Youarevisitornumber3!demo_test.go:71: Got: e!Youarevisitornumber4! PASSok_/home1/tonybai/proj/opensource/experiments/go-debug-profile-optimization/step11.020s競態(tài)條件被消除了!至此,step1結(jié)束了使命!五、CPU Profiling要做CPU Profilling,需要benark數(shù)

24、據(jù),Go test提供benark test功能,只要寫對應(yīng)的Benark測試方法即可:/go-debug-profile-optimization/step2/demo_test.go func BenarkHi(b *testing.B) b.ReportAllocs()req, err := http.ReadRequest(bufi HTTP/1.0rnrn)if err != nil b.Fatal(err)Reader(strings.NewReader(GET /for i := 0 i b.N i+ rw := httptest.NewRecorder() handleHi(r

25、w, req) $ go test -v -run=$ -bench=.PASSBenarkHi-410000014808 ns/op4961 B/op81allocs/opok_/home1/tonybai/proj/opensource/experiments/go-debug-profile-optimization/step21.648s開始CPU Profiling:$ go test -v -run=$ -bench=BenPASSarkHi$ -benchtime=2s -cpuprofile=prof.cpuBenarkHi-420000014679 ns/op4961 B/o

26、p81allocs/opok_/home1/tonybai/proj/opensource/experiments/go-debug-profile-optimization/step23.096s執(zhí)行完benark test后,step2目錄下出現(xiàn)兩個新文件prof.cpu和step2.test,這兩個文件將作為后續(xù)go tool pprof的輸入:$lsdemo.godemo_test.goprof.cpustep2.test*使用go profile viewer工具:$ go tool pprof step2.test prof.cpuEntering(pprof) toperacti

27、ve mode (type help fords)1830ms of 3560ms total (51.40%)Dropped 53 nodes (cum = 1290ms)flat 480ms 360ms 170ms 170ms120msflat% 13.48%10.11%4.78%4.78%3.37%sum% 13.48%23.60%28.37%33.15%36.52%cum 980ms 700ms 170ms 200ms1100mscum% 27.53%19.66%4.78%5.62%30.90%runtime.growslice runtime.mallocgc runtime.hea

28、pBitsSetType runtime.scanblockregexp.makeOnePass.func2120ms 110ms 110ms 100ms90ms3.37%3.09%3.09%2.81%2.53%39.89%42.98%46.07%48.88%51.40%550ms 300ms 220ms 100ms1290ms15.45%8.43%6.18%2.81%36.24%runtime.newarrayruntime.makesliceruntime.mruntime.futexsign1regexp.makeOnePass(pprof) topcum0.18s of 3.56s t

29、otal ( 5.06%)Dropped 53 nodes (cum = 1.29s)flat%0%0.56%0%0%0.84%0.28%0%0%0.84%2.53%sum%0%0.56%0.56%0.56%1.40%1.69%1.69%1.69%2.53%5.06%cum 3.26s2.87s2.87s2.87s2.80s2.46s2.24s2.24s1.56s1.29scum% 91.57%80.62%80.62%80.62%78.65%69.10%62.92%62.92%43.82%36.24%runtime.goexitBenarkHitesting.(*B).launch testi

30、ng.(*B).runN step2.handleHi regexp.MatchStringpile pilepileOnePassregexp.makeOnePass(pprof) lisTotal: 3.56sndleHiROUTINE = handleHi in go-debug-profile-optimization/step2/demo.go30ms.2.80s.(flat, cum) 78.65% of 9:)10:11:var visitors 12:13:func handleHi(wTotal64 / must be acsedatomicallyhttp.Response

31、Writer, r*http.Request).2.47s14:!match15:ifmatch, _:= regexp.MatchString(w*$,r.FormValue(color).http.Error(w, Optional color is invalid,http.SusBadRequest).10ms 10ms.20ms 90ms16:17:18:19:returnvisitNum := atomic.Add64(&visitors, 1)w.Header().Set(Content-Type, text/htmlcharset=utf-8)10ms20ms20:w.Writ

32、e(byte(e!You are visitor number+fmt.Spr(visitNum) +.24:func main()f(Starting on port 8080)25:26:log.Prhttp.HandleFunc(/hi, handleHi)(pprof)從top cum來看,handleHi消耗cpu較大,而handleHi中,又是MatchString耗時最長。六、第一次優(yōu)化前面已經(jīng)發(fā)現(xiàn)MatchString較為耗時,優(yōu)化:讓正則式僅編譯一次(step3):/ go-debug-profile-optimization/step3/demo.go var visito

33、rs64 / must be acsed atomicallyvar rxOptionalID =pile(d*$)func handleHi(w http.ResponseWriter, r *http.Request) if !rxOptionalID.MatchString(r.FormValue(color) http.Error(w, Optional color is invalid, http.S returnusBadRequest)visitNum := atomic.Add64(&visitors, 1)w.Header().Set(Content-Type, text/h

34、tml charset=utf-8)w.Write(byte(e!You are visitornumber + fmt.Spr(visitNum) +!) 運行一下bench:$ go test -bench=.PASSBenarkHi-410000001678ns/op720 B/op9allocs/opok_/home1/tonybai/proj/opensource/experiments/go-debug-profile-optimization/step31.710s對比之前在step2中運行的bench結(jié)果:$ go test -v -run=$ -bench=.PASSBena

35、rkHi-410000014808 ns/op4961 B/op81allocs/opok_/home1/tonybai/proj/opensource/experiments/go-debug-profile-optimization/step21.648s耗時相同,但優(yōu)化后的bench運行了100w次,而之前的Bench運行10w次,相當于性能提高10倍。再看看cpu prof結(jié)果:$ go test -v -run=$ -bench=BenPASSarkHi$ -benchtime=3s -cpuprofile=prof.cpuBenarkHi-430000001640 ns/op720

36、 B/op9allocs/opok_/home1/tonybai/proj/opensource/experiments/go-debug-profile-optimization/step36.540s$ go tool pprof step3.test prof.cpuEnteringeractive mode (typehelp fords)(pprof) top cum 302.74s of 8.07s total (33.95%)Dropped 72 nodes (cum = 0.56s)flat%0%0.62%0%0%0.74%sum%0%0.62%0.62%0.62%1.36%1

37、5.61%15.86%15.86%16.60%17.72%18.34%cum 7.17s6.21s6.21s6.21s4.96s2.35s1.63s1.53s1.53s1.22s1.09scum% 88.85%76.95%76.95%76.95%61.46%29.12%20.20%18.96%18.96%15.12%13.51%runtime.goexitstep3.BenarkHitesting.(*B).launch testing.(*B).runN step3.handleHi runtime.mallocgc runtime.systemstack net/http.Header.S

38、et net/textproto.MIMEHeader.Set runtime.newobjectfmt.Spr14.25%0.25%0%0.74%1.12%0.62%0.20s00.01s0.05s0.09s0.01s0.20s00.05s00.04s0.01s0.01s00.01s0.28s0.17s0.02s0.11s2.48%0%0.12%0.62%1.12%0.12%2.48%0%0.62%0%0.5%0.12%0.12%0%0.12%3.47%2.11%0.25%1.36%20.82%20.82%20.94%21.56%22.68%22.80%25.28%25.28%25.90%2

39、5.90%26.39%26.52%26.64%26.64%26.77%30.24%32.34%32.59%33.95%1s 0.81s0.79s0.76s0.71s0.71s0.70s0.69s0.69s0.68s0.68s0.67s0.65s0.65s0.65s0.62s0.59s0.58s0.56s12.39%10.04%9.79%9.42%8.80%8.80%8.67%8.55%8.55%8.43%8.43%8.30%8.05%8.05%8.05%7.68%7.31%7.19%6.94%runtime.mruntime.mcallsign1runtime.schedule regexp.

40、(*Regexp).MatchString regexp.(*Regexp).doExecute runtime.concatstring5runtime.concatstringsruntime.gosponeruntime.mSpan_Spruntime.bgspruntime.newarray runtime.goschedImpl runtime.gosched_mruntime.gospone.func1runtime.sponeruntime.makemap runtime.heapBitsSfmt.(*pp).doPrpSpanfmt.(*pp).prArghandleHi耗時有

41、一定下降。七、Mem Profiling在step3目錄下執(zhí)行bench,獲取mem分配數(shù)據(jù):$ go test -v -run=$ -bench=BenPASSarkHi$ -benchtime=2s -memprofile=prof.memBenarkHi-420000001657 ns/op720 B/op9allocs/opok_/home1/tonybai/proj/opensource/experiments/go-debug-profile-optimization/step35.002s使用pprof工具分析mem:$ go tool pprof alloc_spatep3.t

42、est prof.memEntering(pprof) toperactive mode (type help fords)2065.91MB of 2067.41MB total (99.93%)Dropped 14flat 1076.35MBnodes (cum =flat%sum% 52.06% 52.06%10.34MB)cumcum% 1076.35MB 52.06%net/textproto.MIMEHeader.Set535.54MB406.52MB47.50MB000025.90%19.66%2.30%0%0%0%0%77.97%97.63%99.93%99.93%99.93%

43、99.93%99.93%2066.91MB1531.37MB48.50MB1076.35MB2066.91MB2066.91MB2066.91MB100%74.07%2.35%52.06%100%100%100%step3.BenarkHistep3.handleHi fmt.Spr net/http.Header.Set runtime.goexit testing.(*B).launchtesting.(*B).runN(pprof) top-cum2065.91MB of 2067.41MB total (99.93%)Dropped 14flat 535.54MB000406.52MB

44、01076.35MB47.50MBnodes (cum =10.34MB)cum 2066.91MB2066.91MB2066.91MB2066.91MB1531.37MB1076.35MB1076.35MB48.50MBflat% 25.90%0%0%0%19.66%0%52.06%2.30%sum% 25.90%25.90%25.90%25.90%45.57%45.57%97.63%99.93%cum% 100%100%100%100%74.07%52.06%52.06%2.35%step3.BenarkHiruntime.goexit testing.(*B).launch testin

45、g.(*B).runN step3.handleHi net/http.Header.Set net/textproto.MIMEHeader.Setfmt.Spr(pprof) lis Total: 2.02GBROUTINE 406.52MB.ndleHi=step3.handleHi in step3/demo.go1.50GB (flat, cum)74.07% of Totalhttp.Error(w, Optional color is invalid,.17:http.SusBadRequest).charset=utf-8).18:19:20:21:22:returnvisit

46、Num := atomic.Add64(&visitors, 1)1.05GBw.Header().Set(Content-Type, text/html.23:w.Write(byte(e!You are visitor number +(visitNum) +.27:func main()f(Starting on port 8080)28:log.Pr.29:http.HandleFunc(/hi, handleHi)(pprof)可以看到handleHi22、23兩行占用了較多內(nèi)存。八、第二次優(yōu)化第二次優(yōu)化的方法:1、刪除w.Header().Set這行2、用fmt.Fprf替代w.W

47、rite第二次優(yōu)化的代碼在step4目錄中:/ go-debug-profile-optimization/step4/demo.go func handleHi(w http.ResponseWriter, r *http.Request) if !rxOptionalID.MatchString(r.FormValue(color) http.Error(w, Optional color is invalid, http.SusBadRequest) returnvisitNum fmt.Fprnumber %d!, := atomic.Add64(&visitors, 1)f(w, e

48、!You are visitorr.FormValue(color),visitNum)執(zhí)行一遍pprof:$ go test -v -run=$ -bench=BenPASSarkHi$ -benchtime=2s -memprofile=prof.memBenarkHi-420000001428 ns/op304 B/op6allocs/opok_/home1/tonybai/proj/opensource/experiments/go-debug-profile-optimization/step44.343s$ go tool pprof alloc_spatep4.test prof

49、.memEntering(pprof) toperactivemode (type help fords)868.06MB of 868.56MBDropped 5 nodes (cumtotal (99.94%)= 4.34MB)flat flat%sum%559.54MB 64.42% 64.42%cumcum%868.06MB 99.94%step4.BenarkHi219.52MB89MB000025.27%10.25%0%0%0%0%89.70%99.94%99.94%99.94%99.94%99.94%219.52MB308.52MB219.52MB219.52MB219.52MB

50、219.52MB25.27%35.52%25.27%25.27%25.27%25.27%bytes.makeSlice step4.handleHi bytes.(*Buffer).Writebytes.(*Buffer).growfmt.Fprfnet/http/httptest.(*ResponseRecorder).Write000(pprof) top 868.06MB of0%0%0%cum99.94%99.94%99.94%868.06MB868.06MB868.06MB99.94%99.94%99.94%runtime.goexittesting.(*B).launch test

51、ing.(*B).runN868.56MB total(99.94%)Dropped 5 nodes (cum . 308.52MBe!You.18:19:20:21:22:returnvisitNum := atomic.Add64(&visitors, 1)fmt.Fprf(w, h1 stype=color:are visitor number %d!, r.FormValue(color), visitNum) 23:24:25:func main() .26:27:log.Prf(Starting on port 8080)http.HandleFunc(/hi, handleHi)

52、(pprof)可以看出內(nèi)存占用大幅減少。九、Benchcmpgolang./x/tools中有一個工具:benchcmp,可以給出兩次bench的結(jié)果對比。/golang/tools是golang./x/tools的一個鏡像。安enchcmp步驟:1、go get -u/golang/tools2、mkdir -p $GOPATH/src/golang./x3、mv $GOP4、go install golang./golang/tools $GOPATH/src/golang./x/tools/cmd/benchcmp/x分別在step2、step3和step4下執(zhí)行如下命令:$ go-de

53、bug-profile-optimization/step2$ go test -bench=. -memprofile=prof.mem mem.2PASS| teeBenarkHi-410000014786 ns/op4961 B/op81allocs/opok_/home1/tonybai/proj/opensource/experiments/go-debug-profile-optimization/step21.644sgo-debug-profile-optimization/step3$ go test -bench=. -memprofile=prof.mem | mem.3

54、PASSteeBenarkHi-410000001662 ns/op720 B/op9allocs/opok_/home1/tonybai/proj/opensource/experiments/go-debug-profile-optimization/step31.694sgo-debug-profile-optimization/step4$ go test -bench=. -memprofile=prof.mem | mem.4PASSteeBenarkHi-410000001428 ns/op304 B/op6allocs/opok_/home1/tonybai/proj/open

55、source/experiments/go-debug-profile-optimization/step41.456s利用benchcmp工具對比結(jié)果(benchcmp old new):$ benchcmp step3/mem.3 step4/mem.4benBenarkarkHi-4old ns/op1662new ns/op1428delta-14.08%benBenarkarkHi-4old9allocsnew6allocsdelta-33.33%benBenarkarkHi-4old720bytesnew304bytesdelta-57.78%$ benchcmp step2/me

56、m.2 step4/mem.4benBenarkarkHi-4old ns/op14786new1428ns/opdelta-90.34%benBenarkarkHi-4old81allocsnew6allocsdelta-92.59%benBenarkarkHi-4old4961bytesnew304bytesdelta-93.87%可以看出優(yōu)化后,內(nèi)存分配大幅減少,gc的時間也隨之減少。十、內(nèi)存來自哪在BenarkHi中每次handleHi執(zhí)行后的內(nèi)存:/step5/demo_test.go func BenarkHi(b *testing.B) b.ReportAllocs()req,

57、err := http.ReadRequest(bufi HTTP/1.0rnrn)if err != nil b.Fatal(err)Reader(strings.NewReader(GET/for i := 0 i b.N i+ rw := httptest.NewRecorder() handleHi(rw, req)reset(rw)func reset(rw *httptest.ResponseRecorder) m := rw.HeaderMapfor k := range m delete(m, k)body := rw.Body body.Reset()*rw = httpte

58、st.ResponseRecorderBody:body,HeaderMap: m, $ go test -v -run=$ -bench=Ben PASSarkHi$-benchtime=2s-memprofile=prof.memBenarkHi-420000001518 ns/op304 B/op6allocs/opok_/home1/tonybai/proj/opensource/experiments/go-debug-profile-optimization/step54.577s$ go tool pprof alloc_spatep5.test prof.memEntering

59、eractive mode (type help fords)(pprof) top cum 10290.52MB of 291.52MB total (99.66%)Dropped 14flat0179.01MB0026.50MB0085.01MB00nodes (cum .(pprof). 111.51MBe!You.18:19:20:21:22:returnvisitNum := atomic.Add64(&visitors, 1)fmt.Fprf(w, h1 stype=color:are visitor number %d!, r.FormValue(color), visitNum

60、) 23:24:25:func main() 26:27:log.Prf(Starting on port 8080)http.HandleFunc(/hi, handleHi)內(nèi)存從300MB降到111MB。內(nèi)存來自哪?看到lisndleHi,fmt.Fprf分配了111.51MB。來看這一行代碼:fmt.Fprf(w, r.FormValue(color), num)e!You are visitor number %d!,fmt.Fprf的manual:$ go docfunc Fprfmt.Fprff(w io.Writer, format string, aerface) (n, e

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
  • 6. 下載文件中如有侵權(quán)或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論