2023/06/02、Go Conference 2023に参加してきました。初参加です。オンライン開催なのでオンライン参加です。
しっかり集中してカンファレンス参加したのは JJUG CCC 2021 Spring以来?
まとめ
一番残しておきたいまとめを最初に書いておきます。
セッションの内容は実務レベルのものから実装中身深掘りなど、様々でした。 個人的には実装中身深掘りシリーズが目から鱗で、自分ひとりでコード読んでても理解できなさそうなところが丁寧に解説されていて、 それを参考にチャレンジしようという気持ちになりました。そしてまとめ方皆さんとても上手い。。
特に、
- Goのメモリ管理
- echoなどのHTTP Router処理
- sync.Mutex
これらは普段お世話になってばかりなのでしっかり理解したい。
また、明日から業務に即活かすためにやることは以下が浮かびそう
- Go Style Guide読む
- Go Proverbs読む
- Fun with Slice 読んでSliceの注意点覚えておく
会社の人にもいろいろ展開していこう。
セッション聞いたメモ
以下、セッションを聞いた自分用メモです。あまり整理されてないので元のスライドなどきちんと読むのがよしです。
タクシーアプリ『GO』高速マッチングシステムで実践したGoチューニングテクニック
https://gocon.jp/2023/sessions/A1-SP/
- リクエスト→レスポンスすぐに返すのではなく、数秒レベルのバッチで一気にレスポンス返す
- マッチングロジックはPythonでステートレス、それ以外はGo
golang.org/x/sync/semaphore
で並列数制御errorgroup
は1つのgo routineしか返せないので、独自errorgroup
を作成
アーキテクチャ設計の試行錯誤が垣間見れる感じで面白かった。
無理なく始めるGoでのユニットテストの並行化戦略
https://gocon.jp/2023/sessions/A2-SP/
スライド: https://speakerdeck.com/shohata/go-conference-2023
- 並行と並列の言葉の定義、大事
go test
の-p
と-parallel
は別物-p=2
とすると2つのテストプロセスが実行される-parallel=2
とするとパッケージの並列化
-p
はデフォルトで設定、-parallel
はt.Parallel()
を埋め込む必要性- 平行化したテストで
os.Setenv
使うはNG、t.Setenv
使おう- ↑
t.Parallel
と併用するとpanicすることも
- ↑
- ループ変数再定義がmust,
tt := tt
- (最近
go vet
で検知できるようなったような…?)
- (最近
t.Parallel()
自動付与- https://github.com/achiku/pgtxdb でDB並列化
- https://github.com/DATA-DOG/go-txdb のポスグレ向け改良版っぽい
業務でgo-txdb使いはじめたとこだが若干使いにくい部分あったのでpgtxdbもwatchしたいとこ
Fun with Slices
https://gocon.jp/2023/sessions/B3-L/
- Sliceの内部構造の話
reflect.SliceHeader
でスライスのヘッダ要素みれる- Sliceから
[:1]
などで取り出したものにappend
したりすると、元の要素にも影響する- メモリ空間を考えてみれば当たり前な話
- 並行処理でSliceに追加するときはsyncでなくchannel使おう!
- Don’t communicate by sharing memory, share memory by communicating.
- Read the proverbs! (Go Proverbs を読もう!)
Go Proverbs、又聞きばかりなのできちんと読まないと。
「Go Style Guide」から学んだ可読性の高いコードの書き方
https://gocon.jp/2023/sessions/A4-S/
スライド: https://speakerdeck.com/andpad/go-style-guide-karaxue-ndake-du-xing-nogao-ikodonoshu-kifang
- https://google.github.io/styleguide/go/
- ゼロ値は設定しない、それによってOptionの場合は指定した項目を目立たせる
- Genericsは使わないで済むなら使わない
- interface受け取るだけで済むならGenericいらない
fmt
で"
を出力するなら、\"
でなく%q
使おう- pkg名でローカル変数と被りそうなものは使わない
- かぶるなら
pkg
suffixつける、net/url
→urlpkg
とか
- かぶるなら
- すべての場面で正しいというわけではない、チームのフェーズや規模等によって重要視するものは異なる
ブクマだけしてて読んでなかった、チームで輪読したいところ。
次なるrouterパッケージ選定のしざまと決め手について
https://gocon.jp/2023/sessions/A6-SP/
スライド: https://speakerdeck.com/yuzuy/ci-narurutapatukezixuan-ding-nosizamatojue-meshou-nituite
- https://github.com/gorilla/mux がarchiveされたので移行どうする問題
- std,echo,gin,chiあたり検討
- (forkして自分ら管理、とかその他fork先を探る、という手は考えなかったかというのも気になった)
- https://techgaun.github.io/active-forks/index.html#https://github.com/gorilla/mux 活発なフォーク先特になさそうではある、、
- chiはかなり薄い感じでよさそう
- うちもecho依存がややつらいところあるので…
評価軸つくって〜なところ丁寧にされてて好印象でした。
どうしてもcgoから逃げられなくなったあなたに知ってほしいcgoの使い方入門
https://gocon.jp/2023/sessions/B7-L/
- スライド見やすい、cgo導入による負担の大きさのとこなど
- recoverできなくなるのとか辛そう
- cgoに関する公式Docはとても少ない
- https://www.swig.org/
- SWIGの使い方など
- 文字列の扱いの難しさ
SWIG知らなかった、頭の片隅に置いておく。
EchoやGinはなぜ速いのか?Goで高速なHTTP routerを作るコツ
https://gocon.jp/2023/sessions/B8-S/
スライド: https://docs.google.com/file/d/1Jh0j2UD4VZjck_34XEA3OgzruLoiZeci/edit?filetype=mspresentation
sync.Pool
がHTTP Routerのユースケースと相性よい- echo,ginはRadix tree
- 静的ルーティングならTrie treeがはやい、それつかえば?
/health
がマッチするが/healthy
でくる場合、backtrackが発生、これに弱い
- Radix treeは実装が複雑
- パスパラメータ、独自Contextに持たせたほうが速い
- chiみたいに
context.Context
だと遅い
- chiみたいに
- 関数呼び出しを減らす、echoは
goto
利用(サブルーチン呼び出し的に)
echoの中身片足突っ込もうとしてやめた自分にとってはかなり面白い内容だった。
Go1.19から始めるGCのチューニング方法
https://gocon.jp/2023/sessions/B9-S/
スライド: https://speakerdeck.com/hagatake/go1-dot-19karashi-merugcnotiyuningufang-fa
- GoのGCの中身詳しく解説
GOGC
,GOMEMLIMIT
をセットして実際のプロダクトでパフォーマンス確認- Goが完全制御化、Goだけが動いているコンピューティングリソースであれば
GOMEMLIMIT
導入の余地あり
スライド見やすかった、あとで振り返る。
Go1.20からサポートされるtree構造のerrの紹介と、treeを考慮した複数マッチができるライブラリを作った話
https://gocon.jp/2023/sessions/A10-S/
スライド: https://speakerdeck.com/convto/introduction-of-tree-structure-err-added-since-go-1-20
- Go 1.20のエラー連結はtree構造
- proposal golang/go 53435
- splitとかwalkとか、需要あるかもだがデザインについて議論の余地→まずはコア仕様のみ
個人的には今のところ今の仕様通りで困ってなかったが…場合によっては困るかも、今後の動向に注目したい。
Goのメモリ管理
https://gocon.jp/2023/sessions/B11-S/
スライド: https://speakerdeck.com/ymotongpoo/memory-management-in-go
- goroutineのスタックは2KB
- ヒープに注目
- オブジェクトを初期化→サイズにあったmcentral内のmspanが割り当てられる
- 基本的なことからざっくりheapメモリまわりの紹介
- size/runtime/sizeclasses.go で様々なサイズのmspanがみれる
- TCMalloc : Goのspanアロケートはこれベース、これだけでも覚えて帰ろう
メモリ管理の基礎からGoでの利用方法まで、Overview分かる感じでよかった。
High performance regular expressions using RE2 and WebAssembly, no cgo required
https://gocon.jp/2023/sessions/B12-S/
- Goの正規表現は遅い
- https://github.com/google/re2 がはやい
- https://github.com/wasilibs/go-re2 RE2をWASM化してwazeroで動かしてGoで呼ぶ
- C++を直接cgoなどから呼び出せない、CのAPIを呼ぶので
- メモリは結構食う、並行数が少なくなる?
- WASMの今後の仕様次第で改善できそう
- 標準regexpと完全互換
コアな内容。Javaの正規表現も遅くてC++実装の呼ぶ、とか以前やったの思い出した…。Go標準の正規表現遅いってことは覚えておくとよいのかも。
net/http/httptest.Server のアプローチをテスト戦略に活用する
https://gocon.jp/2023/sessions/A13-S/
スライド: https://speakerdeck.com/k1low/go-conference-2023
- テストの実行速度と決定性でSmall,Medium,Largeテストに分ける
- アーキテクチャ未完状態ではMediumテストで、アーキテクチャの変更にもつよく
- シナリオごとにYAMLファイル作成、それをもとにhttp clientなど実行
- https://github.com/k1LoW/runn
分散サービスで有用そうなアプローチ。モノリスであればここまでやる必要性はなさそう。
sync.Mutexの仕組みを理解する
https://gocon.jp/2023/sessions/A14-S/
スライド: https://speakerdeck.com/ffjlabo/sync-dot-mutexnoshi-zu-miwoli-jie-suru
- sync.Mutex,stateとsema2つの状態変数
- stateをロック状態にしたとしても、1goroutineがアクセスしていることを保証できない→semaを用いてロック確保
- semaでのロック取得も無理なら次にスケジューリングされるまでgoroutineは一時停止
- スケジューリングのruntimeまわりはあまり理解できていないかも
- semaだけでよいのでは?
- 基本はgoroutine空間、競合が起きたときはruntime空間
- goroutine,runtimeの間のコンテキストスイッチを減らす
しっかり深掘りされてて良かった、途中のまとめで理解度確認しながら、かつ更になぜ?が生まれていく流れが面白かった。
以上。裏セッションだったりLTだったりは省略、気になるところは後で振り返る。