📈

Cloud Profilerを導入してパフォーマンス改善をした話

2023/02/24に公開

こんにちは!
Magic Momentでテックリードをしている Miyake です。

弊社が開発するセールスエンゲージメントプラットフォームである Magic Moment Playbook では営業活動にかかせないツールとの連携を多数を行っており、私が所属するData IntegrationチームではSalesforceなどのCRMツールを中心とした外部連携機能の開発をしています。

ただいまエンタープライズ企業のお客様が続々と増えており、取り扱うデータ規模が増大中です。それに応じて負荷対策や取り込み速度の性能改善などといったパフォーマンス改善に注力しておりまして、その過程で Cloud Profiler を利用したパフォーマンス改善の取り組みを行ったので、その内容をシェアしたいと思います。

Cloud Profiler とは

Google Cloudマネージドなプロファイリングツールです。公式ドキュメントはこちら

提供されている機能としては収集したパフォーマンスデータをフレームグラフとして確認できるといった形で、他に期間比較や関数ごとのパフォーマンス推移を折れ線グラフで確認できるヒストリー機能などもありました。

弊社ではサーバーサイドの開発にGo言語をメインで使っており、Go言語のプロファイラで有名なものとして google/pprof などがありますが、Google Cloud上のサービスへの導入に関してはCloud Profilerでは数行のコードを埋め込むだけで簡単にできるので便利です。

ただしサポートされているサービス・言語は限られているので注意が必要です。またデータの保存期間も30日間と短いので、データを中長期的に管理したい場合には適していません。

Cloud Profiler の導入方法

先述のサポートされているサービス・言語に当てはまる環境であれば、数行のコードを埋め込むだけで導入が完了します。

例えば、Go言語の例で言えば以下のような形です。

package main

import (
  "cloud.google.com/go/profiler"
)

func main(){

  // ...

  // goroutine内で起動しても機能しました。
  go func(){
    conf := profiler.Config{
      Service:        serviceName,
      ServiceVersion: revision,
    }

    // 初期化エラーを回避するためにwait。
    time.Sleep(time.Second * 3)

    if err := profiler.Start(conf); err != nil {
      logger.Errof(err, "Failed to start Cloud Profiler")
    }
  }()

  // ...
}

実際には独自のパッケージとしてラップして利用してはいますが、profilerパッケージをそのまま利用する場合は上記のような形で動きます。

途中Sleepを挟んでいる理由としては、以下のようなエラーが出たからです。

failed to get zone from Compute Engine metadata: Get \"http://xxx.xxx.xxx.xxx/computeMetadata/v1/instance/zone\": dial tcp xxx.xxx.xxx.xxx:80: connect: connection refused

パッケージの中身を見てみると、アプリケーションを起動しているGCEインスタンスのメタ情報(ゾーン情報など)を取得するためにMetadata ServerへのAPI通信をしている部分だったのですが、起動直後は疎通ができないのかエラーが出てしまいました(ちなみにGKE上のアプリだったので、GKE特有の可能性もあります)。

こちらについてはまだ詳しく調査できていませんが、いったんSleepで回避できたのでそのようにしました(goroutineで起動しても問題なく利用できたので、アプリケーションの起動遅延を起こさずに利用できます)。

性能改善例

実際に使ってみた時の内容をご紹介したいと思います。

弊社のサービスはマイクロサービスアーキテクチャで構成されており、バックエンドではサービス間でのAPI通信が多数行われております。

その中で外部連携ツールからの取り込み速度の改善をしている際に、あるサービスへのあるgRPCリクエストのレイテンシが遅いことに気づき、何が問題なのかを調べるためにCloud Profilerを入れてみました。

該当のリクエストのデータがこちらです。

CPU使用時間(改善前)

Cloud Profiler - CPU使用時間(改善前)

メモリ使用量(改善前)

Cloud Profiler - メモリ使用量(改善前)

赤枠で囲った関数がCPU・メモリ共に処理の大部分を占めていることがわかります。

こちらの関数の仕様を調査してみると、本来の目的としては別のgRPCメソッドでの利用をメインの目的としたもので、今回の調査ターゲットのgRPCメソッドでは不要なデータが取得されていることがわかりました。

必要最低限なデータのみを取得するような関数を新たに実装しそちらを利用するように修正後デプロイし、収集したデータがこちらになります。

CPU使用時間(改善後)

Cloud Profiler - CPU使用時間(改善後)

メモリ使用量(改善後)

Cloud Profiler - メモリ使用量(改善後)

数値を比較すると以下になります。

改善前 改善後
CPU 2500ms 176ms
Memory 335MiB 7MiB

問題となっていた部分の処理の負荷について大幅に改善できました🎉

まとめ

Cloud Profilerは、さくっとプロファイリングをして性能分析をしたい場合に便利なことがわかりました。

導入方法がシンプルなので、プロファイリングツールを使ったことがない人でも簡単に性能分析が始めることができると思います。

また公式ドキュメントにプロファイルの見方が説明されており、フレームグラフの見方パフォーマンスデータの評価の仕方などが記載されているので、ご確認いただくのがおすすめです。

最後に

弊社 Magic Moment では、フロントエンド・バックエンドにかかわらず全方位的にエンジニアを募集中です!Magic Momentに少しでも興味を持っていただけたら是非エントリーください!

8/30にはFindy様主催のイベントにMagic Momentから石田さんが登壇されます!
よろしければぜひご視聴ください!

さらに、こちらのイベントも8/29開催予定です!こちらはオンラインイベントです。Magic Momentの開発がどんなものか興味を持っていただいた方は是非ご参加ください!

Discussion