Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Cloud ProfilerでGoアプリケーションのパフォーマンスをお手軽に計測できた/ColoplTech-01-03

COLOPL Inc.
January 27, 2022

Cloud ProfilerでGoアプリケーションのパフォーマンスをお手軽に計測できた/ColoplTech-01-03

※資料内の参照リンクを選択し閲覧する場合は、ダウンロードをお願いいたします

\積極的に技術発信を行なっております/
▽ Twitter/COLOPL_Tech
https://twitter.com/colopl_tech

▽ connpassページ
http://colopl.connpass.com

▽ COLOPL Tech Blog
http://blog.colopl.dev

COLOPL Inc.

January 27, 2022
Tweet

More Decks by COLOPL Inc.

Other Decks in Technology

Transcript

  1. prizm とは • コロプラで開発している対人や協力などリアルタイム性のある ゲームのためのフレームワーク ◦ サーバー: いわゆるリアルタイムサーバーを作るためのフレームワーク ◦ クライアント:

    リアルタイムサーバーと通信するクライアントの基盤ライブラリ • サーバーが Go で書かれている ◦ 今回は prizm を用いたアプリケーションのパフォーマンスを計測した話をします 3
  2. Contents • Cloud Profiler を使うことになった経緯 • プロファイラとは • Cloud Profiler

    ◦ 導入方法 ◦ 画面や設定項目の説明 ◦ 良かったところ 4
  3. Cloud Profiler を使うことになった経緯 • prizm を使ったタイトルのリリースが近づいたため負荷試験を実施 →prizm サーバーの CPU 使用率が高い!となった

    ◦ 試験対象のタイトルではほぼクライアント間のメッセージを中継しているだけ ▪ チャットメッセージの NG ワードチェックで正規表現をかけている程度 ◦ メッセージの送受信で CPU を使っているならいいが、他の要因があるなら潰したい • 負荷試験環境で prizm サーバーのパフォーマンスを計測したい →Cloud Profiler というものがあるらしい →Go なら Cloud Profiler を使えるぞ!使おう! 5
  4. プロファイラとは • 「プログラムの実行を通して情報を収集することで プログラムの性能を解析する」[1](動的解析)ためのツール ◦ CPU やメモリなどの資源をプログラムのどこで多く消費しているかが分かる =ボトルネックが分かる • Go

    には pprof という標準のプロファイラが存在 ◦ サーバーで pprof を扱う場合、計測結果は HTTP サーバーで公開 ▪ クラウド環境で用いる場合はアクセス制御などが必要で、 やってやれないことはないが面倒 [1] Wikipedia より 6 HTTP や gRPC などの サービスを提供 計測結果を HTTP で公開
  5. Cloud Profiler の紹介 • GCP で提供されているプロファイリングサービス ◦ GCP 以外でも動く(らしい) •

    Go、Java、Node.js、Python に対応 ◦ (少なくとも Go では)導入も簡単 • 統計的にパフォーマンスを計測しているため低オーバーヘッド パフォーマンスを 計測・アップロード ブラウザでパフォーマンスを確認 7
  6. Cloud Profiler の導入方法 • プロファイリングしたいコードに 右の赤枠で囲ったコードを追加 ◦ コンフィグ作ってスタートするだけ ▪ コンフィグの中身は後に説明

    ◦ 基本的にはこれだけで OK と ドキュメントには書いてある ▪ しかし GKE 環境の場合これだけでは動かない • GKE 環境で動かす場合、計測対象の プログラムが動く Pod に対して Workload-identity で Cloud Profiler の 権限を付与する必要がある package main import ( "cloud.google.com/go/profiler" ) func main() { cfg := profiler.Config{ Service: "cloud-profiler-test", ServiceVersion: "1.0.1", } if err := profiler.Start(cfg); err != nil { // error handling log.Fatal(err) } // 以下サーバーの実装 } 8
  7. Cloud Profiler がうまく動かなかったら • Cloud Profiler はうまくデータを GCP に 送れなくてもプログラムが異常終了せずに

    そのまま動いてしまう ◦ プロファイリングに失敗しても サービスは提供したいから? ◦ 5分程度待って GCP console でデータが 出てこない場合トラブルが起きてると 思って良さそう • profiler.Config の DebugLogging を true にすると動作ログが出力される ◦ 権限が足りなかったときはこれで気づけました package main import ( "cloud.google.com/go/profiler" ) func main() { cfg := profiler.Config{ Service: "cloud-profiler-test", ServiceVersion: "1.0.1", DebugLogging: true, } if err := profiler.Start(cfg); err != nil { // error handling log.Fatal(err) } // 以下サーバーの実装 } 9
  8. Cloud Profiler の画面 • GCP Console でパフォーマンスを Flame Graph の形式で確認できる

    ◦ 縦がコールスタック、横が処理の重さ( CPU 時間の長さなど)を表す ◦ 横軸はソート済みなので重い処理がどこかすぐに分かる ◦ pprof で見れる画面とほぼ同じだったりする 10
  9. Cloud Profiler の画面 • GCP Console でパフォーマンスを Flame Graph の形式で確認できる

    ◦ HandlerFunc の下で正規表現のコンパイル が走ってしまっている ▪ =正規表現のコンパイルをリクエストごとに実行してしまっている ▪ 実際のサービスで Cloud Profiler を使ったときも 正規表現周りで効率の悪い部分を発見した 11
  10. Cloud Profiler の画面と profiler.Config package main import ( "cloud.google.com/go/profiler" )

    func main() { cfg := profiler.Config{ Service: "cloud-profiler-test", ServiceVersion: "1.0.1", } if err := profiler.Start(cfg); err != nil { // error handling log.Fatal(err) } // 以下サーバーの実装 } • サービス(Service) ◦ プロファイルするプログラムの 識別子 ◦ コロプラではサービスを 用いて “dev” や “prod” の ような環境も分離している ◦ ドキュメントのサンプルが “myservice” なので ◦◦service にしたくなるけど 別にそうする必要はない 13
  11. Cloud Profiler の画面と profiler.Config package main import ( "cloud.google.com/go/profiler" )

    func main() { cfg := profiler.Config{ Service: "cloud-profiler-test", ServiceVersion: "1.0.1", } if err := profiler.Start(cfg); err != nil { // error handling log.Fatal(err) } // 以下サーバーの実装 } • バージョン (ServiceVersion) ◦ 文字通りバージョンを表し、 同じサービスでの区別が可能 ◦ コロプラでは同一の {アプリケーション、環境 } での機能追加時に バージョンを上げている ◦ バージョンアップ前後の パフォーマンス比較に使える ▪ 画面の「比較対象」 から比較先を選べる 14
  12. Cloud Profiler の良かったところ • コードへの組み込みが楽 ◦ Google のサポートが手厚い Go の利点

    ▪ PHP だとこうはいかずつらい • 簡単に動かせる割に強力 ◦ 「このままでも動くけど効率が悪い」系の問題をすぐに見つけられて良い ▪ 正規表現のコンパイルを都度走らせる部分の見落としに気づけた • かかる負荷が小さい ◦ 本番環境でもかけっぱなしで大丈夫なレベル ◦ メトリクス採取に用いている Prometheus exporter より小さかった • 無料 ◦ 30日間しかデータを保存できないという難点もある ▪ とはいえ長期的にデータを見たいケースはあんまりない 15
  13. まとめ • プログラムのパフォーマンスが気になったときはプロファイラを用いて 調査するととても良い • クラウド環境でのプロファイリングは GCP が提供する Cloud Profiler

    が便利 ◦ お手軽に使える ▪ 導入も簡単 ▪ 結果の確認も直感的 ◦ オーバーヘッドが小さいので本番環境でも使える ◦ 無料 16
  14. pprof の使い方 • 計測対象のプログラムに pprof を使うための数行のコードを追加 ◦ ファイルへ計測結果を出力して pprof に食わせる

    ▪ すぐに終了するプログラムで有用 ◦ HTTP サーバーとして計測結果を公開 ▪ サーバーなどの常駐プログラムで有用 ▪ もとのプログラムが HTTP サーバーの場合はハンドラを追加すれば OK • 出力したファイルや HTTP サーバーを用いてパフォーマンスを確認 ファイルに出力する方法 HTTPで公開する方法 HTTP や gRPC などの サービスを提供 計測結果を HTTP で公開 17
  15. • プロファイリングの結果は CLI とブラウザで確認できる ◦ ブラウザで見る場合は以下のコマンドを実行 ▪ go tool pprof

    -http [host:port] [prof file or http path] Flame Graph CLI のような表示 Graph CLI では対話的に操作できる ブラウザでは直感的に可視化 pprof のプロファイリング結果を確認する 18
  16. pprof をクラウド環境で使うのは少し難しい • サーバーがたくさん動くのでまとめる必要がある • ファイルに出力する場合、ファイルをサーバーから回収する必要がある ◦ 例えば Kubernetes で動かしている場合

    Pod が終了する前に回収する必要がある • サーバーとして公開する場合、アクセス制御が必要 ◦ HTTP サーバーではない場合、ポートをプロファイラ用に開ける必要も ◦ 開発環境ではまだいいけど、本番環境だと抵抗感が大きい 19