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
logica / Takuto Nagami
September 03, 2024
Technology
2
780
標準ライブラリの奥深アップデートを掘り下げよう!
2024/9/3 Go 1.23リリースパーティーにて発表した際の資料です。
time / unique / structsパッケージについて、詳細な解説を行っています。
logica / Takuto Nagami
September 03, 2024
Tweet
Share
More Decks by logica / Takuto Nagami
See All by logica / Takuto Nagami
プロポーザル一次〆切に向けて
logica0419
0
29
「海外登壇」という 選択肢を与えるために 〜Gophers EX
logica0419
0
700
Nekko Cloud、 これまでとこれから ~学生サークルが作る、 小さなクラウド
logica0419
2
960
Proposal Challengers 2025 募集説明会
logica0419
1
21
Kubernetesを知る
logica0419
19
6.3k
Resizing Animated GIFs Without CGO or Third-Party Libraries
logica0419
2
42
徹底比較!HA Kubernetes ClusterにおけるControl Plane LoadBalancerの選択肢
logica0419
2
380
外部カンファレンスで登壇しよう! 〜「強い」エンジニアへの一歩を踏み出す〜
logica0419
4
220
kube-vipとkube-proxy置き換えCiliumを積んだ究極のK3sクラスタを建てる
logica0419
4
640
Other Decks in Technology
See All in Technology
Larkご案内資料
customercloud
PRO
0
650
なぜ私は自分が使わないサービスを作るのか? / Why would I create a service that I would not use?
aiandrox
0
730
抽象化をするということ - 具体と抽象の往復を身につける / Abstraction and concretization
soudai
12
2.2k
SA Night #2 FinatextのSA思想/SA Night #2 Finatext session
satoshiimai
1
140
組織貢献をするフリーランスエンジニアという生き方
n_takehata
1
1.3k
Oracle Base Database Service 技術詳細
oracle4engineer
PRO
6
57k
ユーザーストーリーマッピングから始めるアジャイルチームと並走するQA / Starting QA with User Story Mapping
katawara
0
200
君も受託系GISエンジニアにならないか
sudataka
2
430
『衛星データ利用の方々にとって近いようで触れる機会のなさそうな小話 ~ 衛星搭載ソフトウェアと衛星運用ソフトウェア (実物) を動かしながらわいわいする編 ~』 @日本衛星データコミニティ勉強会
meltingrabbit
0
140
バックエンドエンジニアのためのフロントエンド入門 #devsumiC
panda_program
18
7.4k
表現を育てる
kiyou77
1
210
The Future of SEO: The Impact of AI on Search
badams
0
190
Featured
See All Featured
The Success of Rails: Ensuring Growth for the Next 100 Years
eileencodes
44
7k
Intergalactic Javascript Robots from Outer Space
tanoku
270
27k
Fireside Chat
paigeccino
34
3.2k
Why You Should Never Use an ORM
jnunemaker
PRO
55
9.2k
The Invisible Side of Design
smashingmag
299
50k
Agile that works and the tools we love
rasmusluckow
328
21k
Exploring the Power of Turbo Streams & Action Cable | RailsConf2023
kevinliebholz
30
4.6k
Site-Speed That Sticks
csswizardry
4
380
The Language of Interfaces
destraynor
156
24k
Into the Great Unknown - MozCon
thekraken
35
1.6k
A Philosophy of Restraint
colly
203
16k
Building Your Own Lightsaber
phodgson
104
6.2k
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