使用GDB等驗證Golang的“編譯器會為某些場合進行專門最佳化,避免字串轉換時的額外分配和複製操作”

來源:互聯網
上載者:User
這是一個建立於 的文章,其中的資訊可能已經有所發展或是發生改變。

編譯器會為某些場合進行專門最佳化,避免字串轉換時的額外分配和複製操作:

  • 將[]byte轉換為string key,去map[string]查詢的時候。
  • 將string轉換為[]byte,進行for range迭代時,直接取位元組賦值給局部變數。

Example Code

package mainfunc main() {    m := map[string]int {        "abc" : 123,    }    key := []byte("abc")    x, ok := m[string(key)]    println(x, ok)}
➜  go build -gcflags "-N -l" example.go 

GDB go1.7.6 驗證成功

  • 地址都是0xc420047ee0
➜  gdb exampleGNU gdb (GDB) 8.0.1Copyright (C) 2017 Free Software Foundation, Inc.License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>This is free software: you are free to change and redistribute it.There is NO WARRANTY, to the extent permitted by law.  Type "show copying"and "show warranty" for details.This GDB was configured as "x86_64-apple-darwin17.0.0".Type "show configuration" for configuration details.For bug reporting instructions, please see:<http://www.gnu.org/software/gdb/bugs/>.Find the GDB manual and other documentation resources online at:<http://www.gnu.org/software/gdb/documentation/>.For help, type "help".Type "apropos word" to search for commands related to "word"...Reading symbols from example...done.(gdb) b 9Breakpoint 1 at 0x2164: file /Users/anderson/Code/lang-experiments/golang/src/compiler-avoid-copy-when-transform-string/example.go, line 9.(gdb) cThe program is not being run.(gdb) rStarting program: /Users/anderson/Code/lang-experiments/golang/src/compiler-avoid-copy-when-transform-string/example [New Thread 0x2703 of process 90436]warning: unhandled dyld version (15)[New Thread 0x1907 of process 90436][New Thread 0x1a03 of process 90436][New Thread 0x2503 of process 90436][New Thread 0x2603 of process 90436]Thread 2 hit Breakpoint 1, main.main ()    at /Users/anderson/Code/lang-experiments/golang/src/compiler-avoid-copy-when-transform-string/example.go:99        x, ok := m[string(key)](gdb) p key$1 = {array = 0xc420047ee0 "abc", len = 3, cap = 32}(gdb) b runtime.mapaccess2_faststrBreakpoint 2 at 0x94b0: file /Users/anderson/.gvm/gos/go1.7.6/src/runtime/hashmap_fast.go, line 297.(gdb) cContinuing.Thread 2 hit Breakpoint 2, runtime.mapaccess2_faststr (t=0x5a2c0 <type.*+50144>, h=0xc42007c000, ky=..., ~r3=0x3, ~r4=32)    at /Users/anderson/.gvm/gos/go1.7.6/src/runtime/hashmap_fast.go:297297    func mapaccess2_faststr(t *maptype, h *hmap, ky string) (unsafe.Pointer, bool) {(gdb) p ky$2 = 0xc420047ee0 "abc"

delve go1.7.6 驗證失敗

  • 地址分別是:

    • 0xc420047f20
    • 0xc420047ea8
➜  dlv exec exampleType 'help' for list of commands.(dlv) b example.go:9Breakpoint 1 set at 0x2164 for main.main() ./example.go:9(dlv) c> main.main() ./example.go:9 (hits goroutine(1):1 total:1) (PC: 0x2164)     4:        m := map[string]int {     5:            "abc" : 123,     6:        }     7:         8:        key := []byte("abc")=>   9:        x, ok := m[string(key)]    10:        11:        println(x, ok)    12:    }(dlv) p key[]uint8 len: 3, cap: 32, [97,98,99](dlv) p &key(*[]uint8)(0xc420047f20)                                # 地址是0xc420047f20(dlv) b runtime.mapaccess2_faststrBreakpoint 2 set at 0x94c3 for runtime.mapaccess2_faststr() /Users/anderson/.gvm/gos/go1.7.6/src/runtime/hashmap_fast.go:297(dlv) c> runtime.mapaccess2_faststr() /Users/anderson/.gvm/gos/go1.7.6/src/runtime/hashmap_fast.go:297 (hits goroutine(1):1 total:1) (PC: 0x94c3)   292:                return unsafe.Pointer(&zeroVal[0])   293:            }   294:        }   295:    }   296:    => 297:    func mapaccess2_faststr(t *maptype, h *hmap, ky string) (unsafe.Pointer, bool) {   298:        if raceenabled && h != nil {   299:            callerpc := getcallerpc(unsafe.Pointer(&t))   300:            racereadpc(unsafe.Pointer(h), callerpc, funcPC(mapaccess2_faststr))   301:        }   302:        if h == nil || h.count == 0 {(dlv) p &ky(*string)(0xc420047ea8)                               # 地址是0xc420047ea8

LLDB go1.7.6 驗證成功

  • 地址都是: 0x000000c420041ee0
➜  lldb example(lldb) target create "example"Current executable set to 'example' (x86_64).(lldb) b example.go:9Breakpoint 1: where = example`main.main + 292 at example.go:9, address = 0x0000000000002164(lldb) rProcess 91197 launched: '/Users/anderson/Code/lang-experiments/golang/src/compiler-avoid-copy-when-transform-string/example' (x86_64)Process 91197 stopped* thread #1, stop reason = breakpoint 1.1    frame #0: 0x0000000000002164 example`main.main at example.go:9   6           }   7          8           key := []byte("abc")-> 9           x, ok := m[string(key)]   10         11          println(x, ok)   12      }Target 0: (example) stopped.(lldb) p key([]uint8) key = (len 3, cap 32) {  [0] = 97  [1] = 98  [2] = 99}(lldb) p &key(*[]uint8)  = 0x000000c420041ee0 (len 0, cap 0)(lldb) b runtime.mapaccess2_faststrBreakpoint 2: where = example`runtime.mapaccess2_faststr + 33 at hashmap_fast.go:302, address = 0x00000000000094d1(lldb) p key([]uint8) key = (len 3, cap 32) {  [0] = 97  [1] = 98  [2] = 99}(lldb) cProcess 91197 resumingProcess 91197 stopped* thread #1, stop reason = breakpoint 2.1    frame #0: 0x00000000000094d1 example`runtime.mapaccess2_faststr(t=0x000000000005a2c0, h=0x000000c420076000, ky="abc", ~r3=0x0000000000000003, ~r4=true) at hashmap_fast.go:302   299             callerpc := getcallerpc(unsafe.Pointer(&t))   300             racereadpc(unsafe.Pointer(h), callerpc, funcPC(mapaccess2_faststr))   301         }-> 302         if h == nil || h.count == 0 {   303             return unsafe.Pointer(&zeroVal[0]), false   304         }   305         if h.flags&hashWriting != 0 {Target 0: (example) stopped.(lldb) p ky(string) ky = "abc"(lldb) p &ky(*string)  = 0x000000c420041ee0 ""

GDB go1.10 無法查看數組地址,無法驗證

➜  gdb example_1_10 GNU gdb (GDB) 8.0.1Copyright (C) 2017 Free Software Foundation, Inc.License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>This is free software: you are free to change and redistribute it.There is NO WARRANTY, to the extent permitted by law.  Type "show copying"and "show warranty" for details.This GDB was configured as "x86_64-apple-darwin17.0.0".Type "show configuration" for configuration details.For bug reporting instructions, please see:<http://www.gnu.org/software/gdb/bugs/>.Find the GDB manual and other documentation resources online at:<http://www.gnu.org/software/gdb/documentation/>.For help, type "help".Type "apropos word" to search for commands related to "word"...Reading symbols from example_1_10...done.Loading Go Runtime support.(gdb) b 9Breakpoint 1 at 0x104d4b4: file /Users/anderson/Code/lang-experiments/golang/src/compiler-avoid-copy-when-transform-string/example.go, line 9.(gdb) rStarting program: /Users/anderson/Code/lang-experiments/golang/src/compiler-avoid-copy-when-transform-string/example_1_10 [New Thread 0x1903 of process 92053]warning: unhandled dyld version (15)[New Thread 0x1807 of process 92053][New Thread 0x1a03 of process 92053][New Thread 0x2503 of process 92053][New Thread 0x2603 of process 92053]Thread 2 hit Breakpoint 1, main.main () at /Users/anderson/Code/lang-experiments/golang/src/compiler-avoid-copy-when-transform-string/example.go:99        x, ok := m[string(key)](gdb) p key$1 =  []uint8 = {97 'a', 98 'b', 99 'c'}(gdb) p &key$2 =  []uint8 * = {97 'a', 98 'b', 99 'c'}(gdb) b runtime.mapaccess2_faststrBreakpoint 2 at 0x1007ee0: file /usr/local/Cellar/go/1.10/libexec/src/runtime/hashmap_fast.go, line 261.(gdb) cContinuing.Thread 2 hit Breakpoint 2, runtime.mapaccess2_faststr (h=0xc420057e78, ky="abc", t=0x105ad60 <type.*+55168>, ~r3=0x3, ~r4=32)    at /usr/local/Cellar/go/1.10/libexec/src/runtime/hashmap_fast.go:261261    func mapaccess2_faststr(t *maptype, h *hmap, ky string) (unsafe.Pointer, bool) {(gdb) p ky$3 = "abc"(gdb) p &ky$4 = "abc"

delve go1.10 驗證失敗

  • 地址分別是:

    • 0xc420057e60
    • 0xc420057dd0
➜  dlv exec example_1_10Type 'help' for list of commands.(dlv) b example.go:9Breakpoint 1 set at 0x104d4b4 for main.main() ./example.go:9(dlv) c> main.main() ./example.go:9 (hits goroutine(1):1 total:1) (PC: 0x104d4b4)     4:        m := map[string]int {     5:            "abc" : 123,     6:        }     7:         8:        key := []byte("abc")=>   9:        x, ok := m[string(key)]    10:        11:        println(x, ok)    12:    }(dlv) p key[]uint8 len: 3, cap: 32, [97,98,99](dlv) p &key(*[]uint8)(0xc420057e60)(dlv) b runtime.mapaccess2_faststrBreakpoint 2 set at 0x1007ef3 for runtime.mapaccess2_faststr() /usr/local/Cellar/go/1.10/libexec/src/runtime/hashmap_fast.go:261(dlv) c> runtime.mapaccess2_faststr() /usr/local/Cellar/go/1.10/libexec/src/runtime/hashmap_fast.go:261 (hits goroutine(1):1 total:1) (PC: 0x1007ef3)Warning: debugging optimized function   256:            }   257:        }   258:        return unsafe.Pointer(&zeroVal[0])   259:    }   260:    => 261:    func mapaccess2_faststr(t *maptype, h *hmap, ky string) (unsafe.Pointer, bool) {   262:        if raceenabled && h != nil {   263:            callerpc := getcallerpc()   264:            racereadpc(unsafe.Pointer(h), callerpc, funcPC(mapaccess2_faststr))   265:        }   266:        if h == nil || h.count == 0 {(dlv) p ky"abc"(dlv) p &ky(*string)(0xc420057dd0)

LLDB go1.10 驗證成功

  • 地址都是:0x000000c420057e10
➜  lldb example_1_10 (lldb) target create "example_1_10"Current executable set to 'example_1_10' (x86_64).(lldb) b example.go:9Breakpoint 1: where = example_1_10`main.main + 372 at example.go:9, address = 0x000000000104d4b4(lldb) rProcess 91907 launched: '/Users/anderson/Code/lang-experiments/golang/src/compiler-avoid-copy-when-transform-string/example_1_10' (x86_64)Process 91907 stopped* thread #1, stop reason = breakpoint 1.1    frame #0: 0x000000000104d4b4 example_1_10`main.main at example.go:9   6           }   7          8           key := []byte("abc")-> 9           x, ok := m[string(key)]   10         11          println(x, ok)   12      }Target 0: (example_1_10) stopped.(lldb) p key([]uint8) key = (len 3, cap 32) {  [0] = 97  [1] = 98  [2] = 99}(lldb) p &key(*[]uint8)  = 0x000000c420057e10 (len 0, cap 0)(lldb) b runtime.mapaccess2_faststrBreakpoint 2: where = example_1_10`runtime.mapaccess2_faststr + 38 at hashmap_fast.go:266, address = 0x0000000001007f06(lldb) cProcess 91907 resumingProcess 91907 stopped* thread #1, stop reason = breakpoint 2.1    frame #0: 0x0000000001007f06 example_1_10`runtime.mapaccess2_faststr(h=0x000000c420057e78, ky="abc", t=0x000000000105ad60, ~r3=0x0000000000000003, ~r4=true) at hashmap_fast.go:266   263             callerpc := getcallerpc()   264             racereadpc(unsafe.Pointer(h), callerpc, funcPC(mapaccess2_faststr))   265         }-> 266         if h == nil || h.count == 0 {   267             return unsafe.Pointer(&zeroVal[0]), false   268         }   269         if h.flags&hashWriting != 0 {Target 0: (example_1_10) stopped.(lldb) p ky(string) ky = "abc"(lldb) p &ky(*string)  = 0x000000c420057e10 ""(lldb) 

結論

  • 不知道為什麼,切換版本前後delve都驗證失敗了
  • 切換版本前後,LLDB都驗證成功了
  • GDB無法查看GO1.10的數組地址

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.