sync/v2 プロポーザルの 背景と sync.Pool について
by
matumoto
×
Copy
Open
Link
Embed
Share
Beginning
This slide
Copy link URL
Copy link URL
Copy iframe embed code
Copy iframe embed code
Copy javascript embed code
Copy javascript embed code
Share
Tweet
Share
Tweet
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 ご清聴ありがとうございました!