摘要:簡單來講,就是這個函數(shù)跳過堆棧溢出的檢查案例該指令表示編譯器遇到寫屏障時就會產(chǎn)生一個錯誤,并且允許遞歸。
原文地址:簡單圍觀一下有趣的 //go: 指令
前言如果你平時有翻看源碼的習(xí)慣,你肯定會發(fā)現(xiàn)。咦,怎么有的方法上面總是寫著 //go: 這類指令呢。他們到底是干嘛用的?
今天我們一同揭開他們的面紗,我將簡單給你介紹一下,它們都負責(zé)些什么
go:linkname//go:linkname localname importpath.name
該指令指示編譯器使用 importpath.name 作為源代碼中聲明為 localname 的變量或函數(shù)的目標(biāo)文件符號名稱。但是由于這個偽指令,可以破壞類型系統(tǒng)和包模塊化。因此只有引用了 unsafe 包才可以使用
簡單來講,就是 importpath.name 是 localname 的符號別名,編譯器實際上會調(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 }
在這個案例中可以看到 time.now,它并沒有具體的實現(xiàn)。如果你初看可能會懵逼。這時候建議你全局搜索一下源碼,你就會發(fā)現(xiàn)其實現(xiàn)在 runtime.time_now 中
配合先前的用法解釋,可得知在 runtime 包中,我們聲明了 time_now 方法是 time.now 的符號別名。并且在文件頭引入了 unsafe 達成前提條件
go:noescape//go:noescape
該指令指定下一個有聲明但沒有主體(意味著實現(xiàn)有可能不是 Go)的函數(shù),不允許編譯器對其做逃逸分析
一般情況下,該指令用于內(nèi)存分配優(yōu)化。因為編譯器默認會進行逃逸分析,會通過規(guī)則判定一個變量是分配到堆上還是棧上。但凡事有意外,一些函數(shù)雖然逃逸分析其是存放到堆上。但是對于我們來說,它是特別的。我們就可以使用 go:noescape 指令強制要求編譯器將其分配到函數(shù)棧上
案例// memmove copies n bytes from "from" to "to". // in memmove_*.s //go:noescape func memmove(to, from unsafe.Pointer, n uintptr)
我們觀察一下這個案例,它滿足了該指令的常見特性。如下:
memmove_*.s:只有聲明,沒有主體。其主體是由底層匯編實現(xiàn)的
memmove:函數(shù)功能,在棧上處理性能會更好
go:nosplit//go:nosplit
該指令指定文件中聲明的下一個函數(shù)不得包含堆棧溢出檢查。簡單來講,就是這個函數(shù)跳過堆棧溢出的檢查
案例//go:nosplit func key32(p *uintptr) *uint32 { return (*uint32)(unsafe.Pointer(p)) }go:nowritebarrierrec
//go:nowritebarrierrec
該指令表示編譯器遇到寫屏障時就會產(chǎn)生一個錯誤,并且允許遞歸。也就是這個函數(shù)調(diào)用的其他函數(shù)如果有寫屏障也會報錯。簡單來講,就是針對寫屏障的處理,防止其死循環(huán)
案例//go:nowritebarrierrec func gcFlushBgCredit(scanWork int64) { ... }go:yeswritebarrierrec
//go:yeswritebarrierrec
該指令與 go:nowritebarrierrec 相對,在標(biāo)注 go:nowritebarrierrec 指令的函數(shù)上,遇到寫屏障會產(chǎn)生錯誤。而當(dāng)編譯器遇到 go:yeswritebarrierrec 指令時將會停止
案例//go:yeswritebarrierrec func gchelper() { ... }go:noinline
該指令表示該函數(shù)禁止進行內(nèi)聯(lián)
案例//go:noinline func unexportedPanicForTesting(b []byte, i int) byte { return b[i] }
我們觀察一下這個案例,是直接通過索引取值,邏輯比較簡單。如果不加上 go:noinline 的話,就會出現(xiàn)編譯器對其進行內(nèi)聯(lián)優(yōu)化
顯然,內(nèi)聯(lián)有好有壞。該指令就是提供這一特殊處理
go:norace//go:norace
該指令表示禁止進行競態(tài)檢測。而另外一種常見的形式就是在啟動時執(zhí)行 go run -race,能夠檢測應(yīng)用程序中是否存在雙向的數(shù)據(jù)競爭。非常有用
案例//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
該指令常用于類型聲明,它表示這個類型不允許從 GC 堆上進行申請內(nèi)存。在運行時中常用其來做較低層次的內(nèi)部結(jié)構(gòu),避免調(diào)度器和內(nèi)存分配中的寫屏障。能夠提高性能
案例// 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é)
在本文我們簡單介紹了一些常見的指令集,我建議僅供了解。一般我們是用不到的,因為你的瓶頸可能更多的在自身應(yīng)用上
但是了解這一些,對你了解底層源碼和運行機制會更有幫助。如果想再深入些,可閱讀我給出的參考鏈接 :)
參考HACKING
Command compile
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/31142.html
摘要:從全局來看,大多數(shù)計算機只是傳遞一堆布爾值,所以任何對布爾值友好的語言都可以完成這項工作。將模式應(yīng)用于這些布爾值能夠幫助程序員獲得其含義,任何人都要做的最大決策是確定系統(tǒng)將使用哪種字節(jié)順序,并確保所有組件都以正確的順序在總線之間傳遞信息。芯片的設(shè)計到底有多難?想要回答這個問題最好還是先自己實踐一下。最近,來自 BBC 的一名資深軟件工程師 Daniel Harper 使用 Go 語言成功模擬...
摘要:從全局來看,大多數(shù)計算機只是傳遞一堆布爾值,所以任何對布爾值友好的語言都可以完成這項工作。將模式應(yīng)用于這些布爾值能夠幫助程序員獲得其含義,任何人都要做的最大決策是確定系統(tǒng)將使用哪種字節(jié)順序,并確保所有組件都以正確的順序在總線之間傳遞信息。芯片的設(shè)計到底有多難?想要回答這個問題最好還是先自己實踐一下。最近,來自 BBC 的一名資深軟件工程師 Daniel Harper 使用 Go 語言成功模擬...
摘要:入門,第一個這是一門很新的語言,年前后正式公布,算起來是比較年輕的編程語言了,更重要的是它是面向程序員的函數(shù)式編程語言,它的代碼運行在之上。它通過編輯類工具,帶來了先進的編輯體驗,增強了語言服務(wù)。 showImg(https://segmentfault.com/img/bV1xdq?w=900&h=385); 新的一年不知不覺已經(jīng)到來了,總結(jié)過去的 2017,相信小伙們一定有很多收獲...
摘要:入門,第一個這是一門很新的語言,年前后正式公布,算起來是比較年輕的編程語言了,更重要的是它是面向程序員的函數(shù)式編程語言,它的代碼運行在之上。它通過編輯類工具,帶來了先進的編輯體驗,增強了語言服務(wù)。 showImg(https://segmentfault.com/img/bV1xdq?w=900&h=385); 新的一年不知不覺已經(jīng)到來了,總結(jié)過去的 2017,相信小伙們一定有很多收獲...
摘要:入門,第一個這是一門很新的語言,年前后正式公布,算起來是比較年輕的編程語言了,更重要的是它是面向程序員的函數(shù)式編程語言,它的代碼運行在之上。它通過編輯類工具,帶來了先進的編輯體驗,增強了語言服務(wù)。 showImg(https://segmentfault.com/img/bV1xdq?w=900&h=385); 新的一年不知不覺已經(jīng)到來了,總結(jié)過去的 2017,相信小伙們一定有很多收獲...
閱讀 3400·2021-11-24 10:30
閱讀 3269·2021-11-22 15:29
閱讀 3706·2021-10-28 09:32
閱讀 1255·2021-09-07 10:22
閱讀 3336·2019-08-30 15:55
閱讀 3619·2019-08-30 15:54
閱讀 3494·2019-08-30 15:54
閱讀 2833·2019-08-30 15:44