FlaskアプリケーションをGunicornで実行しているとしましょう(クールだからです)。いくつかのエンドポイントがありますが、そのうちの一つが問題を起こしています。さあ、py-spyゴーグルを装着して、何が起きているのか見てみましょう。

容疑者:CPUを食い尽くすハンドラー

こちらが問題を起こしているシンプルなFlaskアプリです:


from flask import Flask
import time

app = Flask(__name__)

@app.route('/')
def hello_world():
    return 'Hello, World!'

@app.route('/cpu_hog')
def cpu_hog():
    # ここで問題が発生しています
    result = 0
    for i in range(10000000):
        result += i
    return f"I counted to {result}. Aren't you proud?"

if __name__ == '__main__':
    app.run()

ネタバレ注意:この/cpu_hogエンドポイントが主な容疑者です。

登場:py-spy、プロファイリングの相棒

まずは、py-spyをインストールしましょう:


pip install py-spy

次に、Gunicornサーバーを起動します:


gunicorn app:app -w 4

ここからが楽しい部分です。別のターミナルで、py-spyをWSGIサーバーに適用します:


sudo py-spy record -o profile.svg --pid $(pgrep -f gunicorn) --subprocesses
プロのヒント:ここではsudoを使用していますが、py-spyがプロセスにアタッチするために必要です。sudoの使用には注意が必要です。大きな力には...まあ、続きはご存知でしょう。

プロファイリング結果の解読:CSI: CPU版

/cpu_hogエンドポイントを何度か叩いた後(どうぞ、待っています)、py-spyが生成した美しいSVGフレームグラフを見てみましょう。

Flame Graph
CPU使用率のフレームグラフ。コードの犯罪現場のようです。

何が見えますか?cpu_hog関数でのCPU使用率の炎のような高まりです!まるでウォルドを見つけたかのようです、もしウォルドが非効率の縞模様のシャツを着たパフォーマンスのボトルネックだったら。

フレームグラフの分解

  • 各バーの幅はその関数で費やされた時間を表しています
  • 色は?ただの飾りです。あまり深く考えないでください。
  • 積み重ねられたバーはコールスタックを示しています。遅さのサンドイッチのようです。

プロットが厚くなる:発見の分析

py-spyの冒険から何を学びましたか?

  1. cpu_hog関数はその名に恥じない動きをしています。まるで流行が終わるかのようにCPUを占有しています。
  2. 犯人は?無害に見えるforループです。洗濯機がスピンサイクルで止まっているかのように多くの反復を行っています。
  3. 他のエンドポイント(hello_worldなど)はほとんど見えません。アプリの無名のヒーローです。

プロットのひねり:CPUホグの最適化

パフォーマンスの犯人を現行犯で捕まえたので、改善しましょう:


@app.route('/cpu_hog_reformed')
def cpu_hog_reformed():
    # より効率的な方法で数を合計しましょう
    result = sum(range(10000001))
    return f"I efficiently counted to {result}. Much better, right?"

この新しいエンドポイントで再度py-spyを実行すると、フレームグラフは炎のような高まりではなく、心地よいキャンプファイヤーのように見えるはずです。

学んだ教訓:py-spyプロファイリングのプレイブック

このプロファイリングの冒険からどんな知恵を得られたでしょうか?

  • 信頼しても確認を:シンプルに見えるコードでもパフォーマンスの悪夢になることがあります。最適化する前に必ずプロファイルを確認しましょう。
  • py-spyは友達:侵入せず、速く、CPU使用率のビジュアルを提供します。愛さずにはいられません。
  • アルゴリズム的に考える:時には、最良の最適化はより効率的なアルゴリズムを使用することです。ビッグO記法はホワイトボード面接だけのものではありません!
  • WSGIサーバーは複雑な獣:私たちはアプリだけでなく、WSGIエコシステム全体をプロファイルしていることを忘れないでください。すべてが連鎖しています!

エピローグ:冷静にプロファイルを続けよう

py-spyでのプロファイリングは、コードの健康診断のようなものです。いくつかの不快な真実を明らかにするかもしれませんが、最終的にはアプリケーションが感謝するでしょう。そして、ウェブリクエストを処理する際には、ミリ秒単位での違いが重要です!

次回、Python WSGIサーバーが問題を起こしたときは、慌てずにpy-spyを手に取り、フレームグラフを生成し、CPUホグを追い詰めましょう。ユーザー(と上司)が感謝してくれるでしょう。

考えるための食料:アプリケーションの他の部分もpy-spyプロファイリングセッションから恩恵を受けることができるでしょうか?データベースクエリ?外部APIコール?可能性は無限大です!

さあ、プロファイルを続けましょう、あなたは素晴らしいコード探偵です!