Slide 1

Slide 1 text

触って理解する
 Go コンパイラ最適化
 市川悠人/izzii @ Techtouch
 Go Conference mini 2023


Slide 2

Slide 2 text

ボツになった京都仕様カラー案
 京都出身の同僚曰く「その気遣いいらんなー」 


Slide 3

Slide 3 text

自己紹介
 名前:市川悠人/izzii
 所属:テックタッチ株式会社
 経歴:AI エンジニア -> PdM -> SRE
 趣味:登山、ボルダリング
 X: ahneahneahne


Slide 4

Slide 4 text

(宣伝) 作っているプロダクト紹介
 Digital Adoption Platform (DAP) 製品を作っています!


Slide 5

Slide 5 text

(宣伝) 作っているプロダクト紹介
 ※公表許可いただいている企業・団体様より一部抜粋
 SaaS 事業者、大企業、公共と幅広く使われるホリゾンタル SaaS です


Slide 6

Slide 6 text

コンパイラの最適化とは
 コンパイル時により良いパフォーマンスのバイナリを生成する仕組 みと思ってもらえれば。
 
 知ることで Go コンパイラ思いのコードが
 書けるようになる!(はず)
 


Slide 7

Slide 7 text

紹介する最適化のカテゴリを大別すると
 - シンタックスの暗記が必要なもの
 - ゼロサイズ最適化
 - キャスト最適化
 - 知識があれば推論できるもの
 - ゼロクリア最適化
 - インライン展開
 - エスケープ解析
 - マークスキャン回避


Slide 8

Slide 8 text

紹介する最適化のカテゴリを大別すると
 - シンタックスの暗記が必要なもの
 - ゼロサイズ最適化
 - キャスト最適化
 - 知識があれば推論できるもの
 - ゼロクリア最適化
 - インライン展開
 - エスケープ解析
 - マークスキャン回避
 暗記ゲーはたったの2つ!
 Go 言語だけでなく
 普遍的に役立つ教養!


Slide 9

Slide 9 text

それぞれ簡単なクイズ形式でやっていきます!
 20分でザクっと記憶に残るように頑張ります! 
 知識の整理は後で僕のブログ読んでください笑 


Slide 10

Slide 10 text

問題です。


Slide 11

Slide 11 text

問題です。


Slide 12

Slide 12 text

問題です。
 下の main のアロケーションサイズは?
 ※ MiB 以下の
 瑣末なアロケーションは無視


Slide 13

Slide 13 text

(暗記型) ゼロサイズのメモリアロケーション回避
 答えは0!ゼロサイズ型のオブジェクトはアロケーションされません。
 Map を利用する時に利用されることが多いでしょう。


Slide 14

Slide 14 text

ちょっとキモいゼロサイズ型の例です。
 素直に空の struct を使いましょう笑
 (暗記型) ゼロサイズのメモリアロケーション回避


Slide 15

Slide 15 text

問題です。


Slide 16

Slide 16 text

問題です。


Slide 17

Slide 17 text

上下のそれぞれのアロケーションサ イズを予想してください。
 
 ※ 1 MiB か 2 MiB です
 ※ m は無視できる小ささ
 ※ MiB 以下の
 瑣末なアロケーションは無視
 問題です。


Slide 18

Slide 18 text

(暗記型) キャスト最適化 「string(b) が複数箇所に出てくるから 1つにまとめよう!」
 
 なんて気遣いは無駄です!笑


Slide 19

Slide 19 text

(暗記型) キャスト最適化 比較のためのキャスト
 byte 走査のためのキャスト
 map キー指定のためのキャスト


Slide 20

Slide 20 text

暗記ゲーは以上!
 - シンタックスの暗記が必要なもの
 - ゼロサイズ最適化 (DONE)
 - キャスト最適化 (DONE)
 - 知識があれば推論できるもの
 - ゼロクリア最適化
 - インライン展開
 - エスケープ解析
 - マークスキャン回避


Slide 21

Slide 21 text

問題です。


Slide 22

Slide 22 text

どれか一つだけが速いです。
 どれでしょう?
 
 0 か 1 で配列を埋めているだけですね〜。
 記法が違いますね〜。
 問題です。


Slide 23

Slide 23 text

他と比較すると1.5~2倍くらい速いです。
 
 memclr という専用の内部関数が呼ばれます。
 Go だけでなく配列埋めは高速化が図られがち。
 
 ちなみに 1.21 で追加された clear 関数も最適化が かかります。
 
 (推論型) ゼロクリア


Slide 24

Slide 24 text

非ゼロ値は用途が限定的なため提案が却下されています。
 C 言語にはより汎用的な memset があります。
 https://github.com/golang/go/issues/5373
 (推論型) ゼロクリア


Slide 25

Slide 25 text

問題です。


Slide 26

Slide 26 text

どちらの方が速いでしょう?
 (上は関数呼び出しをしていますね)
 問題です。


Slide 27

Slide 27 text

(推論型) インライン展開
 正解はどっちも同じです。
 ビルドした結果を ghidra でデコンパイルしてみた


Slide 28

Slide 28 text

インライン展開をオフにすることもできます。
 (推論型) インライン展開


Slide 29

Slide 29 text

(注意) 全ての関数がインライン展開されるわけではありません。
 シンプルな関数がインライン展開されやすいです。
 
 (注意) ビルドオプション -l で全てのインライン展開をオフにすると
 めっちゃパフォーマンス下がります。デバッグ用途
 (推論型) インライン展開


Slide 30

Slide 30 text

問題です。


Slide 31

Slide 31 text

どちらの方が早いでしょう?
 無駄にポインタ使っているな〜
 問題です。


Slide 32

Slide 32 text

(推論型) エスケープ解析
 関数内に閉じるのが明らかな変数はス タックに積まれますが、参照が関数に 閉じない可能性のあるオブジェクトは ヒープにエスケープされて GC が管理 します。
 
 
 ヒープにエスケープ (Alloc)
 スタックに積まれる


Slide 33

Slide 33 text

エスケープ解析については最適化というよりも言語特性の方が近い
 (以下は面白半分発言です。怒らないでね。)
 Go
 変数のライフサイクルを気にせずとも動く。チューンできない
 Rust
 変数のライフサイクルを管理できる。めんどくさい
 C/C++
 変数のライフサイクルを気にせずとも動く(死)。めんどくさい
 (推論型) エスケープ解析


Slide 34

Slide 34 text

問題です。


Slide 35

Slide 35 text

MyStruct1 の方が良さそうですよね。
 
 GC の観点で MyStruct1 の方がベターな のはなぜでしょうか?
 問題です。


Slide 36

Slide 36 text

(推論型) マークスキャン回避
 Go の GC はライブオブジェクトの分析のため、スキャンを実行します。オブジェ クトの生かす殺すのチェックをするためです。
 
 スキャンはオブジェクトグラフという、他のオブジェクトのポインタを
 たどることで作られるグラフを巡回して行われます。
 
 大きな配列内部にポインタが無ければ、
 その分スキャンする必要がなくなるということです。


Slide 37

Slide 37 text

(注意) 偉そうに発表してますが、自分の Go 力では実際に 2 つの struct で GC のパフォーマンスの違いを見れませんでした😭
 
 GC のコントロールむずいよ...
 (推論型) マークスキャン回避


Slide 38

Slide 38 text

That’s All!!
 - シンタックスの暗記が必要なもの
 - ゼロサイズ最適化 (DONE)
 - キャスト最適化 (DONE)
 - 知識があれば推論できるもの
 - ゼロクリア最適化 (DONE)
 - インライン展開 (DONE)
 - エスケープ解析 (DONE)
 - マークスキャン回避 (DONE)


Slide 39

Slide 39 text

ぜひ僕のブログで知識の整理をしてください!笑
 「テックタッチ テックブログ Go」で検索🔍