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
September 03, 2024
Technology
2
460
標準ライブラリの奥深アップデートを掘り下げよう!
2024/9/3 Go 1.23リリースパーティーにて発表した際の資料です。
time / unique / structsパッケージについて、詳細な解説を行っています。
logica
September 03, 2024
Tweet
Share
More Decks by logica
See All by logica
「認証認可」という体験をデザインする ~Nekko Cloud認証認可基盤計画
logica0419
2
250
超アナログ中心な印刷会社で「エンジニアリング」を見直す
logica0419
4
200
Pure GoでアニメーションGIFのリサイズを実装する
logica0419
0
400
isugata 〜ISUCONベンチマーカーのためのカッコいいHTTPレスポンスバリデーターを作る
logica0419
0
450
開発を愛する人が最高にISUCONを楽しむ方法
logica0419
0
660
DockerでProtobufをコンパイルしたい!
logica0419
13
1.4k
ISUCON練習に使えるベンチマーカーWeb UIを作った話
logica0419
0
190
Other Decks in Technology
See All in Technology
OR学会2024秋_短期収益と将来のオフ方策評価性能を考慮したクーポン割当方策混合比の決定
recruitengineers
PRO
4
430
20240906_JAWS_Yamanashi_#1_leap_beyond_the_AWS_all_certifications
tsumita
1
280
Monitor GraalVM Native Apps with OpenTelemetry
logico_jp
0
130
AWSを始めた頃に陥りがちなポイントをまとめてみた
oshanqq
1
3.4k
サーバー管理しないサーバーサービスManaged DevOps Pool
kkamegawa
0
110
たった1人からはじめる【Agile Community of Practice】~ソース原理とFearless Changeを添えて~
ktc_corporate_it
1
200
不動産tech Product Night#2_AIことはじめ_GA橋本
takehikohashimoto
0
120
突撃! 隣のAmazon Bedrockユーザー 〜YouはどうしてAWSで?〜
minorun365
PRO
3
330
contenteditableと向き合う
kikuchikakeru
2
290
Evolving DevOps Teams and Flexible Organizational Culture
kakehashi
1
260
四国クラウドお遍路 2024 in 高知 オープニング
yukataoka
0
190
Agile in Automotive Industry, puzzles and lights.
hiranabe
2
580
Featured
See All Featured
The Illustrated Children's Guide to Kubernetes
chrisshort
47
48k
How GitHub (no longer) Works
holman
310
140k
A Modern Web Designer's Workflow
chriscoyier
691
190k
Thoughts on Productivity
jonyablonski
66
4.2k
Optimizing for Happiness
mojombo
375
69k
Agile that works and the tools we love
rasmusluckow
327
20k
Clear Off the Table
cherdarchuk
91
320k
Art, The Web, and Tiny UX
lynnandtonic
294
20k
Gamification - CAS2011
davidbonilla
79
4.9k
実際に使うSQLの書き方 徹底解説 / pgcon21j-tutorial
soudai
166
48k
ピンチをチャンスに:未来をつくるプロダクトロードマップ #pmconf2020
aki_iinuma
103
48k
Principles of Awesome APIs and How to Build Them.
keavy
125
16k
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