Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
標準ライブラリの奥深アップデートを掘り下げよう!
Search
Takuto Nagami
September 03, 2024
Technology
2
890
標準ライブラリの奥深アップデートを掘り下げよう!
2024/9/3 Go 1.23リリースパーティーにて発表した際の資料です。
time / unique / structsパッケージについて、詳細な解説を行っています。
Takuto Nagami
September 03, 2024
Tweet
Share
More Decks by Takuto Nagami
See All by Takuto Nagami
Fundamentals of Memory Management in Go: Learning Through the History
logica0419
0
84
GopherCon Tourのつくりかた
logica0419
2
64
Go言語はstack overflowの夢を見るか?
logica0419
2
710
あなたの言葉に力を与える、演繹的なアプローチ
logica0419
1
220
GC25 Recap+: Advancing Go Garbage Collection with Green Tea
logica0419
1
720
GopherCon Tour 概略
logica0419
2
420
言葉の壁を越えて ~Gophers EXと歩む海外登壇への道~
logica0419
1
61
Maintainer Meetupで「生の声」を聞く ~講演だけじゃないKubeCon
logica0419
1
620
理想の英語力に一直線!最高効率な英語学習のすゝめ
logica0419
6
470
Other Decks in Technology
See All in Technology
仕様は“書く”より“語る” - 分断を超えたチーム開発の実践 / 20251115 Naoki Takahashi
shift_evolve
PRO
1
950
ABEMAのCM配信を支えるスケーラブルな分散カウンタの実装
hono0130
3
490
プログラミング言語を書く前に日本語を書く── AI 時代に求められる「言葉で考える」力/登壇資料(井田 献一朗)
hacobu
PRO
0
160
ググるより、AIに聞こう - Don’t Google it, ask AI
oikon48
0
920
[mercari GEARS 2025] Keynote
mercari
PRO
1
280
大規模モノレポの秩序管理 失速しない多言語化フロントエンドの運用 / JSConf JP 2025
shoota
0
160
機密情報の漏洩を防げ! Webフロントエンド開発で意識すべき漏洩パターンとその対策
mizdra
PRO
9
3.5k
探求の技術
azukiazusa1
7
2.3k
マーケットプレイス版Oracle WebCenter Content For OCI
oracle4engineer
PRO
4
1.3k
コンピューティングリソース何を使えばいいの?
tomokusaba
1
170
持続可能なアクセシビリティ開発
azukiazusa1
4
110
Flutterで実装する実践的な攻撃対策とセキュリティ向上
fujikinaga
2
430
Featured
See All Featured
Distributed Sagas: A Protocol for Coordinating Microservices
caitiem20
333
22k
The Art of Delivering Value - GDevCon NA Keynote
reverentgeek
16
1.8k
The Cult of Friendly URLs
andyhume
79
6.7k
RailsConf 2023
tenderlove
30
1.3k
Optimising Largest Contentful Paint
csswizardry
37
3.5k
YesSQL, Process and Tooling at Scale
rocio
174
15k
Cheating the UX When There Is Nothing More to Optimize - PixelPioneers
stephaniewalter
285
14k
Unsuck your backbone
ammeep
671
58k
Agile that works and the tools we love
rasmusluckow
331
21k
Performance Is Good for Brains [We Love Speed 2024]
tammyeverts
12
1.3k
Designing for Performance
lara
610
69k
XXLCSS - How to scale CSS and keep your sanity
sugarenia
249
1.3M
Transcript
logica X: @logica0419 GitHub: @logica0419 標準ライブラリの 奥深アップデートを 掘り下げよう!
自己紹介 • logica (ろじか) • 千葉工業大学 情報科学部 情報ネットワーク学科 3年 •
ネットワークコンテンツ研究会 所属 ◦ 数人の自宅サーバーをVPNで繋いでクラウド基盤 作ろうとしてます • 最近、GoLabというイタリアで行われる カンファレンスでの登壇が決まりました
Go 1.23だ!!!
Go 1.23だ!!! イテレータ(range over func)だ!
Go 1.23だ!!! イテレータ(range over func)だ!
ところで…
ところで…
ところで…
ところで…
全部の変更 説明できる人?
説明できる方は 素晴らしい!
今回のアプデ、難しい • そもそも需要が少ない ◦ 問題意識を持つ人が少ない部分へのアプローチ ◦ 特定の課題を解決する上では非常に強力 • 理解するために、事前知識が必要 ◦
特にuniqueとstructsパッケージ ◦ メモリに関する結構深めの知識が必須 でも、理解できるときっと面白い!
今日は 前提知識からしっかり 理解することを目指します! 頑張っていきましょう!
timeの重要な変更 (time.Timer と time.Ticker)
time.Timer / time.Tickerおさらい • time.Timer ◦ 1回のイベントを表す ◦ 指定した時間が過ぎると、Timer.Cから現在時刻が 送られる
• time.Ticker ◦ Timerの繰り返し版 ◦ 指定した間隔で、Ticker.Cから現在時刻が送られ 続ける type Timer struct { C <-chan Time } type Ticker struct { C <-chan Time }
timeの重要な変更 (time.Timer と time.Ticker) 1. Stop()が呼ばれなくてもGCされる
そもそもGCとは?を超簡単に • プログラムの基本的なデータフローはバケツリレー ◦ 関数から関数に引数と戻り値で受け渡す • メモリ内をヒープ・スタックという2つの領域に分けて データを管理する ◦ バケツリレーはスタック
◦ バケツリレーで共有しない ものはヒープ ▪ ポインタで取り出す
ヒープ・スタックの使い分けとGC • スタックだけだと不合理な場合がある ◦ 大きなサイズの構造体は、バケツリレーだと コピーのコストが大きい などなど… • Garbage Collection
(GC) ◦ スタックのデータは関数と寿命が一致するが、 ヒープは溜まる一方 ◦ 使い終わったヒープのデータを検出・削除する プロセスがGC
来年のGo Conferenceの プロポーザルで詳しい話を 出したいと思っています… 応援してください
• 今までのTimer / Tickerは、以下の条件だと使われ ないことが分かっていてもGCされなかった ◦ Timer: Stop()されてない || 時間が過ぎてない
◦ Ticker: Stop()されてない • ↑ のため、関数内でしか使わないTimer / Tickerを 生成したときはdefer Stop()する必要があった • Go 1.23からはしなくても良くなります! Stop()が呼ばれなくてもGCされる
timeの重要な変更 (time.Timer と time.Ticker) 1. Stop()が呼ばれなくてもGCされる 2. channelがバッファ0に
Timer / Tickerのchannel • 今までは1のバッファがあった ◦ Stop()やReset()を呼んだ後でも、呼び出し前に 入れられた値は取り出せてしまう ◦ これがStop()やReset()の使用を難しくしていた
• これからはバッファが0になる ◦ channelから値をすぐに出さなくてもTimer / Tickerが狂うとかはない ◦ Stop()やReset()を呼ぶと値は取り出せなくなる
go.modとasynctimerchan=1 • 今回の挙動が適用されるのは、go.modのgoの行の バージョンが1.23.0以降の時だけ ◦ 古いバージョンを書いていたら、コンパイラが 新しくても古い挙動が適用される • GODEBUG=asynctimerchan=1をつけてビルドすると 古い挙動が適用される(channelもGCも)
◦ Go 1.27までは使える予定らしい
uniqueの追加
uniqueって何? • なんかsliceから重複した値消し去ってくれるとか? • stringの中の同じ文字検知してくれるとか? → 全然違います! uniqueパッケージは、interningという かなり攻めたメモリ使用量の削減手法を Goに実装したもの
です。
interning?
これはinternship
interningとは • 以下のプログラムを考えてみよう func main() { values := make([]int, 2)
values[0] = 10 values[1] = 10 fmt.Println( values[1], values[2], ) }
interningとは • 以下のプログラムを考えてみよう func main() { values := make([]int, 2)
values[0] = 10 values[1] = 10 fmt.Println( values[1], values[2], ) } メモリ使用イメージ
interningとは • 以下のプログラムを考えてみよう func main() { values := make([]int, 2)
values[0] = 10 values[1] = 10 fmt.Println( values[1], values[2], ) } メモリ使用イメージ (同じ値が複数あるの 無駄なのでは…?)
interningとは これを
interningとは これを こうしたい
interningとは これを こうしたい 1つの値にまとめて 容量を削減
interningとは これを こうしたい 1つの値にまとめて 容量を削減 これがinterning
uniqueパッケージ • Handle ◦ interningを実装した型 ◦ 実態はTのポインタだと思えばOK ◦ Value()メソッドで実際の値を引き出せる •
Make() ◦ Handle型を生成するための関数 ◦ もし過去に同じvalueでHandle型が生成されて いたら、その時のポインタを流用する type Handle[T comparable] struct {} func (h Handle[T]) Value() T func Make[T comparable](value T) Handle[T]
使い方 • さっきのプログラムを書き換えてみる func main() { values := make( []unique.Handle[int],
2 ) values[0] = unique.Make(10) values[1] = unique.Make(10) fmt.Println( values[1].Value(), values[2].Value(), ) } func main() { values := make( []int, 2 ) values[0] = 10 values[1] = 10 fmt.Println( values[1], values[2], ) }
使い方 • さっきのプログラムを書き換えてみる func main() { values := make( []unique.Handle[int],
2 ) values[0] = unique.Make(10) values[1] = unique.Make(10) fmt.Println( values[1].Value(), values[2].Value(), ) } メモリ使用イメージ
stringへの特殊な挙動(string interning) • stringは「変更不可能なポインタ」と呼ばれる ◦ ポインタだが、その実体が変更不可 ◦ unsafe.StringData()でアドレスを取得可能 • stringに対してinterningを行うと、このアドレスが
同じ実体に対して揃う ◦ 「string interning」 と呼ばれる
stringへの特殊な挙動(string interning) • 本来interningとstring interningはちょっと違う概念 ◦ interning: 本来はオブジェクトが対象 ◦ string
interning: 文字列型限定 • 今回のuniqueパッケージは、実際は interningとstring interningを同じインターフェース で使えるようにしたもの と言えるかな…?という感じ ◦ Pythonとかも一緒(というかPythonは自動でやる)
使いどころ • 正直そう無いかもしれないが、効くところには効く ◦ 同じ値を色んな箇所で何度も使う場合 ◦ ↑ 特に値がstringや容量が大きい構造体の場合 • net/netipの例
- IPアドレスのプロパティをinterning type Addr struct { addr uint128 z unique.Handle[addrDetail] } type addrDetail struct { isV6 bool // IPv4 is false, IPv6 is true. zoneV6 string // != "" only if IsV6 is true. }
structsの追加
structsって何? • structに対して便利な機能を提供してくれる ユーティリティーだと思ってた! → 全然違います! structsパッケージは、structに関して、 メモリレイアウトのような言語仕様に関わる プロパティを変更できるようにするものです。
structsパッケージ type HostLayout struct {} • 今回追加された変更可能プロパティは1つ • HostLayout ◦
埋め込まれた構造体のメモリレイアウトが、ホスト OSのC言語ABIに則ることを保証する • 使い方 type Example struct { _ structs.HostLayout // こんな感じで差し込むだけ Value string }
ABI? メモリレイアウト? なんじゃそりゃ? みんな「?」だと思うので、1つずつ確認しましょう
ABI • Application Binary Interface (ABI) ◦ OSとバイナリ / バイナリ同士の約束ごと
◦ バイナリの中で変数がどのようにメモリに入るか / 関数がどのように呼ばれるか などを規定する ◦ CGOで特に重要(Goから直にCバイナリを呼ぶので) • 参考: Application Programming Interface (API) ◦ アプリケーション同士の約束事 ◦ どんな機能を持ち、どんな風に使うかを定義する
ABI • Goは独自のABIを持っている ◦ https://go.googlesource.com/go/+/refs/heads/ dev.regabi/src/cmd/compile/internal-abi.md • Cも、コンパイラごと(GNUとかmuslとか)にABIを 持っている ◦
なので、ホストOSごとにCのABIは異なる ◦ 「ホストOSのC言語ABI」はこのこと
メモリレイアウト • ABIの中で、特に変数がどんな風にメモリに入るかを 定義している部分 ◦ 各型のバイト数やアライン、 structのメモリへの積み方 などが書いてある • Goの場合の例
◦ 型のバイト数は→ ◦ structはフィールド順
改めてstructsパッケージ type HostLayout struct {} • 今回追加された変更可能プロパティは1つ • HostLayout ◦
埋め込まれた構造体のメモリレイアウトが、ホスト OSのC言語ABIに則ることを保証する • 使い方 type Example struct { _ structs.HostLayout // こんな感じで差し込むだけ Value string }
なぜstructsパッケージが必要なのか • 元々Goのメモリレイアウトの実装は、ホストOSの C言語ABIに強く依存している ◦ CGOを使うとき、ホストOSのC言語ABIと揃って いないと壊れる可能性がある ←これ、稀では? • structsパッケージがあると、メモリレイアウトを
崩したとき壊れるstructを明示できるため、メモリ レイアウトを崩すメモリ最適化ができる! ◦ structをフィールド順に従わず配置する など
すなわち、HostLayoutは 付けた物を変えるんじゃなく 付けない物を変える下準備です! これだけ皆覚えて帰って下さい
まとめ と 宣伝
「自分使わないな」って機能も 深堀りすると面白いって 思ってもらえたら幸いです! 超スピードで駆け抜けてしまって申し訳ないです…
“Go Far”s Japan プロジェクト (仮) • 僕の人脈・ノウハウ・やる気全てを動員して、日本の Gopherたちを海外カンファレンスに引き込んでいく プロジェクトをやりたいと思っています! ◦
Gophers Japanと協力してやりたいですがまだ 企画書を書いていないです • やりたいこと ◦ 国内英語 / 日本語同時発表カンファレンス ◦ プロポーザルのクオリティUP支援 などなど!
ありがとう ございました
参考文献たち • https://go.dev/doc/go1.23 • https://pkg.go.dev/ • https://pythontutor.com/ • https://github.com/golang/go/issues/62483 •
https://future-architect.github.io/articles/20240719a/ • https://ikorin2.hatenablog.jp/entry/2019/12/16/195847 • https://qiita.com/kahibella/items/cd8b48f1d2c109b76e10 • https://speakerdeck.com/ymotongpoo/memory-manageme nt-in-go • https://cs.opensource.google/go/go/+/refs/tags/go1.23. 0:src/net/netip/netip.go • https://github.com/golang/go/issues/66408 • https://satoru-takeuchi.hatenablog.com/entry/2020/03/ 26/011858