在线观看www成人影院-在线观看www日本免费网站-在线观看www视频-在线观看操-欧美18在线-欧美1级

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

初探Golang內(nèi)聯(lián)

Linux愛好者 ? 來源:稀土掘金技術(shù)社區(qū) ? 作者:ag9920 ? 2022-12-13 09:51 ? 次閱讀

開篇

今天我們來聊聊 Golang 中的內(nèi)聯(lián)。

我們知道,函數(shù)調(diào)用本身是存在成本的。如果把一個實(shí)際調(diào)用的函數(shù)產(chǎn)生的指令,直接插入到的位置,來替換對應(yīng)的函數(shù)調(diào)用指令。就可以消除掉這部分性能損耗。但同時也要注意,我們需要維護(hù)各個模塊的可讀性,需要保證高內(nèi)聚,低耦合,不可能把所有邏輯合到一個函數(shù),這樣可讀性大大降低。

那么,既然在代碼層面做不太好,還有沒有別的招呢?

內(nèi)聯(lián)就是來做這件事的。下面我們一起來看一下。

內(nèi)聯(lián)

所謂內(nèi)聯(lián),指的是編譯期間,直接將調(diào)用函數(shù)的地方替換為函數(shù)的實(shí)現(xiàn),它可以減少函數(shù)調(diào)用的開銷以提高程序的性能。內(nèi)聯(lián)函數(shù)是直接復(fù)制“鑲嵌”到主函數(shù)中去的,就是將內(nèi)聯(lián)函數(shù)的代碼直接放在內(nèi)聯(lián)函數(shù)的位置上,

這與一般函數(shù)不同,主函數(shù)在調(diào)用一般函數(shù)的時候,是指令跳轉(zhuǎn)到被調(diào)用函數(shù)的入口地址,執(zhí)行完被調(diào)用函數(shù)后,指令再跳轉(zhuǎn)回主函數(shù)上繼續(xù)執(zhí)行后面的代碼;而由于內(nèi)聯(lián)函數(shù)是將函數(shù)的代碼直接放在了函數(shù)的位置上,所以沒有指令跳轉(zhuǎn),指令按順序執(zhí)行。Go程序編譯時,默認(rèn)將進(jìn)行內(nèi)聯(lián)優(yōu)化。

當(dāng)然,內(nèi)聯(lián)也并不是沒有代價,這本質(zhì)是一種以空間換時間的優(yōu)化方法,其帶來的優(yōu)點(diǎn)是使CPU需要執(zhí)行的指令數(shù)變少了,不需要根據(jù)地址跳轉(zhuǎn)的過程了,不用壓棧和出棧的過程了,我們把可以復(fù)用的程序指令在調(diào)用它的地方完全展開了。如果一個函數(shù)在很多地方都被調(diào)用了,那么就會展開很多次,整個程序占用的空間就會變大了。

需要注意,內(nèi)聯(lián)也是有門檻的,并不是隨便一個函數(shù)調(diào)用都可以原地替換。Golang 編譯器內(nèi)部會有一套自己的判斷規(guī)則,判斷一次函數(shù)調(diào)用能否被內(nèi)聯(lián),后面的章節(jié)我們會提到。這也是為什么我們會說:

Inlining is the act of combining smaller functions into their respective callers.

這個 small 的程度很關(guān)鍵。

簡單小結(jié)一下,內(nèi)聯(lián)帶來的好處有兩個:

解除函數(shù)調(diào)用的開銷,以空間換時間;

支持編譯器更有效地應(yīng)用其他優(yōu)化策略。

函數(shù)調(diào)用開銷

一個goroutine會有一個單獨(dú)的棧,棧又會包含多個棧幀,棧幀是函數(shù)調(diào)用時在棧上為函數(shù)所分配的區(qū)域。函數(shù)調(diào)用存在一些固定開銷:

創(chuàng)建棧幀;

讀寫寄存器;

棧溢出檢測。

內(nèi)聯(lián)什么時候最有效

函數(shù)執(zhí)行的開銷 vs 函數(shù)調(diào)用的開銷。這兩個開銷的比值會很大程度上決定【內(nèi)聯(lián)】的效果。

內(nèi)聯(lián)其實(shí)就是把函數(shù)調(diào)用這份固定開銷給消除了,所以尤其對于函數(shù)體極其簡單的函數(shù)有效果。如果你的函數(shù)執(zhí)行了一系列復(fù)雜邏輯,開銷遠(yuǎn)超【函數(shù)調(diào)用】本身,這里的優(yōu)化就微不足道了。

內(nèi)聯(lián)雖然可以減少函數(shù)調(diào)用的開銷,但是也可能因?yàn)榇嬖谥貜?fù)代碼,從而導(dǎo)致 CPU 緩存命中率降低,所以并不能盲目追求過度的內(nèi)聯(lián),需要結(jié)合 profile 結(jié)果來具體分析。

Golang 編譯器對內(nèi)聯(lián)的要求

參考官方 wiki:github.com/golang/go/w…[1]

a2e89d80-77b3-11ed-8abf-dac502259ad0.jpg

想要內(nèi)聯(lián),方法本身必須滿足以下條件:

函數(shù)足夠簡單,當(dāng)解析AST時,Go申請了80個節(jié)點(diǎn)作為內(nèi)聯(lián)的預(yù)算。每個節(jié)點(diǎn)都會消耗一個預(yù)算。函數(shù)的開銷不能超過這個預(yù)算;

不能包含閉包,defer,recover,select;

不能以 go:noinline 或 go:unitptrescapes 開頭;

必須有函數(shù)體;

其他等復(fù)雜要求,詳細(xì)可見src/cmd/compile/internal/gc/inl.go相關(guān)內(nèi)容。我們可以使用 gcflags 參數(shù)來判斷能不能內(nèi)聯(lián)。

內(nèi)聯(lián)的實(shí)現(xiàn)原理建議大家看看這篇文章:gocompiler.shizhz.me/8.-golang-b…[2]

如何禁止內(nèi)聯(lián)

單個函數(shù)級別:在函數(shù)定義前一行添加//go:noinline;

全局編譯級別:可通過-gcflags="-l"選項(xiàng)全局禁用內(nèi)聯(lián),與一個-l禁用內(nèi)聯(lián)相反,如果傳遞兩個或兩個以上的-l則會打開內(nèi)聯(lián),并啟用更激進(jìn)的內(nèi)聯(lián)策略。

gcflags

go build 時可以使用 -gcflags 指定編譯選項(xiàng),-gcflags 參數(shù)的格式是:

-gcflags="pattern=arg list"

pattern 是選擇包的模式,arg list 是空格分割的編譯選項(xiàng),如果編譯選項(xiàng)中含有空格,可以使用引號包起來。

如:-gcflags="all=-N -l" 代表的是表示主模塊和它所有的依賴都禁用【編譯器優(yōu)化】和【內(nèi)聯(lián)】。更多編譯選項(xiàng)參照 go tool compile --help

Use -gcflags -m to observe the result of escape analysis and inlining decisions for the gc toolchain.

使用 go build 編譯時,我們可以使用參數(shù)-gflags="-m"運(yùn)行,可顯示被內(nèi)聯(lián)的函數(shù),使用運(yùn)行參數(shù)-gflags="-m -m"可以看到原因。類似:

./main.go:14:6:cannotinlinexxx:unhandledopXXX

/ins.go:9:6:cannotinlinexxx:functiontoocomplex:cost104exceedsbudget80

我們可以用下面的命令分析變量是否逃逸:

gorun-gcflags'-m-l'main.go

-m 其實(shí)是打印優(yōu)化策略的語義,實(shí)際上最多總共可以用 4 個 -m,但是信息量較大,一般用 1 個就可以了;

-l 會禁用函數(shù)內(nèi)聯(lián),在這里禁用掉內(nèi)聯(lián)能更好的觀察逃逸情況,減少干擾

內(nèi)聯(lián)后堆棧信息還對不對

內(nèi)聯(lián)會將函數(shù)調(diào)用的過程抹掉,這會引入一個新的問題:代碼的堆棧信息還能否保證。其實(shí)這一點(diǎn)不用擔(dān)心,Golang 內(nèi)部會為每個存在內(nèi)聯(lián)優(yōu)化的 goroutine 維持一個內(nèi)聯(lián)樹(inlining tree),該樹可通過 -gcflags="-d pctab=pctoinline" 命令查看,Go在生成的代碼中映射了內(nèi)聯(lián)函數(shù)。并且,也映射了行號。這張表被嵌入到了二進(jìn)制文件中,所以在運(yùn)行時可以得到準(zhǔn)確的堆棧信息。

審核編輯:湯梓紅

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報投訴
  • 寄存器
    +關(guān)注

    關(guān)注

    31

    文章

    5392

    瀏覽量

    121935
  • 函數(shù)
    +關(guān)注

    關(guān)注

    3

    文章

    4355

    瀏覽量

    63322
  • 編譯器
    +關(guān)注

    關(guān)注

    1

    文章

    1645

    瀏覽量

    49480

原文標(biāo)題:初探 Golang 內(nèi)聯(lián)

文章出處:【微信號:LinuxHub,微信公眾號:Linux愛好者】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。

收藏 人收藏

    評論

    相關(guān)推薦

    Golang接口的作用和應(yīng)用場景

    Golang(Go)作為一門現(xiàn)代的靜態(tài)類型編程語言,提供了許多強(qiáng)大的特性,其中之一便是接口(interface)。接口是Golang中的一個核心概念,它具有廣泛的應(yīng)用場景,可以幫助開發(fā)者實(shí)現(xiàn)
    的頭像 發(fā)表于 12-05 10:44 ?1250次閱讀

    如何使用Golang連接MySQL

    首先我們來看如何使用Golang連接MySQL。
    的頭像 發(fā)表于 01-08 09:42 ?3524次閱讀
    如何使用<b class='flag-5'>Golang</b>連接MySQL

    Golang怎么實(shí)現(xiàn)UTS隔離

    Golang實(shí)現(xiàn)UTS隔離
    發(fā)表于 08-23 14:44

    基于SUIF的函數(shù)內(nèi)聯(lián)技術(shù)

    從基于調(diào)用圖的函數(shù)內(nèi)聯(lián)技術(shù)、函數(shù)參數(shù)的映射技術(shù)和內(nèi)聯(lián)使用的不同策略3 個方面討論基于SUIF 系統(tǒng)的內(nèi)聯(lián)技術(shù)的實(shí)現(xiàn)。根據(jù)KAP 系統(tǒng)需求,提出葉節(jié)點(diǎn)的內(nèi)聯(lián)算法,以滿足并行性分
    發(fā)表于 03-28 09:50 ?6次下載

    C++如何處理內(nèi)聯(lián)虛函數(shù)

    當(dāng)一個函數(shù)是內(nèi)聯(lián)和虛函數(shù)時,會發(fā)生代碼替換或使用虛表調(diào)用嗎? 為了弄 清楚內(nèi)聯(lián)和虛函數(shù),讓我們將它們分開來考慮。通常,一個內(nèi)聯(lián)函數(shù)是被展開的 。 class CFoo {
    發(fā)表于 11-29 11:59 ?28次下載

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

    什么是內(nèi)聯(lián)性和外聯(lián)函數(shù) 類的成員函數(shù)可以分為內(nèi)聯(lián)函數(shù)和外聯(lián)函數(shù)。內(nèi)聯(lián)函數(shù)是指那些定義在類體內(nèi)的成員函數(shù),即該函數(shù)的函數(shù)體放在類體內(nèi)。而說明在類體內(nèi),定義在類體外的成員函數(shù)叫外聯(lián)函數(shù)。外聯(lián)函數(shù)的函數(shù)體
    發(fā)表于 11-02 14:05 ?0次下載

    內(nèi)聯(lián)函數(shù)和外聯(lián)函數(shù)有什么區(qū)別

    內(nèi)聯(lián)函數(shù)是指用inline關(guān)鍵字修飾的函數(shù)。在類內(nèi)定義的函數(shù)被默認(rèn)成內(nèi)聯(lián)函數(shù)。內(nèi)聯(lián)函數(shù)從源代碼層看,有函數(shù)的結(jié)構(gòu),而在編譯后,卻不具備函數(shù)的性質(zhì)。內(nèi)聯(lián)函數(shù)不是在調(diào)用時發(fā)生控制轉(zhuǎn)移,而是
    發(fā)表于 12-15 11:52 ?5999次閱讀
    <b class='flag-5'>內(nèi)聯(lián)</b>函數(shù)和外聯(lián)函數(shù)有什么區(qū)別

    使用golang channel的諸多特性和技巧

    ? 本文介紹了使用 golang channel 的諸多特性和技巧,已經(jīng)熟悉了 go 語言特性的小伙伴也可以看看,很有啟發(fā)。
    的頭像 發(fā)表于 09-06 15:14 ?1933次閱讀
    使用<b class='flag-5'>golang</b> channel的諸多特性和技巧

    C++基礎(chǔ)語法之inline 內(nèi)聯(lián)函數(shù)

    上節(jié)我們分析了C++基礎(chǔ)語法的const,static以及 this 指針,那么這節(jié)內(nèi)容我們來看一下 inline 內(nèi)聯(lián)函數(shù)吧! inline 內(nèi)聯(lián)函數(shù) 特征 相當(dāng)于把內(nèi)聯(lián)函數(shù)里面的內(nèi)容寫在調(diào)用
    的頭像 發(fā)表于 09-09 09:38 ?2240次閱讀

    GoLang的安裝和使用

    GoLang的安裝和使用
    的頭像 發(fā)表于 01-13 14:06 ?1355次閱讀
    <b class='flag-5'>GoLang</b>的安裝和使用

    講解下C語言的內(nèi)聯(lián)函數(shù)

    內(nèi)聯(lián)函數(shù)是C語言從C++中借鑒過來的,適當(dāng)?shù)氖褂?b class='flag-5'>內(nèi)聯(lián)函數(shù)可以提高程序的執(zhí)行效率。
    的頭像 發(fā)表于 02-16 09:15 ?1600次閱讀

    C語言內(nèi)聯(lián)函數(shù),提升C技巧必備

    內(nèi)聯(lián)函數(shù)是C語言從C++中借鑒過來的,適當(dāng)?shù)氖褂?b class='flag-5'>內(nèi)聯(lián)函數(shù)可以提高程序的執(zhí)行效率。本篇文章就來講解下內(nèi)聯(lián)函數(shù),趕緊來看下吧!
    的頭像 發(fā)表于 02-16 09:16 ?865次閱讀

    一個快速應(yīng)用程序開發(fā)(RAD)工具(Golang版)

    SNMPAgent Builder(Golang版)是一個快速應(yīng)用程序開發(fā)(RAD)工具,用于基于Golang 的 SNMP代理開發(fā)。提供了一個直觀的圖形用戶界面,用于自動執(zhí)行各種SNMP 代理開發(fā)任務(wù)
    的頭像 發(fā)表于 04-13 09:30 ?1652次閱讀

    【芒果派MangoPi MQ Quad】使用Golang點(diǎn)燈

    使用Golang在芒果派上點(diǎn)燈
    的頭像 發(fā)表于 07-21 14:44 ?807次閱讀
    【芒果派MangoPi MQ Quad】使用<b class='flag-5'>Golang</b>點(diǎn)燈

    宏的缺陷與內(nèi)聯(lián)函數(shù)的引入

    。 所以為了解決這種不利于調(diào)試的問題,就有了內(nèi)聯(lián)函數(shù)。 那么什么是內(nèi)聯(lián)函數(shù)呢? 我們以inline修飾的函數(shù)叫做內(nèi)聯(lián)函數(shù),編譯階段,C編譯器會在調(diào)用函數(shù)的地方直接把函數(shù)展開,沒有壓棧開銷,內(nèi)聯(lián)
    的頭像 發(fā)表于 11-01 17:57 ?513次閱讀
    主站蜘蛛池模板: 福利看片| 午夜免费观看_视频在线观看 | 在线免费看黄的网站 | 高h细节肉爽文bl文 高h细节肉爽文男男 | 久久做| 性色小视频 | 日本特级视频 | 91极品反差婊在线观看 | 在线观看视频网站 | 天天草天天干 | 亚洲国产人久久久成人精品网站 | 97午夜| 日本一道高清不卡免费 | bt在线www天堂资源网 | free性日本| 视频一区二区不卡 | 免费操人视频 | 国产午夜视频在永久在线观看 | 欧美成人伊人十综合色 | www.黄黄黄 | 五月激情综合网 | 亚洲欧美一区二区三区在线播放 | 免费日本网站 | 在线观看亚洲一区二区 | 久久精品99无色码中文字幕 | 国产成人高清 | 国产剧情麻豆三级在线观看 | www.色99| 欧美一区二区视频三区 | 午夜激情福利视频 | 成人网在线观看 | 真实偷清晰对白在线视频 | 免费啪视频观在线视频在线 | 68日本xxxxxxxxx xx | 国产精品三级a三级三级午夜 | 额去鲁97在线观看视频 | 88av视频在线观看 | 天天透天天操 | 天天干天天操天天透 | 美女很黄很黄是免费的·无遮挡网站 | 久久精品国产精品亚洲人人 |