sync/v2 プロポーザルの 背景と sync.Pool について
by
matumoto
×
Copy
Open
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
Slide 1
Slide 1 text
© DMM © DMM CONFIDENTIAL sync/v2 プロポーザルの 背景と sync.Pool について DMM.go #10 24新卒 松本響輝(matumoto) 2025-05-15
Slide 2
Slide 2 text
© DMM 2 松本 響輝 (matumoto) ● 合同会社DMM.com 開発統括本部マーケティングテクノロジー 部開発チーム ● Goがちょっと好きな24新卒です ● X: @matumoto_1234
Slide 3
Slide 3 text
© DMM 発表の目的 • sync/v2 についてちょっと詳しくなる • 今後注目される機能に目を向ける足がかりになれれば! • 追加される機能の背景や議論を知ってもっとGoを好きに! • Approveされていない のであくまで参考程度に 3
Slide 4
Slide 4 text
© DMM 目次 • v2のプロポーザル一覧 • syncパッケージ(v1)のおさらい • インターフェースのメモリ割り当てについて • sync/v2パッケージのプロポーザル • ジェネリクス対応とv2 • まとめ 4
Slide 5
Slide 5 text
© DMM CONFIDENTAL v2のプロポーザル一覧
Slide 6
Slide 6 text
© DMM 6 label:v2 かつ label:Proposal なものは32件もある
Slide 7
Slide 7 text
© DMM 7 今回、sync/v2 について紹介
Slide 8
Slide 8 text
© DMM CONFIDENTAL そのまえに
Slide 9
Slide 9 text
© DMM CONFIDENTAL syncパッケージ (v1)のおさらい
Slide 10
Slide 10 text
© DMM Go1.24までの sync パッケージの機能 ● 代表的なもの ○ sync.Pool ○ sync.Map ○ sync.WaitGroup ○ sync.Mutex ○ … 10
Slide 11
Slide 11 text
© DMM それぞれの概要 ● 代表的なもの ○ sync.Pool → スレッドセーフなキャッシュ(GCの負荷を軽減) ○ sync.Map → スレッドセーフなmap ○ sync.WaitGroup → goroutine の待機に ○ sync.Mutex → 排他制御に ○ … 11
Slide 12
Slide 12 text
© DMM 今回 sync.Pool と sync.Map に注目 ● 代表的なもの ○ sync.Pool → スレッドセーフなキャッシュ(GCの負荷を軽減) ○ sync.Map → スレッドセーフなmap ○ sync.WaitGroup → goroutine の待機に ○ sync.Mutex → 排他制御に ○ … 12
Slide 13
Slide 13 text
© DMM sync.Pool 型 13
Slide 14
Slide 14 text
© DMM sync.Pool 型 14 any を返す関数を渡す
Slide 15
Slide 15 text
© DMM sync.Map 型 15
Slide 16
Slide 16 text
© DMM sync.Map 型 16
Slide 17
Slide 17 text
© DMM sync.Map 型 17 メソッドでは基本 any を扱う
Slide 18
Slide 18 text
© DMM any で扱うことのなにが問題か? 18 ● メモリ割り当てが行われる ● 返り値の型アサーションがめんどう
Slide 19
Slide 19 text
© DMM any で扱うことのなにが問題か? 19 ● メモリ割り当てが行われる ● 返り値の型アサーションがめんどう
Slide 20
Slide 20 text
© DMM any で扱うことのなにが問題か? 20 ● メモリ割り当てが行われる ● 返り値の型アサーションがめんどう sync(v1) では any で扱ってしまっている ...
Slide 21
Slide 21 text
© DMM any で扱うことのなにが問題か? 21 ● メモリ割り当てが行われる ● 返り値の型アサーションがめんどう sync(v1) では any で扱ってしまっている ... インターフェースを介さないジェネリクスで扱い たい!
Slide 22
Slide 22 text
© DMM CONFIDENTAL インターフェースを 介したくない理由って ...?🤔
Slide 23
Slide 23 text
© DMM CONFIDENTAL インターフェースの メモリ割り当てについて
Slide 24
Slide 24 text
© DMM インターフェースのメモリ割り当て(雑) 24 ● インターフェースは「型」と「値」を持っている ● 「型」はメソッド情報へのポインタ ● 「値」は実際のデータへのポインタ (他の言語でのボックス化に近い概念かもしれません)
Slide 25
Slide 25 text
© DMM インターフェースのメモリ割り当て(雑) 25 String() メソッドを持つ構造体 A
Slide 26
Slide 26 text
© DMM インターフェースのメモリ割り当て(雑) 26 fmt.Stringer として新しく変数を作る
Slide 27
Slide 27 text
© DMM インターフェースのメモリ割り当て(雑) 27 s := fmt.Stringer(a) 型へのポインタ 値へのポインタ a.str などの値 fmt.Stringer a.String()
Slide 28
Slide 28 text
© DMM インターフェースのメモリ割り当て(雑) 28 s := fmt.Stringer(a) 型へのポインタ 値へのポインタ a.str などの値 fmt.Stringer 値へのポインタはヒー プ領域に確保 a.String()
Slide 29
Slide 29 text
© DMM インターフェースのメモリ割り当て(雑) 29 s := fmt.Stringer(a) 型へのポインタ 値へのポインタ a.str などの値 a.String() 値へのポインタはヒー プ領域に確保 ポインタ分のヒープ領域への 割り当てが発生する!
Slide 30
Slide 30 text
© DMM インターフェースのメモリ割り当て(雑) 30 s := fmt.Stringer(a) 型へのポインタ 値へのポインタ a.str などの値 a.String() 値へのポインタはヒー プ領域に確保 最適化で割り当てが 発生しない場合もあります
Slide 31
Slide 31 text
© DMM 最適化. 割り当てが発生しないこともある 31 ※ ワードサイズ: 32bit や 64bit などのCPUの処理単位
Slide 32
Slide 32 text
© DMM 最適化. 割り当てが発生しないこともある 32 i := any(v) 型へのポインタ 値へのポインタ 100 any
Slide 33
Slide 33 text
© DMM 最適化. 割り当てが発生しないこともある 33 i := any(v) 型へのポインタ 値へのポインタ 100 any 値をここに入れた方が 効率的!
Slide 34
Slide 34 text
© DMM 最適化. 割り当てが発生しないこともある 34 i := any(v) 型へのポインタ 100 any ポインタのヒープ 割り当てがなくなる
Slide 35
Slide 35 text
© DMM つまり..? 35 ● インターフェースを介すと、メモリ割り当てが発生! ○ (大体のケースで) ● 1回は小さくても頻繁に行われるなら大きく響くかも..?
Slide 36
Slide 36 text
© DMM CONFIDENTAL sync.Pool, sync.Map に話をもどして ...
Slide 37
Slide 37 text
© DMM any で扱うことのなにが問題か?(再掲) 37 ● メモリ割り当てが行われる ● 返り値の型アサーションがめんどう
Slide 38
Slide 38 text
© DMM any で扱うことのなにが問題か?(再掲) 38 ● メモリ割り当てが行われる ● 返り値の型アサーションがめんどう sync(v1) では any で扱ってしまっている ... インターフェースを介さないジェネリクスで扱い たい!
Slide 39
Slide 39 text
© DMM CONFIDENTAL sync/v2 パッケージのプロポーザル
Slide 40
Slide 40 text
© DMM 提案の概要 • sync.Pool, sync.Map をジェネリクス対応 • (sync.NewPool() があるのでただの移行ではないが、主題はジェネリク ス) • それ以外は据え置き 40
Slide 41
Slide 41 text
© DMM sync.Pool のジェネリクス対応 41
Slide 42
Slide 42 text
© DMM sync.Map のジェネリクス対応 42
Slide 43
Slide 43 text
© DMM 提案の内容(再掲) • sync.Pool, sync.Map をジェネリクス対応 • (sync.NewPool() があるのでただの移行ではないが、主題はジェネリク ス) • それ以外は据え置き 43
Slide 44
Slide 44 text
© DMM 提案の内容(再掲) • sync.Pool, sync.Map をジェネリクス対応 • (sync.NewPool() があるのでただの移行ではないが、主題はジェネリク ス) • それ以外は据え置き 44 ジェネリクス対応のためだけに v2 にするのか という意見もある
Slide 45
Slide 45 text
© DMM 議論の一部要約 45 ジェネリクス対応のためだけに v2にするべきか? 今後 sync/v3, net/http/v10, … のように 乱立してしまうのでは? ジェネリクスほどの大きな変更で はじめて sync/v3 になるので乱立しない
Slide 46
Slide 46 text
© DMM CONFIDENTAL ジェネリクス対応と v2
Slide 47
Slide 47 text
© DMM ジェネリクス対応とv2 • 2021年頃から sync/v2 とは別で議論がされている 47
Slide 48
Slide 48 text
© DMM 検討案 48 2. XxxOf 接尾辞 3. 型パラメータ デフォルト値 1. v2パッケージ をつくる
Slide 49
Slide 49 text
© DMM 案1. v2パッケージをつくる • まさしく sync/v2 のようにバージョンを分ける 49
Slide 50
Slide 50 text
© DMM 案1. v2パッケージをつくる • まさしく sync/v2 のようにバージョンを分ける 50 sync/v3, net/http/v10, ... のように乱立しそう
Slide 51
Slide 51 text
© DMM 案2. XxxOf 接尾辞 • PoolOf[T], MinOf[T] • XxxOf でジェネリクスとする • 元々ジェネリクスなものはそのまま Tree[K, V] 51
Slide 52
Slide 52 text
© DMM 案2. XxxOf 接尾辞 • PoolOf[T], MinOf[T] • XxxOf でジェネリクスとする • 元々ジェネリクスなものはそのまま Tree[K, V] 52 混乱しやすい
Slide 53
Slide 53 text
© DMM 案3. 型パラメータにデフォルト値 • ジェネリクス構文を拡張して互換性を保つ 53
Slide 54
Slide 54 text
© DMM 案3. 型パラメータにデフォルト値 • ジェネリクス構文を拡張して互換性を保つ 54 直感的でない
Slide 55
Slide 55 text
© DMM ジェネリクス対応とv2 • 結論は出ず... • sync/v2 パッケージでも同様の議論が生まれている • 差別化のために x/sync の Cond をいれてみてはという意 見も 55
Slide 56
Slide 56 text
© DMM CONFIDENTAL 感想とまとめ
Slide 57
Slide 57 text
© DMM 感想とまとめ • いろんな v2 パッケージのプロポーザルがある! • sync.Pool と sync.Map がジェネリクス対応するかも? • sync/v2 は今後のジェネリクス対応にも関わってきそうなので期 待 57
Slide 58
Slide 58 text
© DMM 参考 • https://github.com/golang/go/issues/71076 • https://research.swtch.com/interfaces • https://github.com/dominikh/go-tools/issues/302 • https://go-review.googlesource.com/c/go/+/24371?tab=comments • メモリアドレス - Wikipedia 58
Slide 59
Slide 59 text
© DMM ご清聴ありがとうございました!