実行中の Perl プロセスが何にメモリを消費しているかを知るには、OpenResty XRay でプロファイルします。XRay は未改変のプロセスにアタッチし、生きている Perl オブジェクトや値を使用メモリ量で並べ替え、最大のものをデータ参照パスによって正確な変数とソース行まで追跡します——コード変更も再起動も不要です。

本チュートリアルでは、OpenResty XRay の Guided Analysis と、独自に開発した Perl オブジェクトメモリ分布のフレームグラフを使って、その手順を最後まで解説します。実際の事例では、180MB の Perl プロセスのメモリが、order_name_cache という名前の 1 つのハッシュテーブルに集中していたことが判明しました。

症状: top で Perl プロセスのメモリ使用率が高い

まず各プロセスのメモリ使用状況を確認するため、top コマンドを実行します。ご覧のように、ある Perl プロセスが最も多くのメモリを消費しており、180MB を超えています。

top の出力。この Perl プロセスが最も多くのメモリ(180MB 超)を消費している

次に ps コマンドを実行して、このプロセスの詳細を確認します。このプロセスが使用している Perl バイナリ実行ファイルは、Linux ディストリビューション付属のものです。

ps の出力。このプロセスがシステム付属の perl バイナリであることを示している

それでは OpenResty XRay を使って、この未改変のプロセスをリアルタイムで分析し、メモリが具体的にどこで消費されているかを特定します。

OpenResty XRay の Guided Analysis で最大の Perl オブジェクトを特定する

ブラウザで OpenResty XRay の Web コンソールを開き、分析中のマシンが正しいことを確認します(正しくない場合はリストから選び直せます)。「Guided Analysis」ページに移動すると、システムが診断できる問題の種類が表示されます。

OpenResty XRay の Guided Analysis で診断できる問題の種類。High memory usage を含む

「High memory usage」を選び、先ほどの Perl アプリケーションと top で示されたプロセス(180MB 超を消費しているもの)を選択し、Perl と C/C++ の両方の言語レベルを選択したまま、最大分析時間はデフォルトの 300 秒のままにして分析を開始します。1〜2 ラウンド実行すると、OpenResty XRay が自動的にメモリ分析レポートを生成します。libc アロケータによって割り当てられたメモリが大部分を占めており、160MB を超えていることがわかります。

OpenResty XRay のレポート。メモリの大部分(160MB 超)が libc アロケータによって割り当てられていることを示している

これは最も多くのメモリを使用している Perl メモリオブジェクトの参照パスです。明らかに、この Perl 仮想マシンは libc によって割り当てられたメモリの大部分を使用しています。

レポート内で最も多くのメモリを使用している Perl メモリオブジェクトの参照パス

最大の使用量は Services::Preprocessor モジュール内にあります。

参照パスが Services::Preprocessor Perl モジュールを指している

モジュールのシンボルテーブルには、order_name_cache という名前の変数があります。

Services::Preprocessor モジュールのシンボルテーブル内の order_name_cache 変数

この変数は Perl ハッシュテーブルです。

Perl ハッシュテーブルとして表示された order_name_cache 変数

クリックして詳細を確認します。

参照パス内の order_name_cache ハッシュテーブルの詳細ビュー

このオブジェクト参照パスは、Perl 言語レベルの GC オブジェクトメモリ分布フレームグラフから自動的に導き出されたものです。

参照パスの導出元となった Perl 言語レベルの GC オブジェクトメモリ分布フレームグラフ

以下は問題についてのより詳細な説明と提案です。データ参照パス内のオブジェクトについて、一つずつ説明しています。

データ参照パス内の各オブジェクトに対する OpenResty XRay の説明と提案

最大のオブジェクトをソースファイルまで追跡する

モジュール名 Services::PreProcessor は Perl ソースファイルのパスに対応しています。したがって、これを使用してソースファイルを見つけることができます。

モジュール名 Services::Preprocessor が Perl ソースファイルのパスに対応している

ターミナルで、カレントワーキングディレクトリを Perl アプリケーションのソースツリーに切り替えます。

ターミナルで Perl アプリケーションのソースツリーに切り替える

find コマンドを使用してソースファイルを検索します。

find コマンドで Services/Preprocessor の Perl ソースファイルを特定する

完全なファイルパスをコピーし、vim エディタでソースファイルを開きます。お好みのエディタを使用することができます。

完全なファイルパスをコピーし、vim でソースファイルを開く

データ参照パスに戻り、アイコンをクリックして、この Perl ハッシュテーブルの変数名をコピーします。

データ参照パスから order_name_cache ハッシュテーブルの変数名をコピーする

貼り付けると、ハッシュテーブルがここで定義されていることがわかります。

Perl ソースファイル内で order_name_cache ハッシュテーブルが定義されている箇所

そして、このハッシュテーブル変数がどのように使用されているかも確認できます。

Perl ソースコード内で order_name_cache ハッシュテーブルが使用されている箇所

Insights レポートで Perl プロセスのメモリを自動監視する

OpenResty XRay はオンラインのプロセスを自動的に監視し、分析レポートを表示することもできます。「Insights」ページでは日次・週次のレポートを確認できるため、「Guided Analysis」機能を手動で実行する必要はありません——もちろん、「Guided Analysis」はアプリケーションの開発やデモにおいて非常に有用です。

OpenResty XRay の Insights ページにある Perl アプリケーションの日次・週次メモリレポート

本記事が対象とするのは、メモリ使用量が大きいものの概ね安定しているケースです。もし Perl プロセスのメモリが時間とともに増え続ける場合は、事例記事「Perl のメモリリークを診断する」をご覧ください。CPU 側の問題については「Perl プロセスの CPU 使用率が高い問題を調査する」をご覧ください。

よくある質問(FAQ)

どの Perl プロセスが最も多くのメモリを使用しているかを調べるには?

top コマンドを実行します——最も多くのメモリを使用しているのがその Perl プロセスで、本例では 180MB を超えています。ps を実行して詳細を確認すると、ここでは Linux ディストリビューション付属の標準 Perl バイナリです。次に OpenResty XRay がその具体的なプロセスを分析し、メモリがどこで消費されているかを特定します。

コードを変更したり再起動したりせずに Perl のメモリ使用状況をプロファイルできますか?

はい。OpenResty XRay は、未改変の実行中の Perl プロセスをリアルタイムで分析します——本例ではディストリビューション付属の標準 Perl バイナリです。プロセスをそのまま分析するため、アプリケーションを変更したり再起動したりせずに、メモリの行き先を確認できます。

Perl メモリオブジェクトの参照パスとは何ですか?

最も多くのメモリを保持しているオブジェクトへの参照パスのことです——ここでは Services::Preprocessor モジュール内の order_name_cache ハッシュテーブルです。OpenResty XRay は、Perl 言語レベルの GC オブジェクトメモリ分布フレームグラフからこのパスを自動的に導き出します。

大きな Perl オブジェクトをソースコードまで追跡するには?

モジュール名は Perl ソースファイルのパスに対応しているため、それを使ってソースファイルを特定できます。参照パスから変数名——ここでは order_name_cache——をコピーし、find でファイルを特定して開くと、そのハッシュテーブルがどこで定義され、どこで使用されているかがわかります。

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、LuaJITGDBSystemTapLLVM、Perl など、複数のオープンソースプロジェクトに累計 100 万行以上のコードを寄与し、60 以上のオープンソースソフトウェアライブラリを執筆しております。

翻訳

英文版の原文と日本語訳版(本文)をご用意しております。読者の皆様による他の言語への翻訳版も歓迎いたします。全文翻訳で省略がなければ、採用を検討させていただきます。心より感謝申し上げます!