成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

簡(jiǎn)單圍觀一下有趣的 //go: 指令

CNZPH / 689人閱讀

摘要:簡(jiǎn)單來(lái)講,就是這個(gè)函數(shù)跳過(guò)堆棧溢出的檢查案例該指令表示編譯器遇到寫(xiě)屏障時(shí)就會(huì)產(chǎn)生一個(gè)錯(cuò)誤,并且允許遞歸。

原文地址:簡(jiǎn)單圍觀一下有趣的 //go: 指令

前言

如果你平時(shí)有翻看源碼的習(xí)慣,你肯定會(huì)發(fā)現(xiàn)。咦,怎么有的方法上面總是寫(xiě)著 //go: 這類指令呢。他們到底是干嘛用的?

今天我們一同揭開(kāi)他們的面紗,我將簡(jiǎn)單給你介紹一下,它們都負(fù)責(zé)些什么

go:linkname
//go:linkname localname importpath.name

該指令指示編譯器使用 importpath.name 作為源代碼中聲明為 localname 的變量或函數(shù)的目標(biāo)文件符號(hào)名稱。但是由于這個(gè)偽指令,可以破壞類型系統(tǒng)和包模塊化。因此只有引用了 unsafe 包才可以使用

簡(jiǎn)單來(lái)講,就是 importpath.namelocalname 的符號(hào)別名,編譯器實(shí)際上會(huì)調(diào)用 localname 。但前提是使用了 unsafe 包才能使用

案例 time/time.go
...
func now() (sec int64, nsec int32, mono int64)
runtime/timestub.go
import _ "unsafe" // for go:linkname

//go:linkname time_now time.now
func time_now() (sec int64, nsec int32, mono int64) {
    sec, nsec = walltime()
    return sec, nsec, nanotime() - startNano
}

在這個(gè)案例中可以看到 time.now,它并沒(méi)有具體的實(shí)現(xiàn)。如果你初看可能會(huì)懵逼。這時(shí)候建議你全局搜索一下源碼,你就會(huì)發(fā)現(xiàn)其實(shí)現(xiàn)在 runtime.time_now

配合先前的用法解釋,可得知在 runtime 包中,我們聲明了 time_now 方法是 time.now 的符號(hào)別名。并且在文件頭引入了 unsafe 達(dá)成前提條件

go:noescape
//go:noescape

該指令指定下一個(gè)有聲明但沒(méi)有主體(意味著實(shí)現(xiàn)有可能不是 Go)的函數(shù),不允許編譯器對(duì)其做逃逸分析

一般情況下,該指令用于內(nèi)存分配優(yōu)化。因?yàn)榫幾g器默認(rèn)會(huì)進(jìn)行逃逸分析,會(huì)通過(guò)規(guī)則判定一個(gè)變量是分配到堆上還是棧上。但凡事有意外,一些函數(shù)雖然逃逸分析其是存放到堆上。但是對(duì)于我們來(lái)說(shuō),它是特別的。我們就可以使用 go:noescape 指令強(qiáng)制要求編譯器將其分配到函數(shù)棧上

案例
// memmove copies n bytes from "from" to "to".
// in memmove_*.s
//go:noescape
func memmove(to, from unsafe.Pointer, n uintptr)

我們觀察一下這個(gè)案例,它滿足了該指令的常見(jiàn)特性。如下:

memmove_*.s:只有聲明,沒(méi)有主體。其主體是由底層匯編實(shí)現(xiàn)的

memmove:函數(shù)功能,在棧上處理性能會(huì)更好

go:nosplit
//go:nosplit

該指令指定文件中聲明的下一個(gè)函數(shù)不得包含堆棧溢出檢查。簡(jiǎn)單來(lái)講,就是這個(gè)函數(shù)跳過(guò)堆棧溢出的檢查

案例
//go:nosplit
func key32(p *uintptr) *uint32 {
    return (*uint32)(unsafe.Pointer(p))
}
go:nowritebarrierrec
//go:nowritebarrierrec

該指令表示編譯器遇到寫(xiě)屏障時(shí)就會(huì)產(chǎn)生一個(gè)錯(cuò)誤,并且允許遞歸。也就是這個(gè)函數(shù)調(diào)用的其他函數(shù)如果有寫(xiě)屏障也會(huì)報(bào)錯(cuò)。簡(jiǎn)單來(lái)講,就是針對(duì)寫(xiě)屏障的處理,防止其死循環(huán)

案例
//go:nowritebarrierrec
func gcFlushBgCredit(scanWork int64) {
    ...
}
go:yeswritebarrierrec
//go:yeswritebarrierrec

該指令與 go:nowritebarrierrec 相對(duì),在標(biāo)注 go:nowritebarrierrec 指令的函數(shù)上,遇到寫(xiě)屏障會(huì)產(chǎn)生錯(cuò)誤。而當(dāng)編譯器遇到 go:yeswritebarrierrec 指令時(shí)將會(huì)停止

案例
//go:yeswritebarrierrec
func gchelper() {
    ...
}
go:noinline

該指令表示該函數(shù)禁止進(jìn)行內(nèi)聯(lián)

案例
//go:noinline
func unexportedPanicForTesting(b []byte, i int) byte {
    return b[i]
}

我們觀察一下這個(gè)案例,是直接通過(guò)索引取值,邏輯比較簡(jiǎn)單。如果不加上 go:noinline 的話,就會(huì)出現(xiàn)編譯器對(duì)其進(jìn)行內(nèi)聯(lián)優(yōu)化

顯然,內(nèi)聯(lián)有好有壞。該指令就是提供這一特殊處理

go:norace
//go:norace

該指令表示禁止進(jìn)行競(jìng)態(tài)檢測(cè)。而另外一種常見(jiàn)的形式就是在啟動(dòng)時(shí)執(zhí)行 go run -race,能夠檢測(cè)應(yīng)用程序中是否存在雙向的數(shù)據(jù)競(jìng)爭(zhēng)。非常有用

案例
//go:norace
func forkAndExecInChild(argv0 *byte, argv, envv []*byte, chroot, dir *byte, attr *ProcAttr, sys *SysProcAttr, pipe int) (pid int, err Errno) {
    ...
}
go:notinheap
//go:notinheap

該指令常用于類型聲明,它表示這個(gè)類型不允許從 GC 堆上進(jìn)行申請(qǐng)內(nèi)存。在運(yùn)行時(shí)中常用其來(lái)做較低層次的內(nèi)部結(jié)構(gòu),避免調(diào)度器和內(nèi)存分配中的寫(xiě)屏障。能夠提高性能

案例
// notInHeap is off-heap memory allocated by a lower-level allocator
// like sysAlloc or persistentAlloc.
//
// In general, it"s better to use real types marked as go:notinheap,
// but this serves as a generic type for situations where that isn"t
// possible (like in the allocators).
//
//go:notinheap
type notInHeap struct{}
總結(jié)

在本文我們簡(jiǎn)單介紹了一些常見(jiàn)的指令集,我建議僅供了解。一般我們是用不到的,因?yàn)槟愕钠款i可能更多的在自身應(yīng)用上

但是了解這一些,對(duì)你了解底層源碼和運(yùn)行機(jī)制會(huì)更有幫助。如果想再深入些,可閱讀我給出的參考鏈接 :)

參考

HACKING

Command compile

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/31142.html

相關(guān)文章

  • 我這個(gè)人不懂什么CPU,于是我用代碼模擬出了一個(gè)

    摘要:從全局來(lái)看,大多數(shù)計(jì)算機(jī)只是傳遞一堆布爾值,所以任何對(duì)布爾值友好的語(yǔ)言都可以完成這項(xiàng)工作。將模式應(yīng)用于這些布爾值能夠幫助程序員獲得其含義,任何人都要做的最大決策是確定系統(tǒng)將使用哪種字節(jié)順序,并確保所有組件都以正確的順序在總線之間傳遞信息。芯片的設(shè)計(jì)到底有多難?想要回答這個(gè)問(wèn)題最好還是先自己實(shí)踐一下。最近,來(lái)自 BBC 的一名資深軟件工程師 Daniel Harper 使用 Go 語(yǔ)言成功模擬...

    番茄西紅柿 評(píng)論0 收藏0
  • 我這個(gè)人不懂什么CPU,于是我用代碼模擬出了一個(gè)

    摘要:從全局來(lái)看,大多數(shù)計(jì)算機(jī)只是傳遞一堆布爾值,所以任何對(duì)布爾值友好的語(yǔ)言都可以完成這項(xiàng)工作。將模式應(yīng)用于這些布爾值能夠幫助程序員獲得其含義,任何人都要做的最大決策是確定系統(tǒng)將使用哪種字節(jié)順序,并確保所有組件都以正確的順序在總線之間傳遞信息。芯片的設(shè)計(jì)到底有多難?想要回答這個(gè)問(wèn)題最好還是先自己實(shí)踐一下。最近,來(lái)自 BBC 的一名資深軟件工程師 Daniel Harper 使用 Go 語(yǔ)言成功模擬...

    incredible 評(píng)論0 收藏0
  • SegmentFault 技術(shù)周刊 Vol.40 - 2018,來(lái)學(xué)習(xí)一門新編程語(yǔ)言吧!

    摘要:入門,第一個(gè)這是一門很新的語(yǔ)言,年前后正式公布,算起來(lái)是比較年輕的編程語(yǔ)言了,更重要的是它是面向程序員的函數(shù)式編程語(yǔ)言,它的代碼運(yùn)行在之上。它通過(guò)編輯類工具,帶來(lái)了先進(jìn)的編輯體驗(yàn),增強(qiáng)了語(yǔ)言服務(wù)。 showImg(https://segmentfault.com/img/bV1xdq?w=900&h=385); 新的一年不知不覺(jué)已經(jīng)到來(lái)了,總結(jié)過(guò)去的 2017,相信小伙們一定有很多收獲...

    caspar 評(píng)論0 收藏0
  • SegmentFault 技術(shù)周刊 Vol.40 - 2018,來(lái)學(xué)習(xí)一門新編程語(yǔ)言吧!

    摘要:入門,第一個(gè)這是一門很新的語(yǔ)言,年前后正式公布,算起來(lái)是比較年輕的編程語(yǔ)言了,更重要的是它是面向程序員的函數(shù)式編程語(yǔ)言,它的代碼運(yùn)行在之上。它通過(guò)編輯類工具,帶來(lái)了先進(jìn)的編輯體驗(yàn),增強(qiáng)了語(yǔ)言服務(wù)。 showImg(https://segmentfault.com/img/bV1xdq?w=900&h=385); 新的一年不知不覺(jué)已經(jīng)到來(lái)了,總結(jié)過(guò)去的 2017,相信小伙們一定有很多收獲...

    nihao 評(píng)論0 收藏0
  • SegmentFault 技術(shù)周刊 Vol.40 - 2018,來(lái)學(xué)習(xí)一門新編程語(yǔ)言吧!

    摘要:入門,第一個(gè)這是一門很新的語(yǔ)言,年前后正式公布,算起來(lái)是比較年輕的編程語(yǔ)言了,更重要的是它是面向程序員的函數(shù)式編程語(yǔ)言,它的代碼運(yùn)行在之上。它通過(guò)編輯類工具,帶來(lái)了先進(jìn)的編輯體驗(yàn),增強(qiáng)了語(yǔ)言服務(wù)。 showImg(https://segmentfault.com/img/bV1xdq?w=900&h=385); 新的一年不知不覺(jué)已經(jīng)到來(lái)了,總結(jié)過(guò)去的 2017,相信小伙們一定有很多收獲...

    Drummor 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<