精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

使用 Go defer 要小心這 2 個雷區(qū)!

開發(fā) 后端
大家擔(dān)心如果循環(huán)過大 defer 鏈表會巨長,不夠 “精益求精”。又或是猜想會不會 Go defer 的設(shè)計和 Redis 數(shù)據(jù)結(jié)構(gòu)設(shè)計類似,自己做了優(yōu)化,其實沒啥大影響?

[[395204]]

大家好,我是煎魚。

在 Go 語言中 defer 是一個非常有意思的關(guān)鍵字特性。例子如下:

  1. package main 
  2.  
  3. import "fmt" 
  4.  
  5. func main() { 
  6.  defer fmt.Println("煎魚了"
  7.  
  8.  fmt.Println("腦子進(jìn)"

輸出結(jié)果是:

  1. 腦子進(jìn) 
  2. 煎魚了 

在前幾天我的讀者群內(nèi)有小伙伴討論起了下面這個問題:

讀者群的聊天截圖

簡單來講,問題就是針對在 for 循環(huán)里搞 defer 關(guān)鍵字,是否會造成什么性能影響?

因為在 Go 語言的底層數(shù)據(jù)結(jié)構(gòu)設(shè)計上 defer 是鏈表的數(shù)據(jù)結(jié)構(gòu):

defer 基本底層結(jié)構(gòu)

大家擔(dān)心如果循環(huán)過大 defer 鏈表會巨長,不夠 “精益求精”。又或是猜想會不會 Go defer 的設(shè)計和 Redis 數(shù)據(jù)結(jié)構(gòu)設(shè)計類似,自己做了優(yōu)化,其實沒啥大影響?

今天這篇文章,我們就來探索循環(huán) Go defer,造成底層鏈表過長會不會帶來什么問題,若有,具體有什么影響?

開始吸魚之路。

defer 性能優(yōu)化 30%

在早年 Go1.13 時曾經(jīng)對 defer 進(jìn)行了一輪性能優(yōu)化,在大部分場景下 提高了 defer 30% 的性能:

Go defer 1.13 優(yōu)化記錄

我們來回顧一下 Go1.13 的變更,看看 Go defer 優(yōu)化在了哪里,這是問題的關(guān)鍵點。

以前和現(xiàn)在對比

在 Go1.12 及以前,調(diào)用 Go defer 時匯編代碼如下:

  1. 0x0070 00112 (main.go:6)    CALL    runtime.deferproc(SB) 
  2.  0x0075 00117 (main.go:6)    TESTL    AX, AX 
  3.  0x0077 00119 (main.go:6)    JNE    137 
  4.  0x0079 00121 (main.go:7)    XCHGL    AX, AX 
  5.  0x007a 00122 (main.go:7)    CALL    runtime.deferreturn(SB) 
  6.  0x007f 00127 (main.go:7)    MOVQ    56(SP), BP 

在 Go1.13 及以后,調(diào)用 Go defer 時匯編代碼如下:

  1. 0x006e 00110 (main.go:4) MOVQ AX, (SP) 
  2. 0x0072 00114 (main.go:4) CALL runtime.deferprocStack(SB) 
  3. 0x0077 00119 (main.go:4) TESTL AX, AX 
  4. 0x0079 00121 (main.go:4) JNE 139 
  5. 0x007b 00123 (main.go:7) XCHGL AX, AX 
  6. 0x007c 00124 (main.go:7) CALL runtime.deferreturn(SB) 
  7. 0x0081 00129 (main.go:7) MOVQ 112(SP), BP 

從匯編的角度來看,像是原本調(diào)用 runtime.deferproc 方法改成了調(diào)用 runtime.deferprocStack 方法,難道是做了什么優(yōu)化?

我們抱著疑問繼續(xù)看下去。

defer 最小單元:_defer

相較于以前的版本,Go defer 的最小單元 _defer 結(jié)構(gòu)體主要是新增了 heap 字段:

  1. type _defer struct { 
  2.  siz     int32 
  3.  siz     int32 // includes both arguments and results 
  4.  started bool 
  5.  heap    bool 
  6.  sp      uintptr // sp at time of defer 
  7.  pc      uintptr 
  8.  fn      *funcval 
  9.  ... 

該字段用于標(biāo)識這個 _defer 是在堆上,還是在棧上進(jìn)行分配,其余字段并沒有明確變更,那我們可以把聚焦點放在 defer 的堆棧分配上了,看看是做了什么事。

deferprocStack

  1. func deferprocStack(d *_defer) { 
  2.  gp := getg() 
  3.  if gp.m.curg != gp { 
  4.   throw("defer on system stack"
  5.  } 
  6.   
  7.  d.started = false 
  8.  d.heap = false 
  9.  d.sp = getcallersp() 
  10.  d.pc = getcallerpc() 
  11.  
  12.  *(*uintptr)(unsafe.Pointer(&d._panic)) = 0 
  13.  *(*uintptr)(unsafe.Pointer(&d.link)) = uintptr(unsafe.Pointer(gp._defer)) 
  14.  *(*uintptr)(unsafe.Pointer(&gp._defer)) = uintptr(unsafe.Pointer(d)) 
  15.  
  16.  return0() 

這一塊代碼挺常規(guī)的,主要是獲取調(diào)用 defer 函數(shù)的函數(shù)棧指針、傳入函數(shù)的參數(shù)具體地址以及PC(程序計數(shù)器),這塊在前文 《深入理解 Go defer》 有詳細(xì)介紹過,這里就不再贅述了。

這個 deferprocStack 特殊在哪呢?

可以看到它把 d.heap 設(shè)置為了 false,也就是代表 deferprocStack 方法是針對將 _defer 分配在棧上的應(yīng)用場景的。

deferproc

問題來了,它又在哪里處理分配到堆上的應(yīng)用場景呢?

  1. func newdefer(siz int32) *_defer { 
  2.  ... 
  3.  d.heap = true 
  4.  d.link = gp._defer 
  5.  gp._defer = d 
  6.  return d 

具體的 newdefer 是在哪里調(diào)用的呢,如下:

  1. func deferproc(siz int32, fn *funcval) { // arguments of fn follow fn 
  2.  ... 
  3.  sp := getcallersp() 
  4.  argp := uintptr(unsafe.Pointer(&fn)) + unsafe.Sizeof(fn) 
  5.  callerpc := getcallerpc() 
  6.  
  7.  d := newdefer(siz) 
  8.  ... 

非常明確,先前的版本中調(diào)用的 deferproc 方法,現(xiàn)在被用于對應(yīng)分配到堆上的場景了。

小結(jié)

  • 可以確定的是 deferproc 并沒有被去掉,而是流程被優(yōu)化了。
  • Go 編譯器會根據(jù)應(yīng)用場景去選擇使用 deferproc 還是 deferprocStack 方法,他們分別是針對分配在堆上和棧上的使用場景。

優(yōu)化在哪兒

主要優(yōu)化在于其 defer 對象的堆棧分配規(guī)則的改變,措施是:編譯器對 defer 的 for-loop 迭代深度進(jìn)行分析。

  1. // src/cmd/compile/internal/gc/esc.go 
  2. case ODEFER: 
  3.  if e.loopdepth == 1 { // top level 
  4.   n.Esc = EscNever // force stack allocation of defer record (see ssa.go) 
  5.   break 
  6.  } 

如果 Go 編譯器檢測到循環(huán)深度(loopdepth)為 1,則設(shè)置逃逸分析的結(jié)果,將分配到棧上,否則分配到堆上。

  1. // src/cmd/compile/internal/gc/ssa.go 
  2. case ODEFER: 
  3.  d := callDefer 
  4.  if n.Esc == EscNever { 
  5.   d = callDeferStack 
  6.  } 
  7.  s.call(n.Left, d) 

以此免去了以前頻繁調(diào)用 systemstack、mallocgc 等方法所帶來的大量性能開銷,來達(dá)到大部分場景提高性能的作用。

循環(huán)調(diào)用 defer

回到問題本身,知道了 defer 優(yōu)化的原理后。那 “循環(huán)里搞 defer 關(guān)鍵字,是否會造成什么性能影響?”

最直接的影響就是這大約 30% 的性能優(yōu)化直接全無,且由于姿勢不正確,理論上 defer 既有的開銷(鏈表變長)也變大,性能變差。

因此我們要避免以下兩種場景的代碼:

  • 顯式循環(huán):在調(diào)用 defer 關(guān)鍵字的外層有顯式的循環(huán)調(diào)用,例如:for-loop 語句等。
  • 隱式循環(huán):在調(diào)用 defer 關(guān)鍵字有類似循環(huán)嵌套的邏輯,例如:goto 語句等。

顯式循環(huán)

第一個例子是直接在代碼的 for 循環(huán)中使用 defer 關(guān)鍵字:

  1. func main() { 
  2.  for i := 0; i <= 99; i++ { 
  3.   defer func() { 
  4.    fmt.Println("腦子進(jìn)煎魚了"
  5.   }() 
  6.  } 

這個也是最常見的模式,無論是寫爬蟲時,又或是 Goroutine 調(diào)用時,不少人都喜歡這么寫。

這屬于顯式的調(diào)用了循環(huán)。

隱式循環(huán)

第二個例子是在代碼中使用類似 goto 關(guān)鍵字:

  1. func main() { 
  2.  i := 1 
  3. food: 
  4.  defer func() {}() 
  5.  if i == 1 { 
  6.   i -= 1 
  7.   goto food 
  8.  } 

這種寫法比較少見,因為 goto 關(guān)鍵字有時候甚至?xí)涣袨榇a規(guī)范不給使用,主要是會造成一些濫用,所以大多數(shù)就選擇其實方式實現(xiàn)邏輯。

這屬于隱式的調(diào)用,造成了類循環(huán)的作用。

總結(jié)

顯然,Defer 在設(shè)計上并沒有說做的特別的奇妙。他主要是根據(jù)實際的一些應(yīng)用場景進(jìn)行了優(yōu)化,達(dá)到了較好的性能。

雖然本身 defer 會帶一點點開銷,但并沒有想象中那么的不堪使用。除非你 defer 所在的代碼是需要頻繁執(zhí)行的代碼,才需要考慮去做優(yōu)化。

否則沒有必要過度糾結(jié),在實際上,猜測或遇到性能問題時,看看 PProf 的分析,看看 defer 是不是在相應(yīng)的 hot path 之中,再進(jìn)行合理優(yōu)化就好。

 

所謂的優(yōu)化,可能也只是去掉 defer 而采用手動執(zhí)行,并不復(fù)雜。在編碼時避免踩到 defer 的顯式和隱式循環(huán)這 2 個雷區(qū)就可以達(dá)到性能最大化了。

 

責(zé)任編輯:武曉燕 來源: 腦子進(jìn)煎魚了
相關(guān)推薦

2025-03-12 00:22:00

2013-06-25 09:52:32

GoGo語言Go編程

2022-08-23 08:53:31

Go項目語言

2025-08-05 02:11:00

2024-01-07 23:11:16

defer?Go語言

2020-02-05 14:42:52

網(wǎng)絡(luò)安全IT安全漏洞

2021-03-31 22:51:51

手機(jī)爆炸充電

2018-12-04 14:00:41

協(xié)程編程模式PHP

2019-04-26 12:29:04

云遷移數(shù)據(jù)

2023-07-11 08:46:38

閉包函數(shù)Rust

2021-04-22 10:14:46

Redis數(shù)據(jù)庫命令

2020-08-06 08:27:21

JavaScript概念語言

2021-03-30 15:10:50

Java序列化

2022-06-08 10:40:18

顯卡礦卡暴跌

2025-10-31 09:01:37

2010-04-22 10:13:46

Google英特爾

2021-06-07 23:19:44

Golang語言 Defer

2011-08-09 13:43:48

2010-12-01 11:08:43

職場

2013-09-03 10:18:16

虛擬網(wǎng)絡(luò)VMware思科
點贊
收藏

51CTO技術(shù)棧公眾號

国产91精品露脸国语对白| 欧美精品一区二区久久| 亚洲一区二区三区四区的| 国产欧美一区二区三区不卡高清| 国产精品国产三级国产专区52| 久久99国内| 欧美一区二区免费视频| 国产精品久久久久久久乖乖| 青青视频在线观| 日本不卡在线视频| 久久99国产精品久久久久久久久| 91精品又粗又猛又爽| 欧美日韩国产v| 亚洲老司机在线| 久精品国产欧美| 国产三级视频在线播放| 国产视频一区欧美| 久久久电影免费观看完整版| 亚洲av成人片无码| 欧美网站免费| 欧美网站在线观看| 免费看黄色a级片| 免费看男男www网站入口在线 | 高清亚洲成在人网站天堂| 国产三级av在线播放 | 欧美日韩在线精品一区二区三区| av综合在线观看| 美美哒免费高清在线观看视频一区二区| 久久久久久久久网站| 精品一区二区在线观看视频| 尤物tv在线精品| 亚洲高清不卡av| 苍井空张开腿实干12次| 国产成人免费av一区二区午夜| 色综合夜色一区| 91丨porny丨探花| 日韩少妇视频| 亚洲免费在线看| 一区二区在线观看网站| 国产人成在线观看| 久久久91精品国产一区二区精品| 国产一级特黄a大片99| 国产黄色片网站| 国内精品国产成人| 成人一区二区电影| 亚洲天堂视频网| 久久精品国产99国产| 国产精品久久久久国产a级| 五月天婷婷导航| 久久一区中文字幕| 日本欧美黄网站| 久久精品视频7| 欧美专区18| 日韩美女视频中文字幕| 秋霞av一区二区三区| 久久久久99| 国产精品青青在线观看爽香蕉| 欧美日韩一级黄色片| 玖玖玖国产精品| 国产精品www网站| 亚洲天天综合网| 久久福利视频一区二区| 成人高清视频观看www| 一级全黄裸体免费视频| 九九热在线视频观看这里只有精品| 国产精品偷伦视频免费观看国产 | 国产一区二区三区四区五区美女| 成人性生交大片免费看小说| 99草在线视频| 成人午夜免费电影| 精品国产免费一区二区三区| 天堂av在线免费观看| 久久久国际精品| 亚洲va韩国va欧美va精四季| 黄网站视频在线观看| 玉米视频成人免费看| 国产视频在线观看网站| 亚洲一区资源| 欧美日韩国产首页| 国产人妖在线观看| 欧美网色网址| 最近更新的2019中文字幕| 午夜精品福利在线视频| 最新国产乱人伦偷精品免费网站| 欧美又大又粗又长| 一卡二卡三卡在线观看| 国产乱码精品一区二区三区av| 国产精品久久久久久久久久久久冷| 婷婷国产在线| 综合久久综合久久| 精品国产一二三四区| 日韩中文在线播放| 日韩美一区二区三区| 国产艳俗歌舞表演hd| 国产精品国内免费一区二区三区| 久久久久久av| 这里只有精品999| 成人小视频免费观看| 香蕉久久免费影视| 丁香花在线电影| 欧美日韩亚洲综合| 中文在线永久免费观看| 日韩大片在线观看| 97视频在线播放| 国产精品无码免费播放| 久久精品亚洲一区二区三区浴池 | 日韩欧美电影一区| 亚洲av无码一区二区三区人| 欧美人成在线| 国产精品女人网站| 亚洲人妻一区二区三区| 亚洲男同性视频| 别急慢慢来1978如如2| 91欧美极品| 精品国内产的精品视频在线观看| 中文字幕av影院| 成人一区二区三区| 久久av秘一区二区三区| se01亚洲视频| 亚洲精品久久7777777| 亚洲天堂黄色片| 强制捆绑调教一区二区| 精品国产乱码久久久久久108| jizz性欧美| 欧美日韩情趣电影| 在线观看国产精品一区| 国产日韩一区二区三区在线播放 | 欧美激情理论| 国产精品久久久久久亚洲调教| 手机看片1024国产| 亚洲一区视频在线观看视频| 激情五月婷婷基地| 日韩av专区| 国产精品视频永久免费播放| 欧洲毛片在线| 福利微拍一区二区| 超碰97在线资源站| 99国产精品久久久久久久 | 国产精品欧美三级在线观看| 高清欧美性猛交xxxx| 亚洲精品一级片| 一区二区三区精品在线| 韩国三级与黑人| 欧美成人久久| av日韩中文字幕| 男女在线视频| 精品成人免费观看| 国产精品成人av久久| 成人18视频日本| 自拍日韩亚洲一区在线| 偷拍自拍亚洲色图| 日韩美女av在线免费观看| 久久久久久女乱国产| 色婷婷精品大在线视频| 国产精品久久久久久久av| 日本美女一区二区三区视频| 亚洲一区二区在线免费观看| 成人福利片在线| 久久精品人人做人人爽| 国产婷婷一区二区三区久久| 亚洲资源在线观看| 人人妻人人澡人人爽人人精品| 免费亚洲视频| 亚洲高清在线观看一区| 2020国产精品小视频| 欧美日韩第一页| 天天干天天舔天天射| 一本一道久久a久久精品综合蜜臀 一本一道综合狠狠老 | 日本激情视频一区二区三区| 极品尤物av久久免费看| 国产在线xxxx| 亚洲精品一级二级三级| 国产精品第一区| 性网站在线观看| 亚洲老头老太hd| 一级做a爱片性色毛片| 亚洲大片免费看| 国产特级黄色录像| 麻豆久久久久久久| 国产精品一色哟哟| 精品久久精品| 97自拍视频| 厕沟全景美女厕沟精品| 日韩在线观看成人| 欧美在线精品一区二区三区| 91久久精品一区二区二区| 国产精品精品软件男同| 99久久精品免费看国产| 一本久道中文无码字幕av| 91综合在线| 久草热久草热线频97精品| 欧美一区=区三区| 992tv在线成人免费观看| 在线激情网站| 国产视频久久久久| 国产色视频在线| 福利一区视频在线观看| 日本高清一二三区| 久久精品人人爽人人爽| 91福利视频免费观看| 日韩精品视频网| h无码动漫在线观看| 欧美综合另类| 精品一区日韩成人| 国产视频一区二| 国产精品成人播放| 久草在线资源站手机版| 久久国产精品99国产精| 欧美精品a∨在线观看不卡 | 欧美成人高清| 亚洲国产欧美一区二区三区不卡| 高清日韩中文字幕| 成人激情黄色网| 日韩毛片在线| 欧美在线xxx| 高h视频在线播放| 日韩视频中文字幕| 玖玖综合伊人| 亚洲美女精品成人在线视频| 欧美性受xxxx狂喷水| 91精品国产一区二区三区| 艳妇乳肉豪妇荡乳av无码福利| 亚洲aⅴ怡春院| 欧美日韩精品在线观看视频| 中文字幕不卡的av| 日本激情小视频| 91亚洲国产成人精品一区二区三 | 欧美性猛交xxxx乱大交91| 日韩激情av在线| 丝袜老师办公室里做好紧好爽| 亚洲无线一线二线三线区别av| 强开小嫩苞一区二区三区网站| 成人在线亚洲| 亚洲人成人77777线观看| 精品国产一区探花在线观看| 欧洲一区二区在线观看| 婷婷国产精品| 久久久久久草| 日本欧美三级| 免费国产一区二区| 妖精视频一区二区三区| 久久国产一区| 亚洲宅男一区| 欧美一区二区视频17c| 在线日本制服中文欧美| 免费一区二区三区| 精品久久影院| 亚洲一区二区三区精品在线观看| 大色综合视频网站在线播放| 亚洲不卡1区| 狠狠色狠狠色综合婷婷tag| 欧美激情论坛| 精品国产一区二区三区四区| 亚洲国产精品一区二区第一页| 日韩欧美中文| 亚洲啊啊啊啊啊| 亚洲午夜久久久久久尤物| 日韩xxxx视频| 午夜在线一区| 日本成人黄色网| 久久91精品久久久久久秒播| 91插插插影院| 成人毛片视频在线观看| 成人h动漫精品一区| 国产调教视频一区| 免费黄色激情视频| 亚洲另类春色国产| 好吊操这里只有精品| 精品国产乱码久久久久酒店| 欧美精品韩国精品| 欧美日韩国产美| www.国产精品视频| 日韩精品在线免费观看| 77777影视视频在线观看| 久久精品久久久久电影| 91av久久| 国产日韩欧美视频在线| 国产福利资源一区| 日韩国产一区久久| 欧美激情视频一区二区三区在线播放| 亚洲色成人www永久在线观看| 麻豆9191精品国产| 手机av在线网| 99精品欧美一区二区三区小说 | 一区二区三区四区激情| 日韩黄色一级大片| 欧美日韩国产美女| 少妇一区二区三区四区| 中文字幕亚洲欧美| 秋霞在线午夜| 国产精品视频久久| 老牛影视av一区二区在线观看| 色噜噜狠狠一区二区三区| 欧美777四色影| 色七七在线观看| 大美女一区二区三区| 变态另类ts人妖一区二区| 亚洲免费观看高清| 日本成人一级片| 亚洲福利视频久久| 黄色网址在线免费播放| 欧美在线免费看| 久久九九精品视频| 日韩三级电影| 一本色道久久综合亚洲精品不卡| 亚洲国产日韩欧美在线观看| 成人18视频日本| 538精品在线视频| 91成人在线免费观看| 男人天堂一区二区| 久久精品国产免费观看| 欧美一级大片| 精品欧美国产| 在线精品一区| 亚洲精品乱码久久久久久9色| 中文字幕第一区| 黄色污污网站在线观看| 亚洲国产天堂久久综合| 中文字幕在线播放网址| 国产精品香蕉av| 校园春色另类视频| 男女日批视频在线观看| 国产精品 欧美精品| 成人黄色短视频| 欧美日韩一区 二区 三区 久久精品| 亚洲aⅴ乱码精品成人区| 久久久国产在线视频| jizz久久久久久| 日韩久久在线| 老司机午夜免费精品视频 | 丰满人妻妇伦又伦精品国产 | 日本乱码一区二区三区不卡| 99高清视频有精品视频| 一区二区三区中文| 久久精品视频在线观看免费| 国产精品伦理在线| 最近中文字幕免费观看| 在线观看免费高清视频97| 欧美xxxx做受欧美护士| 欧洲精品码一区二区三区免费看| 亚洲一区国产| 动漫精品一区二区三区| 欧美体内谢she精2性欧美| 午夜一区在线观看| 欧美性在线观看| 国产欧美一区二区精品久久久| 国产精品亚洲αv天堂无码| 久久影院电视剧免费观看| 欧美日韩一二三四区| 亚洲免费av网址| 欧美黄色三级| 亚洲人成网站在线播放2019| 久久99精品国产麻豆不卡| 国产在线观看免费视频软件| 欧美日韩国产成人在线91| 免费在线看黄网站| 亚洲一区亚洲二区亚洲三区| 欧美午夜电影在线观看| 中文字幕第九页| 福利二区91精品bt7086| 国产三级视频在线播放线观看| 国产欧美日韩中文| 一区二区电影| 免费a v网站| 欧美香蕉大胸在线视频观看 | 久久99精品久久久久久噜噜| 久久视频免费| 亚洲国产精品成人天堂| 久久综合九色综合欧美亚洲| 欧美 亚洲 另类 激情 另类| 精品国产一区二区在线 | 日本成人三级电影网站| 蜜臀久久99精品久久久久宅男| 国产极品美女在线| 欧美精品一区二区三区视频| 超碰国产一区| 国产精品8888| 久久免费电影网| 国产乱码久久久| 68精品久久久久久欧美| 菠萝蜜一区二区| 美女日批在线观看| 一本大道久久精品懂色aⅴ| 日本视频在线免费观看| 翡翠波斯猫1977年美国| 日本在线不卡视频一二三区| 欧美大片xxxx| 亚洲欧美中文日韩在线| 性欧美video另类hd尤物| 欧美 日韩 亚洲 一区| 中文无字幕一区二区三区| www.亚洲天堂.com| 日韩免费在线播放| 欧美激情自拍| 在线观看亚洲大片短视频| 精品国产一区二区三区四区四| 国产综合色区在线观看| avav在线播放| 亚洲欧洲精品一区二区三区 | 国产普通话bbwbbwbbw|