Go 高 CPU 使用率:正規表現のコンパイルが CPU 時間の 36.8% を消費
Go プロセスが CPU コアを 100% 以上まで占有する場合、その原因は多くの場合、ホットなコードパスが CPU を消費していることにあります。実行中で未修正の Go チャットサービスを OpenResty XRay でプロファイリングしたところ、その高 CPU 使用率は正規表現のコンパイルにあることが判明しました。標準 regexp ライブラリの関数(業務関数 CheckMessage から prev_processor.go の 17 行目で呼び出される)が、CPU 時間の 36.8% を消費していたのです。正規表現のコンパイルはコストが高く、ホットなコードパスでは避けるべきです。本番環境で実行する際のオーバーヘッドが気になりますか?稼働中の Go サービスに対する OpenResty XRay のオーバーヘッドを実測しました——サンプリング中のスループット・レイテンシ・CPU のデータがあります。
本記事では、コードの変更も再起動も不要なプロファイリングの全過程を、Go の高 CPU 使用率を観察する段階から、原因となる正確なソースファイルと行番号を特定する段階まで示します。
Go プロセスの高 CPU 使用率を観察する
top コマンドを実行すると、chat-service という名前の Go プロセスが CPU コアの 100% 以上を消費していることがわかります。(症状が逆の場合——リクエストが届き続けているのに CPU 使用率が低いままの場合——は、2% の CPU 使用率で停滞する Go プロセスの追跡をご覧ください。)
OpenResty XRay で Go の CPU 使用率をプロファイリングする
OpenResty XRay を使って、この未修正のプロセスをリアルタイムで分析します。特別なモジュールもコードの変更も再起動も必要ありません。Web コンソールで Guided Analysis(ガイド付き分析) ページに移動し、問題の種類として High CPU Usage(高 CPU 使用率) を選択します。OpenResty XRay は対象マシン上で実行中のアプリケーションを自動的に検出します。ドロップダウンからこの Go アプリケーションを選択します。
CPU を 96% 消費している特定のプロセス、つまり先ほど top で確認したプロセスを選択します。
言語レベルを Go に設定し、最大分析時間はデフォルトの 300 秒のままにします。分析を開始すると、システムは複数回のラウンドを実行しますが、この例では 2 回で十分です。
CPU フレームグラフ分析
OpenResty XRay が自動的にレポートを生成します。
このレポートには、最も多くの CPU 時間を消費している Go レベルのコードパスが表示されます。その中で最も割合が高いのは正規表現のコンパイルで、CPU 時間の 36.8% を占めています。
これは Go ランタイムの標準 regexp ライブラリにある 2 つの関数で、正規表現のコンパイルを担当しています。
この CheckMessage 関数は業務ロジックの一部であり、先ほど見た正規表現コンパイル関数を呼び出しています。
Go のソースファイルと行番号を特定する
このコードパスをさらに詳しく知りたい場合は、More リンクをクリックします。
クリックすると、そのコードパスの詳細ビューが表示されます。これは Go レベルの CPU フレームグラフから導き出されたものです。
ここには、このコードパスのパフォーマンスを改善する方法に関する説明と提案があります。
例えば、正規表現コンパイル関数はコストが高いため、可能な限り呼び出しを避けるべきだと述べています。
続いて、正規表現を使用およびコンパイルする業務レベルの関数 CheckMessage について説明しています。
コンパイル済みの正規表現についても言及しています。
コードパスに戻り、CheckMessage という名前の Go 関数の緑色のボックスにマウスカーソルを合わせます。CheckMessage 関数の Go ソースファイルが表示され、ツールチップには prev_processor.go ファイルの完全なパスも表示されます。
Go ソースコードの行番号は 17 です。
アイコンをクリックして、この関数の完全な Go ソースファイルパスをコピーします。
先ほどコピーしたパスをターミナルに貼り付け、vim エディタで対応する Go の業務コードを表示します。お好みのエディタを自由にお使いいただけます。
レポートに表示されていた行番号どおり、17 行目に移動します。
このコードが実際に正規表現をコンパイルしており、regexp.MustCompile 関数を呼び出していることがわかります。
これはレポートに表示されていた CheckMessage 関数内にあることも確認できます。これで、この Go コードを最適化するのは簡単です!
自動モニタリングとレポート
本番環境のワークロードに対しては、OpenResty XRay がプロセスを継続的にモニタリングし、Insights ページで日次および週次のレポートを自動生成します。手動でのガイド付き分析は不要です。
高 CPU だけでなく、OpenResty XRay は稼働中のプロセスで Go の Panic をトレースすることも、再起動やコード変更なしで同様に行えます。
よくある質問
Go プログラムの CPU 使用率が高いのはなぜですか?
Go の高 CPU 使用率のよくある原因は、ホットなコードパス内にコストの高い処理があることです。今回のケースでは、OpenResty XRay が CPU のボトルネックを正規表現のコンパイルに特定しました。標準 regexp ライブラリの関数が CPU 時間の 36.8% を占めており、これらは業務関数 CheckMessage から prev_processor.go の 17 行目で呼び出されていました。CPU フレームグラフは、業務ロジックからランタイムライブラリの関数までの完全な呼び出しチェーンを明らかにします。
Go で正規表現をコンパイルするのはコストが高いですか?
はい。正規表現のコンパイルはマッチング用のオートマトンを構築するため、コンパイル済みのパターンを実行するよりもはるかにコストがかかります。OpenResty XRay のレポートは regexp のコンパイル関数を明確にコストが高いものとして示し、ホットなコードパスでの呼び出しを避けるよう推奨しています。一般的なやり方は、各パターンを一度だけコンパイルしてその結果を再利用し、繰り返しコンパイルしないことです。
Go の高 CPU の原因となるコードを見つけるにはどうすればよいですか?
OpenResty XRay のガイド付き分析を使い、Go レベルの CPU フレームグラフを生成します。フレームグラフは関数呼び出しをスタックで表示し、ボックスの幅が CPU 時間を表します。関数のボックスにマウスカーソルを合わせるとソースファイルのパスと行番号が表示されるので、そのファイルを任意のエディタで開いて、原因となっている正確なコードを確認できます。計装もコードの変更も不要です。
OpenResty XRay について
OpenResty XRay は動的トレーシング製品であり、実行中のアプリケーションを自動的に分析して、パフォーマンスの問題、動作の問題、セキュリティの脆弱性を解決し、実行可能な提案を提供いたします。基盤となる実装において、OpenResty XRay は弊社の Y 言語によって駆動され、Stap+、eBPF+、GDB、ODB など、様々な環境下で複数の異なるランタイムをサポートしております。
このチュートリアルがお役に立ちましたら、当ブログおよび YouTube チャンネル のご購読をお願いいたします。ありがとうございます!
著者について
章亦春(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 以上のオープンソースソフトウェアライブラリを執筆しております。
翻訳
英語版の原文と日本語訳版(本文)をご用意しております。読者の皆様による他の言語への翻訳版も歓迎いたします。全文翻訳で省略がなければ、採用を検討させていただきます。心より感謝申し上げます!








































