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
相關文章
- [譯] 優化 Go 的模式優化Go模式
- 【譯】優化Go的模式優化Go模式
- JVM編譯優化JVM編譯優化
- webpack 編譯優化Web編譯優化
- [譯] 優化 Swift 的編譯時間優化Swift編譯
- 15個問題自查你真的瞭解java編譯優化嗎?Java編譯優化
- Android 編譯優化Android編譯優化
- 優化 Swift 編譯速度優化Swift編譯
- Go 高效能系列教程之三:編譯器優化Go編譯優化
- SPI編譯問題編譯
- perl 編譯問題!編譯
- jive編譯問題編譯
- C++編譯器優化C++編譯優化
- 後端編譯與優化後端編譯優化
- 淺談編譯器優化編譯優化
- maven-編譯速度優化Maven編譯優化
- 前端工程中的編譯時優化前端編譯優化
- Java動態編譯優化——URLClassLoader 記憶體洩漏問題解決Java編譯優化記憶體
- Java動態編譯優化——ZipFileIndex記憶體洩漏問題分析解決Java編譯優化Index記憶體
- [翻譯]關於Swift的編譯時間優化Swift編譯優化
- libmemcached編譯問題IBM編譯
- EBS form編譯問題ORM編譯
- nginx 編譯出現的問題Nginx編譯
- 關於TIJ的編譯問題編譯
- jivejdon3編譯的問題編譯
- Java動態編譯優化——提升編譯速度(N倍)Java編譯優化
- golang windows10下 go build 無法編譯 問題解決GolangWindowsUI編譯
- 編譯器優化:方法內聯編譯優化
- Taro編譯打包優化實踐編譯優化
- 優化 Xcode 編譯時間優化XCode編譯
- webpack 應用編譯優化之路Web編譯優化
- CMake編譯Qt工程時的問題編譯QT
- Python Extension 編譯問題Python編譯
- 請教javac 編譯問題Java編譯
- cmake編譯問題解決編譯
- Myeclipse不能編譯問題Eclipse編譯
- 【問題記錄】—.NetCore 編譯問題NetCore編譯
- [譯] 如何優化您的 Android 應用(Go 版)優化AndroidGo