Python メモリプロファイラ:コード変更なしで最も RAM を消費するオブジェクトを特定する
コードを一行も変更せずに Python のメモリ使用量をプロファイリングするには、OpenResty XRay を稼働中のプロセスにアタッチするだけです。独自開発の Python GC オブジェクトメモリ分布フレームグラフが、どのオブジェクト・モジュール・辞書が最も RAM を消費しているかを正確に指し示し、それぞれに至る完全なデータ参照パスを提示します。
以下では、未変更の gunicorn プロセスに対してこの分析をリアルタイムで実行します——@profile デコレータも再起動も不要です——さらに、メモリを浪費している箇所を継続的に洗い出す自動レポートもご紹介します。Python コードのメモリリークや大規模なメモリ使用は、もはや謎ではありません!
どの Python プロセスが最もメモリを消費しているかを特定する
top コマンドを実行してメモリ使用状況を確認します。gunicorn という名前の Python プロセスが最もメモリを消費しており、RSS が 600MB を超えていることがわかります。
ps を実行して詳細を確認します。ここでは、Linux ディストリビューションに付属の標準 Python 3 バイナリ(/usr/bin/python3)が、order_service の gunicorn WSGI アプリケーションを実行しています。
ガイド分析で Python メモリをプロファイリングする:最大のオブジェクトとそのモジュールを特定する
OpenResty XRay を使用して、この未変更のプロセスをリアルタイムで検査します。Web コンソールを開き、観察しているマシンが正しいことを確認して、Guided Analysis(ガイド分析)ページに移動します。ここでは OpenResty XRay が診断できる問題の種類を選択できます。
High memory usage を選択し、Python アプリケーションと top が示した gunicorn プロセス(約 600MB を消費しているもの)を選び、Python と C/C++ の両方の言語レベルを選択したまま開始します。1〜2 ラウンドの分析の後、OpenResty XRay は自動的にレポートを生成します。
これが、今回分析対象としている問題の種類、すなわちメモリです。
メモリの大部分が Libc アロケータによって割り当てられており、580 MB 以上に達していることがわかります。
これは最もメモリを占有している Python GC オブジェクトの参照パスです。この Python 仮想マシンが Libc アロケータを使用してメモリを要求していることが明確です。
この Python 辞書は、ロードされたすべての Python モジュールを保存するために使用されています。
これは order_service.service.order.prev_processor という名前の Python モジュールです。
このモジュール内に order_name_cache という名前のフィールドがあります。
このフィールドの値は Python 辞書です。
クリックして詳細を表示します。
このデータ参照パスは、Python GC オブジェクトメモリ分布フレームグラフから自動的に導出されたものです。
以下は問題に関するより詳細な説明と提案です。先ほど確認した prev_processor モジュールについて言及しています。
また、order_name_cache 辞書についても言及しています。
データ参照パスに戻りましょう。このアイコンをクリックして、モジュール名をコピーします。
ターミナルで find コマンドを使用して Python ソースファイルを検索します。
先ほどコピーしたモジュール名を貼り付けます。ここでは、モジュール名のドットを grep コマンドのワイルドカードとして利用しています。
完全なファイルパスをコピーします。vim エディタを使用してこのソースファイルを開きます。お好みのエディタを使用していただいて構いません。
先ほどのレポートで言及された order_name_cache 変数を見つけることができます。
この変数がどのように使用されているかを確認し、メモリリークの問題があるかどうかを判断することもできます。
order_name_cache はモジュールレベルの辞書で、handle() は処理する注文ごとに新しいエントリを書き込みますが、エントリを削除する箇所はどこにもありません。この上限のない増加こそが、プロセスが数百 MB を保持し続ける原因です——古典的な Python のメモリリークであり、今やその発生源で修正できます。
定期レポートで Python のメモリ使用量を自動監視する
OpenResty XRay はオンラインプロセスを自動的に監視し、分析レポートを生成することもできます。Insights ページでは日次および週次のレポートを確認でき——同じメモリ参照パスがひとりでに浮かび上がります——毎回手動でガイド分析を開始する必要はありません。とはいえ、ガイド分析はアプリケーションの開発やデモンストレーションには依然として有用です。
よくある質問
どの Python プロセスが最もメモリを消費しているかを見つけるには?
top を実行して常駐メモリでプロセスをランク付けし、ps でバイナリとアプリケーションを確認します。本チュートリアルでは、order_service WSGI アプリを実行する gunicorn ワーカーの RSS が 600 MB を超えており、詳細なプロファイリングの対象として明確でした。
@profile デコレータの追加やプロセスの再起動なしに Python メモリをプロファイリングできますか?
はい。OpenResty XRay は既に稼働中の未変更の Python プロセスにリアルタイムでアタッチします。@profile デコレータの挿入も再起動も不要で、分析はそのままの状態のプロセスに対して実行されます。
Python GC オブジェクトメモリ分布フレームグラフとは何ですか?
OpenResty が独自に開発したフレームグラフで、ガベージコレクション対象の Python オブジェクトそれぞれが保持するメモリ量とデータ参照パスに沿ってマッピングします。OpenResty XRay は稼働中のプロセスから自動的に生成し、各オブジェクトをモジュール階層に沿って遡ります——例えば、最上位の .modules 辞書から prev_processor.order_name_cache まで追跡します。
Python メモリ内で最大のオブジェクトを見つけるには?
OpenResty XRay でガイド分析を開始し、High memory usage を選択します。生成されたレポートは GC オブジェクト参照パスをサイズ順にランク付けします。本例では、最もホットなパスが order_service.service.order.prev_processor モジュール内の order_name_cache という dict を指し示しました。handle() が注文を処理するたびに新しいエントリを書き込み、削除されることがないため、約 570 MB を占有していました。
GC オブジェクトフレームグラフはどのようなメモリ問題を明らかにできますか?
フレームグラフは各オブジェクトに至る完全なデータ参照パスを示すため、大容量のメモリ消費とリークの両方を検出できます。本チュートリアルでは、参照パスにより order_name_cache がモジュールレベルの辞書であり、handle() がエントリを追加し続けるにもかかわらず削除されないことが判明しました——典型的な上限のない増加によるメモリリークです。OpenResty XRay がメモリを特定のモジュール内の特定のフィールドに帰属させるため、ソースファイルを直接開いてその変数の使われ方を確認できます。
OpenResty XRay について
OpenResty XRay は動的トレーシング製品であり、実行中のアプリケーションを自動的に分析して、パフォーマンスの問題、動作の問題、セキュリティの脆弱性を解決し、実行可能な提案を提供いたします。基盤となる実装において、OpenResty XRay は弊社の Y 言語によって駆動され、Stap+、eBPF+、GDB、ODB など、様々な環境下で複数の異なるランタイムをサポートしております。
著者について
章亦春(Zhang Yichun)は、オープンソースの OpenResty® プロジェクトの創始者であり、OpenResty Inc. の CEO および創業者です。
章亦春(GitHub ID: agentzh)は中国江蘇省生まれで、現在は米国ベイエリアに在住しております。同氏は中国における初期のオープンソース技術と文化の提唱者およびリーダーの一人であり、Cloudflare、Yahoo!、Alibaba など、国際的に有名なハイテク企業に勤務した経験があります。「エッジコンピューティング」、「動的トレーシング」、「マシンコーディング」 の先駆者であり、22 年以上のプログラミング経験と 16 年以上のオープンソース経験を持っております。世界中で 4000 万以上のドメイン名を持つユーザーを抱えるオープンソースプロジェクトのリーダーとして、同氏は OpenResty® オープンソースプロジェクトをベースに、米国シリコンバレーの中心部にハイテク企業 OpenResty Inc. を設立いたしました。同社の主力製品である OpenResty XRay(動的トレーシング技術を利用した非侵入型の障害診断・解決ツール)と OpenResty Edge(マイクロサービスおよび分散トラフィックに最適化された多機能ゲートウェイソフトウェア)は、世界中の多くの上場企業および大企業から高い評価を得ております。OpenResty 以外にも、章亦春は Linux カーネル、Nginx、LuaJIT、GDB、SystemTap、LLVM、Perl など、複数のオープンソースプロジェクトに累計 100 万行以上のコードを寄与し、60 以上のオープンソースソフトウェアライブラリを執筆しております。
翻訳
英語版の原文と日本語訳版(本文)をご用意しております。読者の皆様による他の言語への翻訳版も歓迎いたします。全文翻訳で省略がなければ、採用を検討させていただきます。心より感謝申し上げます!






































