go的編譯優化問題
如下程式
package main
func main(){
var a = &struct {
}{}
var b = &struct {
}{}
if a == b{
println(a,b)
}
}
直接 run,沒有輸出。將println(a,b)
改為println(&a,&b)
,就能夠正確輸出 a,b 的指標。
編譯的時候如果禁止優化,那麼println(a,b)
也是能夠輸出的。
禁止優化的彙編程式碼為
"".main STEXT size=150 args=0x0 locals=0x30
0x0000 00000 (test.go:4) TEXT "".main(SB), $48-0
0x0000 00000 (test.go:4) MOVQ TLS, CX
0x0009 00009 (test.go:4) MOVQ (CX)(TLS*2), CX
0x0010 00016 (test.go:4) CMPQ SP, 16(CX)
0x0014 00020 (test.go:4) JLS 140
0x0016 00022 (test.go:4) SUBQ $48, SP
0x001a 00026 (test.go:4) MOVQ BP, 40(SP)
0x001f 00031 (test.go:4) LEAQ 40(SP), BP
0x0024 00036 (test.go:4) FUNCDATA $0, gclocals·f6bd6b3389b872033d462029172c8612(SB)
0x0024 00036 (test.go:4) FUNCDATA $1, gclocals·217c3c5f2c7a9e43555fa9a99f0bae4a(SB)
0x0024 00036 (test.go:4) FUNCDATA $3, gclocals·bfec7e55b3f043d1941c093912808913(SB)
0x0024 00036 (test.go:5) PCDATA $2, $1
0x0024 00036 (test.go:5) PCDATA $0, $0
0x0024 00036 (test.go:5) LEAQ ""..autotmp_3+8(SP), AX
0x0029 00041 (test.go:5) MOVQ AX, ""..autotmp_2+32(SP)
0x002e 00046 (test.go:5) PCDATA $2, $0
0x002e 00046 (test.go:5) PCDATA $0, $1
0x002e 00046 (test.go:5) MOVQ AX, "".a+16(SP)
0x0033 00051 (test.go:7) PCDATA $2, $1
0x0033 00051 (test.go:7) LEAQ ""..autotmp_5+8(SP), AX
0x0038 00056 (test.go:7) MOVQ AX, ""..autotmp_4+24(SP)
0x003d 00061 (test.go:7) PCDATA $0, $2
0x003d 00061 (test.go:7) MOVQ AX, "".b+8(SP)
0x0042 00066 (test.go:9) PCDATA $2, $2
0x0042 00066 (test.go:9) MOVQ "".a+16(SP), CX
0x0047 00071 (test.go:9) PCDATA $2, $0
0x0047 00071 (test.go:9) CMPQ CX, AX
0x004a 00074 (test.go:9) JEQ 78
0x004c 00076 (test.go:9) JMP 138
0x004e 00078 (test.go:11) CALL runtime.printlock(SB)
0x0053 00083 (test.go:11) PCDATA $2, $1
0x0053 00083 (test.go:11) PCDATA $0, $3
0x0053 00083 (test.go:11) MOVQ "".a+16(SP), AX
0x0058 00088 (test.go:11) PCDATA $2, $0
0x0058 00088 (test.go:11) MOVQ AX, (SP)
0x005c 00092 (test.go:11) CALL runtime.printpointer(SB)
0x0061 00097 (test.go:11) CALL runtime.printsp(SB)
0x0066 00102 (test.go:11) PCDATA $2, $1
0x0066 00102 (test.go:11) PCDATA $0, $0
0x0066 00102 (test.go:11) MOVQ "".b+8(SP), AX
0x006b 00107 (test.go:11) PCDATA $2, $0
0x006b 00107 (test.go:11) MOVQ AX, (SP)
0x006f 00111 (test.go:11) CALL runtime.printpointer(SB)
0x0074 00116 (test.go:11) CALL runtime.printnl(SB)
0x0079 00121 (test.go:11) CALL runtime.printunlock(SB)
0x007e 00126 (test.go:11) JMP 128
0x0080 00128 (<unknown line number>) PCDATA $2, $-2
0x0080 00128 (<unknown line number>) PCDATA $0, $-2
0x0080 00128 (<unknown line number>) MOVQ 40(SP), BP
0x0085 00133 (<unknown line number>) ADDQ $48, SP
0x0089 00137 (<unknown line number>) RET
0x008a 00138 (test.go:9) JMP 128
0x008c 00140 (test.go:9) NOP
0x008c 00140 (test.go:4) PCDATA $0, $-1
0x008c 00140 (test.go:4) PCDATA $2, $-1
0x008c 00140 (test.go:4) CALL runtime.morestack_noctxt(SB)
0x0091 00145 (test.go:4) JMP 0
此時直接在棧上分配地址,a,b 都是 8(SP) 的地址,所以肯定是相等的。但是假如加入優化,就變成了下面這樣
"".main STEXT nosplit size=1 args=0x0 locals=0x0
0x0000 00000 (test.go:16) TEXT "".main(SB), NOSPLIT, $0-0
0x0000 00000 (test.go:16) FUNCDATA $0, gclocals·33cdeccccebe80329f1fdbee7f5874cb(SB)
0x0000 00000 (test.go:16) FUNCDATA $1, gclocals·33cdeccccebe80329f1fdbee7f5874cb(SB)
0x0000 00000 (test.go:16) FUNCDATA $3, gclocals·33cdeccccebe80329f1fdbee7f5874cb(SB)
0x0000 00000 (<unknown line number>) RET
什麼都沒了。
如果 if 裡呼叫的是 fmt 或者 log.Println(a,b),分配在堆上,runtime.newobject 分配的是相同的地址,相等也沒問題。
所以現在是不是編譯器的優化問題?
更多原創文章乾貨分享,請關注公眾號
- 加微信實戰群請加微信(註明:實戰群):gocnio
相關文章
- 15個問題自查你真的瞭解java編譯優化嗎?Java編譯優化
- [譯] 優化 Swift 的編譯時間優化Swift編譯
- Android 編譯優化Android編譯優化
- JVM編譯優化JVM編譯優化
- libmemcached編譯問題IBM編譯
- SPI編譯問題編譯
- Java動態編譯優化——URLClassLoader 記憶體洩漏問題解決Java編譯優化記憶體
- Go 高效能系列教程之三:編譯器優化Go編譯優化
- 【問題記錄】—.NetCore 編譯問題NetCore編譯
- nginx 編譯出現的問題Nginx編譯
- 前端工程中的編譯時優化前端編譯優化
- Java動態編譯優化——ZipFileIndex記憶體洩漏問題分析解決Java編譯優化Index記憶體
- 後端編譯與優化後端編譯優化
- C++編譯器優化C++編譯優化
- 優化 Xcode 編譯時間優化XCode編譯
- Java動態編譯優化——提升編譯速度(N倍)Java編譯優化
- 一個nvcc編譯的小問題編譯
- CMake編譯Qt工程時的問題編譯QT
- golang windows10下 go build 無法編譯 問題解決GolangWindowsUI編譯
- 編譯器優化:方法內聯編譯優化
- Taro編譯打包優化實踐編譯優化
- [譯] 如何優化您的 Android 應用(Go 版)優化AndroidGo
- 深入理解flutter的編譯原理與優化Flutter編譯原理優化
- Linux下C語言編譯的問題LinuxC語言編譯
- 凸優化問題優化
- c++模板類的使用,編譯的問題C++編譯
- Gradle 編譯警告亂碼問題Gradle編譯
- 數值最優化—優化問題的解(二)優化
- Go編譯器簡介【譯】Go編譯
- [Vue] 使用dllPlugin編譯最佳化後路由傳參問題VuePlugin編譯路由
- 【go】【應用編譯】Go編譯
- go 交叉編譯,部署Go編譯
- Eclipse的啟動優化詳解(我看過的最全的優化), 終於解決啟動/編譯/執行期間的頻繁卡死問題了...Eclipse優化編譯
- Android編譯通過,執行編譯錯誤問題總結Android編譯
- 優化使用kotlin開發Android app的編譯速度優化KotlinAndroidAPP編譯
- lombok編譯遇到“找不到符號的問題”Lombok編譯符號
- matlab中出現mex無法編譯的問題Matlab編譯
- Laravel6.18.0 NPM 編譯時遇到的問題LaravelNPM編譯