国产精品电影_久久视频免费_欧美日韩国产激情_成年人视频免费在线播放_日本久久亚洲电影_久久都是精品_66av99_九色精品美女在线_蜜臀a∨国产成人精品_冲田杏梨av在线_欧美精品在线一区二区三区_麻豆mv在线看

Go中的內(nèi)聯(lián)優(yōu)化

開(kāi)發(fā) 后端
本文討論 Go 編譯器是如何實(shí)現(xiàn)內(nèi)聯(lián)的,以及這種優(yōu)化方法如何影響你的 Go 代碼。

[[324890]]

本文討論 Go 編譯器是如何實(shí)現(xiàn)內(nèi)聯(lián)的,以及這種優(yōu)化方法如何影響你的 Go 代碼。

請(qǐng)注意:本文重點(diǎn)討論 gc,這是來(lái)自 golang.org 的事實(shí)標(biāo)準(zhǔn)的 Go 編譯器。討論到的概念可以廣泛適用于其它 Go 編譯器,如 gccgo 和 llgo,但它們?cè)趯?shí)現(xiàn)方式和功效上可能有所差異。

內(nèi)聯(lián)是什么?

內(nèi)聯(lián)inlining就是把簡(jiǎn)短的函數(shù)在調(diào)用它的地方展開(kāi)。在計(jì)算機(jī)發(fā)展歷程的早期,這個(gè)優(yōu)化是由程序員手動(dòng)實(shí)現(xiàn)的。現(xiàn)在,內(nèi)聯(lián)已經(jīng)成為編譯過(guò)程中自動(dòng)實(shí)現(xiàn)的基本優(yōu)化過(guò)程的其中一步。

為什么內(nèi)聯(lián)很重要?

有兩個(gè)原因。第一個(gè)是它消除了函數(shù)調(diào)用本身的開(kāi)銷(xiāo)。第二個(gè)是它使得編譯器能更高效地執(zhí)行其他的優(yōu)化策略。

函數(shù)調(diào)用的開(kāi)銷(xiāo)

在任何語(yǔ)言中,調(diào)用一個(gè)函數(shù) 1 都會(huì)有消耗。把參數(shù)編組進(jìn)寄存器或放入棧中(取決于 ABI),在返回結(jié)果時(shí)的逆反過(guò)程都會(huì)有開(kāi)銷(xiāo)。引入一次函數(shù)調(diào)用會(huì)導(dǎo)致程序計(jì)數(shù)器從指令流的一點(diǎn)跳到另一點(diǎn),這可能導(dǎo)致管道滯后。函數(shù)內(nèi)部通常有前置處理preamble,需要為函數(shù)執(zhí)行準(zhǔn)備新的棧幀,還有與前置相似的后續(xù)處理epilogue,需要在返回給調(diào)用方之前釋放棧幀空間。

在 Go 中函數(shù)調(diào)用會(huì)消耗額外的資源來(lái)支持棧的動(dòng)態(tài)增長(zhǎng)。在進(jìn)入函數(shù)時(shí),goroutine 可用的棧空間與函數(shù)需要的空間大小進(jìn)行比較。如果可用空間不同,前置處理就會(huì)跳到運(yùn)行時(shí)runtime的邏輯中,通過(guò)把數(shù)據(jù)復(fù)制到一塊新的、更大的空間的來(lái)增長(zhǎng)棧空間。當(dāng)這個(gè)復(fù)制完成后,運(yùn)行時(shí)就會(huì)跳回到原來(lái)的函數(shù)入口,再執(zhí)行棧空間檢查,現(xiàn)在通過(guò)了檢查,函數(shù)調(diào)用繼續(xù)執(zhí)行。這種方式下,goroutine 開(kāi)始時(shí)可以申請(qǐng)很小的棧空間,在有需要時(shí)再申請(qǐng)更大的空間。2

這個(gè)檢查消耗很小,只有幾個(gè)指令,而且由于 goroutine 的棧是成幾何級(jí)數(shù)增長(zhǎng)的,因此這個(gè)檢查很少失敗。這樣,現(xiàn)代處理器的分支預(yù)測(cè)單元可以通過(guò)假定檢查肯定會(huì)成功來(lái)隱藏棧空間檢查的消耗。當(dāng)處理器預(yù)測(cè)錯(cuò)了棧空間檢查,不得不放棄它在推測(cè)性執(zhí)行所做的操作時(shí),與為了增加 goroutine 的棧空間運(yùn)行時(shí)所需的操作消耗的資源相比,管道滯后的代價(jià)更小。

雖然現(xiàn)代處理器可以用預(yù)測(cè)性執(zhí)行技術(shù)優(yōu)化每次函數(shù)調(diào)用中的泛型和 Go 特定的元素的開(kāi)銷(xiāo),但那些開(kāi)銷(xiāo)不能被完全消除,因此在每次函數(shù)調(diào)用執(zhí)行必要的工作過(guò)程中都會(huì)有性能消耗。一次函數(shù)調(diào)用本身的開(kāi)銷(xiāo)是固定的,與更大的函數(shù)相比,調(diào)用小函數(shù)的代價(jià)更大,因?yàn)樵诿看握{(diào)用過(guò)程中它們做的有用的工作更少。

因此,消除這些開(kāi)銷(xiāo)的方法必須是要消除函數(shù)調(diào)用本身,Go 的編譯器就是這么做的,在某些條件下通過(guò)用函數(shù)的內(nèi)容來(lái)替換函數(shù)調(diào)用來(lái)實(shí)現(xiàn)。這個(gè)過(guò)程被稱(chēng)為內(nèi)聯(lián),因?yàn)樗诤瘮?shù)調(diào)用處把函數(shù)體展開(kāi)了。

改進(jìn)的優(yōu)化機(jī)會(huì)

Cliff Click 博士把內(nèi)聯(lián)描述為現(xiàn)代編譯器做的優(yōu)化措施,像常量傳播(LCTT 譯注:此處作者筆誤,原文為 constant proportion,修正為 constant propagation)和死代碼消除一樣,都是編譯器的基本優(yōu)化方法。實(shí)際上,內(nèi)聯(lián)可以讓編譯器看得更深,使編譯器可以觀(guān)察調(diào)用的特定函數(shù)的上下文內(nèi)容,可以看到能繼續(xù)簡(jiǎn)化或徹底消除的邏輯。由于可以遞歸地執(zhí)行內(nèi)聯(lián),因此不僅可以在每個(gè)獨(dú)立的函數(shù)上下文處進(jìn)行這種優(yōu)化決策,也可以在整個(gè)函數(shù)調(diào)用鏈中進(jìn)行。

實(shí)踐中的內(nèi)聯(lián)

下面這個(gè)例子可以演示內(nèi)聯(lián)的影響:

  1. package main
  2.  
  3. import "testing"
  4.  
  5. //go:noinline
  6. func max(a, b int) int {
  7. if a > b {
  8. return a
  9. }
  10. return b
  11. }
  12.  
  13. var Result int
  14.  
  15. func BenchmarkMax(b *testing.B) {
  16. var r int
  17. for i := 0; i < b.N; i++ {
  18. r = max(-1, i)
  19. }
  20. Result = r
  21. }

運(yùn)行這個(gè)基準(zhǔn),會(huì)得到如下結(jié)果:3

  1. % go test -bench=.
  2. BenchmarkMax-4 530687617 2.24 ns/op

在我的 2015 MacBook Air 上 max(-1, i) 的耗時(shí)約為 2.24 納秒。現(xiàn)在去掉 //go:noinline 編譯指令,再看下結(jié)果:

  1. % go test -bench=.
  2. BenchmarkMax-4 1000000000 0.514 ns/op

從 2.24 納秒降到了 0.51 納秒,或者從 benchstat 的結(jié)果可以看出,有 78% 的提升。

  1. % benchstat {old,new}.txt
  2. name old time/op new time/op delta
  3. Max-4 2.21ns ± 1% 0.49ns ± 6% -77.96% (p=0.000 n=18+19)

這個(gè)提升是從哪兒來(lái)的呢?

首先,移除掉函數(shù)調(diào)用以及與之關(guān)聯(lián)的前置處理 4 是主要因素。把 max 函數(shù)的函數(shù)體在調(diào)用處展開(kāi),減少了處理器執(zhí)行的指令數(shù)量并且消除了一些分支。

現(xiàn)在由于編譯器優(yōu)化了 BenchmarkMax,因此它可以看到 max 函數(shù)的內(nèi)容,進(jìn)而可以做更多的提升。當(dāng) max 被內(nèi)聯(lián)后,BenchmarkMax 呈現(xiàn)給編譯器的樣子,看起來(lái)是這樣的:

  1. func BenchmarkMax(b *testing.B) {
  2. var r int
  3. for i := 0; i < b.N; i++ {
  4. if -1 > i {
  5. r = -1
  6. } else {
  7. r = i
  8. }
  9. }
  10. Result = r
  11. }

再運(yùn)行一次基準(zhǔn),我們看一下手動(dòng)內(nèi)聯(lián)的版本和編譯器內(nèi)聯(lián)的版本的表現(xiàn):

  1. % benchstat {old,new}.txt
  2. name old time/op new time/op delta
  3. Max-4 2.21ns ± 1% 0.48ns ± 3% -78.14% (p=0.000 n=18+18)

現(xiàn)在編譯器能看到在 BenchmarkMax 里內(nèi)聯(lián) max 的結(jié)果,可以執(zhí)行以前不能執(zhí)行的優(yōu)化措施。例如,編譯器注意到 i 初始值為 0,僅做自增操作,因此所有與 i 的比較都可以假定 i 不是負(fù)值。這樣條件表達(dá)式 -1 > i 永遠(yuǎn)不是 true5

證明了 -1 > i 永遠(yuǎn)不為 true 后,編譯器可以把代碼簡(jiǎn)化為:

  1. func BenchmarkMax(b *testing.B) {
  2. var r int
  3. for i := 0; i < b.N; i++ {
  4. if false {
  5. r = -1
  6. } else {
  7. r = i
  8. }
  9. }
  10. Result = r
  11. }

并且因?yàn)榉种Ю锸莻€(gè)常量,編譯器可以通過(guò)下面的方式移除不會(huì)走到的分支:

  1. func BenchmarkMax(b *testing.B) {
  2. var r int
  3. for i := 0; i < b.N; i++ {
  4. r = i
  5. }
  6. Result = r
  7. }

這樣,通過(guò)內(nèi)聯(lián)和由內(nèi)聯(lián)解鎖的優(yōu)化過(guò)程,編譯器把表達(dá)式 r = max(-1, i)) 簡(jiǎn)化為 r = i

內(nèi)聯(lián)的限制

本文中我論述的內(nèi)聯(lián)稱(chēng)作葉子內(nèi)聯(lián)leaf inlining:把函數(shù)調(diào)用棧中最底層的函數(shù)在調(diào)用它的函數(shù)處展開(kāi)的行為。內(nèi)聯(lián)是個(gè)遞歸的過(guò)程,當(dāng)把函數(shù)內(nèi)聯(lián)到調(diào)用它的函數(shù) A 處后,編譯器會(huì)把內(nèi)聯(lián)后的結(jié)果代碼再內(nèi)聯(lián)到 A 的調(diào)用方,這樣持續(xù)內(nèi)聯(lián)下去。例如,下面的代碼:

  1. func BenchmarkMaxMaxMax(b *testing.B) {
  2. var r int
  3. for i := 0; i < b.N; i++ {
  4. r = max(max(-1, i), max(0, i))
  5. }
  6. Result = r
  7. }

與之前的例子中的代碼運(yùn)行速度一樣快,因?yàn)榫幾g器可以對(duì)上面的代碼重復(fù)地進(jìn)行內(nèi)聯(lián),也把代碼簡(jiǎn)化到 r = i 表達(dá)式。

下一篇文章中,我會(huì)論述當(dāng) Go 編譯器想要內(nèi)聯(lián)函數(shù)調(diào)用棧中間的某個(gè)函數(shù)時(shí)選用的另一種內(nèi)聯(lián)策略。最后我會(huì)論述編譯器為了內(nèi)聯(lián)代碼準(zhǔn)備好要達(dá)到的極限,這個(gè)極限 Go 現(xiàn)在的能力還達(dá)不到。 

責(zé)任編輯:龐桂玉 來(lái)源: Linux中國(guó)
相關(guān)推薦

2020-05-06 20:40:03

Go編程語(yǔ)言

2023-11-21 08:03:43

語(yǔ)言架構(gòu)偏移量

2010-03-22 14:58:35

2021-08-13 09:06:52

Go高性能優(yōu)化

2010-09-08 17:11:29

CSS塊元素CSS內(nèi)聯(lián)元素

2021-06-08 07:45:44

Go語(yǔ)言優(yōu)化

2023-11-20 09:57:03

內(nèi)聯(lián)函數(shù)C++

2023-09-12 11:10:00

代碼優(yōu)化Go

2023-12-30 18:35:37

Go識(shí)別應(yīng)用程序

2021-08-04 09:33:22

Go 性能優(yōu)化

2023-05-09 11:02:22

Go內(nèi)聯(lián)版本

2011-06-21 11:05:41

內(nèi)聯(lián)函數(shù)

2024-01-15 11:12:28

Go內(nèi)存開(kāi)發(fā)

2022-02-14 08:04:02

Go語(yǔ)法糖編譯器

2022-07-19 08:01:55

函數(shù)Go格式化

2025-05-22 09:01:28

2016-09-22 09:37:14

GCC內(nèi)聯(lián)語(yǔ)法

2024-12-04 11:31:41

Go編程技巧

2021-09-01 07:21:46

堆棧Gopanic

2022-06-13 07:03:25

Go 語(yǔ)言怎么優(yōu)化重
點(diǎn)贊
收藏

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

国产日韩欧美夫妻视频在线观看| 欧美色图五月天| 国产女主播一区二区| 欧美日韩一区在线观看| 激情图片小说一区| 成人系列视频| 成人午夜大片| 红杏视频成人| 久久国产成人精品| 夜夜嗨av一区二区三区网站四季av| 免费精品视频在线| 成人精品在线视频观看| 欧美日韩在线观看一区二区 | 亚洲国产中文字幕| 亚洲精品电影网| 成人免费大片黄在线播放| 欧美精品自拍视频| 日韩av毛片| 色就是色亚洲色图| 啪啪免费视频一区| 日韩精品一区二区三区中文| 欧美日韩伊人| 秋霞影院一区二区三区| 激情伊人五月天久久综合| 日韩av网址在线| 热99这里只有精品| 欧美成人片在线| 外国成人激情视频| 精品国产露脸精彩对白| 成人一区二区av| 美女网站色精品尤物极品姐弟| 美女一区二区视频| 国产精品久久久久久久久久免费看| 欧美日韩成人精品| 欧美少妇一级片| 国产美女av在线| 蜜臀久久99精品久久久久久9 | 韩国成人精品a∨在线观看| 亚洲成人激情av| 欧美肥臀大乳一区二区免费视频| 男同互操gay射视频在线看| 波多野结衣中文在线| av中文字幕一区| 亚洲精品www久久久| 黄p免费网站| 伊人在我在线看导航| 国产最新精品免费| 青青久久aⅴ北条麻妃| 91色p视频在线| 黑人精品xxx一区一二区| 国内免费精品永久在线视频| 丝袜老师办公室里做好紧好爽 | 亚洲女人被黑人巨大进入| 99.玖玖.com| 欧美日韩mv| 欧美日韩日日摸| 久久久成人精品一区二区三区| 2024短剧网剧在线观看| 国产激情精品久久久第一区二区 | 欧美成人合集magnet| 91短视频在线| 99久精品视频在线观看视频| 福利精品视频在线| 日韩妆和欧美的一区二区| 欧美色网一区| 国产成人h网站| 亚洲精品电影网在线观看| 日韩在线三区| 91精品影视| 国产亚洲综合在线| 欧洲成人免费aa| 成人性a激情免费视频| 狠狠一区二区三区| 久久综合99re88久久爱| 日韩精品免费在线播放| 日韩av在线一区二区三区| av网站在线免费看推荐| 快she精品国产999| 亚洲国产精品久久| 精品一区在线| 欧美日韩直播| 欧美电影免费网站| 偷拍一区二区| 国产一区二区精品福利地址| 国内精品久久久久久久影视简单| 欧美自拍一区| 欧美午夜精彩| 亚洲国产精品91| 国内一区二区三区| 日韩一级欧洲| 日本亚洲最大的色成网站www| 日本不卡的三区四区五区| 日韩不卡手机在线v区| 九色综合国产一区二区三区| 国产v日产∨综合v精品视频| 久久蜜桃av一区精品变态类天堂| 中文字幕第一区二区| 亚洲精品伦理在线| 色综合中文字幕国产| 在线播放中文字幕一区| 亚洲国产精彩中文乱码av| 亚洲日本欧美中文幕| 久久中文字幕国产| 欧美最猛性xxxxx免费| 成人天堂噜噜噜| 久久偷窥视频| 欧美日韩中文字幕在线播放| 亚洲人成色77777| 久草福利资源在线视频| 日韩国产福利| 黄视频在线免费看| 国产资源一区| 蜜桃国内精品久久久久软件9| 国产精品jvid在线观看蜜臀| 国产999精品在线观看| 7777精品久久久大香线蕉| 午夜肉伦伦影院| 蜜臀av国产精品久久久久| 午夜伦伦电影理论片费看 | 亚洲a区在线视频| 日韩免费视频在线观看| 91久久夜色精品国产网站| 韩国一区二区三区美女美女秀| 欧美午夜免费| heyzo亚洲| 麻豆电影传媒二区| 午夜看片在线免费| 中文字幕av一区二区三区佐山爱| 99精品在免费线中文字幕网站一区 | 老头吃奶性行交视频| 日本调教视频在线观看| av影片免费在线观看| 欧美人体一区二区三区| 免费日韩一区二区三区| 亚洲国产mv| 国产91精品在线观看| 一区二区三区中文在线| 欧美一区二区三区在线观看| 在线精品视频视频中文字幕| 国产精品91免费在线| 日韩福利在线| 日本久久久久久久久久久久| 国产中文字幕在线观看| 亚洲精品88| 精品国产aⅴ| 蜜桃视频一区二区三区在线观看| 国产精品午夜免费| 91精品国产麻豆| 欧美极品第一页| 日韩高清a**址| 粉嫩av一区二区三区四区五区| 欧美精品视频www在线观看| 欧美高清在线一区二区| 精品女厕一区二区三区| 亚洲美女在线视频| 国产精品jizz在线观看麻豆| 日本一区二区在线| 成人免费在线观看视频网站| 在线观看精品一区二区三区| 日韩精品一区二区三区中文字幕 | 色爱av综合网| 国产欧美在线一区二区| 91精品国产乱码久久久久久久| 欧美性视频精品| 天天影视欧美综合在线观看| 欧美韩国理论所午夜片917电影| 神马午夜伦理不卡 | 视频一区二区三| 国产综合色产在线精品| 成人深夜直播免费观看| 国产探花一区二区| 国产精品都在这里| 欧美综合久久| 精品在线你懂的| 欧美极品欧美精品欧美| 国产成人免费在线视频| 最近中文字幕免费mv| 国产一区啦啦啦在线观看| 欧美一级视频免费看| 91免费小视频| 成人淫片免费视频95视频| 国产精品污网站| 一本大道香蕉久久| 欧美三级三级三级| 成人免费观看在线观看| 自拍亚洲一区欧美另类| 99亚洲乱人伦aⅴ精品| 国产精品h片在线播放| 欧美黄色精品| 一区二区不卡在线观看| 福利一区福利二区| 91在线最新| 欧美日韩在线观看一区二区| 搜成人激情视频| 日韩mv欧美mv国产网站| 影院欧美亚洲| 91亚洲国产| 精品国产不卡一区二区三区| 国产丝袜视频在线播放| 欧美肥臀大乳一区二区免费视频|