Upgrade to Pro — share decks privately, control downloads, hide ads and more …

GC24 Recap: Interface Internals

task4233
September 18, 2024

GC24 Recap: Interface Internals

mercari.go #27での発表資料です。
ref: https://mercari.connpass.com/event/329214/

GopherCon2024で発表されたInterface Internalsに沿って、次のトピックをシェアしました:
・interfaceの内部処理に必要なステップ
・高速に実行するための仕組み

デモをご覧になりたい方はYouTubeのアーカイブを参照してください。
https://www.youtube.com/live/AEXVYTsM94Y

task4233

September 18, 2024
Tweet

More Decks by task4233

Other Decks in Technology

Transcript

  1. 3 ・発表の中で登場するアセンブリは linux/amd64 を仮定してください  ・Go の擬似アセンブリは基本的に登場しません  ・興味のある方は The Design of

    the Go Assembler を参照してください ・CS や Go の基本文法に関する事柄は深く説明しません  ・例) アセンブリ・デバッガの使い方・ interfaceなど  ・†完全に理解† するには余白が足りない  ・簡単な説明は挟む予定です はじめに
  2. 13 ・interfaceに含まれている型の取得 : *strings.Reader ・メソッドの一覧の取得 : Read ・正しい名前のメソッド情報の取得: strings.(*Reader).Read ・バイナリにおけるアドレスの取得

    ・対象メソッドの呼び出し interfaceの内部処理に必要なステップ var buf []byte var r io.Reader r = strings.NewReader("hoge") r.Read(buf)
  3. 14 ・interfaceに含まれている型の取得 : *strings.Reader ・メソッドの一覧の取得 : Read ・正しい名前のメソッド情報の取得: strings.(*Reader).Read ・バイナリにおけるアドレスの取得:

    strings.(*Reader).Read のアドレス ・対象メソッドの呼び出し interfaceの内部処理に必要なステップ var buf []byte var r io.Reader r = strings.NewReader("hoge") r.Read(buf)
  4. 15 ・interfaceに含まれている型の取得 : *strings.Reader ・メソッドの一覧の取得 : Read ・正しい名前のメソッド情報の取得: strings.(*Reader).Read ・バイナリにおけるアドレスの取得:

    strings.(*Reader).Read のアドレス ・対象メソッドの呼び出し: strings.(*Reader).Read の呼び出し interfaceの内部処理に必要なステップ var buf []byte var r io.Reader r = strings.NewReader("hoge") r.Read(buf)
  5. 16 empty interface ( interface{} ) 型情報を保持 データへのポインタを保持 空のメソッドセットを持つ interface

    ・Assignabilityに基づき、任意の値を代入できる   ref: https://go.dev/ref/spec#Assignability 2つのフィールドで実現されている ref: https://github.com/golang/go/blob/go1.23.1/src/runtime/runtime2.go#L210-L213
  6. 17 empty interface ( interface{} ) 型情報を保持 データへのポインタを保持 空のメソッドセットを持つ interface

    ・Assignabilityに基づき、任意の値を代入できる   ref: https://go.dev/ref/spec#Assignability 2つのフィールドで実現されている ref: https://github.com/golang/go/blob/go1.23.1/src/runtime/runtime2.go#L210-L213
  7. 18 empty interfaceのデータ参照 var i interface{} i = [3]int{1, 2,

    3} type data i: 1 2 3 = registers / stack = heap ref: https://github.com/gophercon/2024-talks/blob/main/KeithRandall-InterfaceInternal s/KeithRandall-InterfaceInternals.pdf
  8. 19 empty interfaceのデータ参照 var i interface{} i = [3]int{1, 2,

    3} i = [4]float64{4.0, 5.0} type data i: = registers / stack = heap ref: https://github.com/gophercon/2024-talks/blob/main/KeithRandall-InterfaceInternal s/KeithRandall-InterfaceInternals.pdf 1 2 3 4.0 5.0 GCのsweep対象に
  9. 20 empty interfaceのデータ参照の最適化 var i interface{} i = strings.NewReader("hoge") type

    data i: = registers / stack = heap ref: https://github.com/gophercon/2024-talks/blob/main/KeithRandall-InterfaceInternal s/KeithRandall-InterfaceInternals.pdf *strings.Reader s string i int64 prevRune int strings.Reader type data 🤔
  10. 21 empty interfaceのデータ参照の最適化 var i interface{} i = strings.NewReader("hoge") type

    *strings.Reader i: = registers / stack = heap ref: https://github.com/gophercon/2024-talks/blob/main/KeithRandall-InterfaceInternal s/KeithRandall-InterfaceInternals.pdf s string i int64 prevRune int strings.Reader 👍
  11. 22 empty interfaceのデータ参照の最適化 var i interface{} i = 'A' type

    data i: = registers / stack = heap ref: https://github.com/gophercon/2024-talks/blob/main/KeithRandall-InterfaceInternal s/KeithRandall-InterfaceInternals.pdf 'A' type data
  12. 23 empty interfaceのデータ参照の最適化 var i interface{} i = 'A' type

    data i: = registers / stack = heap ref: https://github.com/gophercon/2024-talks/blob/main/KeithRandall-InterfaceInternal s/KeithRandall-InterfaceInternals.pdf type data: 'A'
  13. 24 empty interface ( interface{} ) 型情報を保持 データへのポインタを保持 空のメソッドセットを持つ interface

    ・Assignabilityに基づき、任意の値を代入できる   ref: https://go.dev/ref/spec#Assignability 2つのフィールドで実現されている ref: https://github.com/golang/go/blob/go1.23.1/src/runtime/runtime2.go#L210-L213
  14. 25 empty interfaceの型情報 var i interface{} i = strings.NewReader("hoge") type

    data i: = registers / stack = heap ref: https://github.com/gophercon/2024-talks/blob/main/KeithRandall-InterfaceInternal s/KeithRandall-InterfaceInternals.pdf *strings.Readerの type descriptor 実データ = 静的データ
  15. 26 次のような型情報を与える ・型のサイズ ・ポインタフィールド ・文字列表現 ・型に対して == を行う方法 ・メソッドのリスト など

    interfaceのtype descriptor ref: https://github.com/golang/go/blob/go1.23.1/src/internal/abi/type.go#L20-L37 ref: https://github.com/golang/go/blob/go1.23.1/src/internal/abi/type.go#L442-L446
  16. 27 具象型から interfaceへの変換 var s *strings.Reader = ... var i

    interface{} = s type data i: 実データ = registers / stack = heap = 静的データ $type:*strings.Reader(SB) *strings.Readerの type descriptor
  17. 28 interfaceから具象型への型アサーション var i interface{} = ... if s, ok

    := i.(*strings.Reader); ok {...} type data i: 実データ = registers / stack = heap = 静的データ 比較 *strings.Readerの type descriptor *strings.Readerの type descriptor
  18. 29 interfaceから具象型への型アサーション err := f() if err != nil {...}

    type data err: 実データ = registers / stack = heap = 静的データ 比較 nil errの type descriptor
  19. 38 interface tableの導入 type data i: = registers / stack

    = heap ref: https://github.com/gophercon/2024-talks/blob/main/KeithRandall-InterfaceInternal s/KeithRandall-InterfaceInternals.pdf type descriptor 実データ = 静的データ 🤔
  20. 39 interface tableの導入 type data i: = registers / stack

    = heap ref: https://github.com/gophercon/2024-talks/blob/main/KeithRandall-InterfaceInternal s/KeithRandall-InterfaceInternals.pdf type descriptor 実データ = 静的データ type ... interface table (itab) で追加データを保持
  21. 41 interface tableの導入 = registers / stack = heap ref:

    https://github.com/gophercon/2024-talks/blob/main/KeithRandall-InterfaceInternals/KeithRandall-InterfaceInternals.pdf ... = 静的データ Inter Type Hash Fun var r io.Reader r = strings.NewReader("hoge") type: io.Reader Hash ... type: *strings.Reader ... strings.(*Reader).Read itab: *strings.Reader, io.Reader
  22. 42 interface tableの導入 = registers / stack = heap ref:

    https://github.com/gophercon/2024-talks/blob/main/KeithRandall-InterfaceInternals/KeithRandall-InterfaceInternals.pdf ... = 静的データ Inter Type Hash Fun var r io.Reader r = strings.NewReader("hoge") type: io.Reader Hash ... type: *strings.Reader ... strings.(*Reader).Read itab: *strings.Reader, io.Reader tab data r: 実データ
  23. 43 interface tableの導入 = registers / stack = heap ref:

    https://github.com/gophercon/2024-talks/blob/main/KeithRandall-InterfaceInternals/KeithRandall-InterfaceInternals.pdf ... = 静的データ Inter Type Hash Fun var r io.Reader r = ? type: io.Reader Hash ... type: ? ... ?.Read itab: ?, io.Reader tab data r: ?
  24. 44 interfaceを介した呼び出しはどう実行される ...? func f(r io.Reader) { var buf []byte

    r.Read(buf) } mov rdx,QWORD PTR [rdx+0x18] ; rdxはr.tabを指し、+0x18でfun[0]へアクセス mov rax,QWORD PTR [rsp+0x50] ; raxはreceiverを設定 call rdx ; 対象のメソッドを呼び出す
  25. 45 interface tableのキャッシュ戦略 (Go1.22〜) ・interface tableが過去に作成されたか確認 ・具象型の全てのメソッドリストを取得 ・リストの中からinterfaceの各メソッドを見つける ・interface tableを構築して、キャッシュに保存して返却

    ref: https://go-review.googlesource.com/c/go/+/526658 , https://go-review.googlesource.com/c/go/+/529316 etc… type assertion, type switch時の改善 高速に実行するための仕組み ref: https://github.com/gophercon/2024-talks/blob/main/KeithRandall-InterfaceInternals/KeithRandall-InterfaceInternals.pdf
  26. 47 ・Interface Internals: https://github.com/gophercon/2024-talks/blob/main/KeithRandall-InterfaceInternals/KeithRandall-InterfaceInternals.pdf ・teh-cmc / go-internals: https://github.com/teh-cmc/go-internals/tree/master ・Interfaces in

    Golang: A Deeper Lock: https://blog.stackademic.com/interfaces-in-golang-a-deeper-look-4a0931481c00 ・golang / go: https://github.com/golang/go/tree/go1.23.1/src ・Debugging Go Code with GDB: https://go.dev/doc/gdb ・cmd/compile: add a cache to interface type switches: https://go-review.googlesource.com/c/go/+/526658 ・cmd/compile: use cache in front of type assert runtime call: https://go-review.googlesource.com/c/go/+/529316 ・Vtable and Vptr How it works in C++: https://web.archive.org/web/20111215130820/http://www.kniraj.com/vtable-and-vptr-how-it-works-in-c/ ・The Design of the Go Assembler: https://go.dev/talks/2016/asm.slide ・A Quick Guide to Go’s Assembler: https://go.dev/doc/asm ・The Go Programming Language Specification: https://go.dev/ref/spec ・Goクイズで学ぶメソッドセット: https://speakerdeck.com/task4233/gokuizudexue-bumesotudosetuto ・Go internal ABI specification: https://go.googlesource.com/go/+/refs/heads/dev.regabi/src/cmd/compile/internal-abi.md References