[インデックス 14150] ファイルの概要
このコミットは、Go言語のプロファイリングツールである pprof
スクリプトに対する改善を含んでいます。具体的には、プロファイル結果からGoランタイムの内部関数である runtime.settype
および runtime.settype_flush
を除外するフィルタリング機能の追加と、--svg
オプションでSVG形式の出力を生成する際に、生成されるXMLが不正になる問題を修正しています。
コミット
commit bcf88de5ffa1119e8b56a765a076d6a302ae3ecc
Author: Brad Fitzpatrick <bradfitz@golang.org>
Date: Mon Oct 15 20:49:15 2012 -0700
pprof: filter out runtime.settype and fix --svg mode to produce valid XML
R=golang-dev, rsc
CC=golang-dev
https://golang.org/cl/6642043
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/bcf88de5ffa1119e8b56a765a076d6a302ae3ecc
元コミット内容
pprof: filter out runtime.settype and fix --svg mode to produce valid XML
R=golang-dev, rsc
CC=golang-dev
https://golang.org/cl/6642043
変更の背景
このコミットは、Go言語のプロファイリングツール pprof
のユーザビリティと出力品質を向上させるために行われました。
-
runtime.settype
のフィルタリング: Goプログラムのプロファイルを取得する際、runtime.settype
やruntime.settype_flush
といったGoランタイムの内部関数がプロファイル結果に現れることがありました。これらの関数は、Goの型システムやガベージコレクションに関連する内部的な処理であり、通常、アプリケーション開発者がパフォーマンスボトルネックを特定する上で直接的に関心を持つ対象ではありません。プロファイル結果にこれらの内部関数が含まれると、本当に重要なアプリケーションコードのパフォーマンス特性が埋もれてしまい、分析が困難になるという問題がありました。そのため、これらの「興味のない」フレームを自動的に除外することで、よりクリーンで分析しやすいプロファイル結果を提供することが求められました。 -
SVG出力のXML妥当性問題:
pprof
は、プロファイルデータを視覚的に表現するためにSVG(Scalable Vector Graphics)形式のグラフを生成する機能を提供しています。SVGはXMLベースの画像フォーマットであり、その構造は厳密なXML仕様に準拠している必要があります。しかし、これまでのpprof
の実装では、SVG出力時にプログレス情報やサマリー情報などのテキストメッセージが標準出力に直接printf
で出力されていました。これらのテキストメッセージは、SVGのXML構造の外部に存在するため、生成されたSVGファイルがXMLとして不正な形式となり、SVGビューアやエディタで正しく表示・処理できないという問題が発生していました。このコミットは、SVG出力時にはこれらの余分なテキストメッセージを出力しないようにすることで、XMLの妥当性を確保することを目的としています。
前提知識の解説
- pprof: Go言語の標準的なプロファイリングツールです。CPU使用率、メモリ割り当て、ゴルーチン、ブロックされた同期操作など、様々な種類のプロファイルデータを収集し、分析・可視化することができます。通常、
go tool pprof
コマンドとして利用され、プロファイルデータをテキスト形式、グラフ形式(SVGなど)、Web UIなど様々な形式で表示できます。 - プロファイリング: ソフトウェアの実行中にそのパフォーマンス特性(どの関数が多くのCPU時間を使っているか、どの部分が多くのメモリを消費しているかなど)を測定・分析するプロセスです。これにより、パフォーマンスのボトルネックを特定し、最適化の指針を得ることができます。
- スタックトレースとフレーム: プロファイルデータは通常、関数呼び出しのスタックトレースとして記録されます。スタックトレースの各エントリは「フレーム」と呼ばれ、特定の関数呼び出しを表します。
- Goランタイム (runtime): Go言語のプログラムが実行される際に、メモリ管理(ガベージコレクション)、ゴルーチン管理、スケジューリング、システムコールインターフェースなど、低レベルな機能を提供する部分です。
runtime
パッケージに含まれる関数は、通常、Goコンパイラや標準ライブラリによって内部的に使用されます。 runtime.settype
/runtime.settype_flush
: これらはGoランタイムの内部関数であり、Goの型システムやガベージコレクションの内部動作に関連しています。具体的には、新しい型情報の登録や、型情報のキャッシュのフラッシュなど、メモリ管理やリフレクションの低レベルな側面に関わる可能性があります。これらはアプリケーションのロジックとは直接関係ないため、プロファイル結果から除外されることで、より高レベルなアプリケーションのパフォーマンスに焦点を当てることができます。- SVG (Scalable Vector Graphics): XMLベースの2次元ベクターグラフィックス記述言語です。Webブラウザで直接表示でき、拡大・縮小しても画質が劣化しないという特徴があります。XML形式であるため、厳密な構文規則に従う必要があります。
- XML妥当性: XML文書が、そのDTD(Document Type Definition)やXMLスキーマなどの定義に従っているかどうかを指します。妥当なXMLは、構文的に正しいだけでなく、構造的にも定義されたルールに準拠しています。不正なXMLは、パーサーによってエラーと見なされ、正しく処理されない可能性があります。
技術的詳細
このコミットは、misc/pprof
というPerlスクリプトに対して行われています。pprof
は元々Googleが開発したプロファイリングツールであり、Go言語の pprof
もその影響を強く受けています。このスクリプトは、Goプログラムから生成されたプロファイルデータを解析し、様々な形式で出力する役割を担っています。
変更点は大きく分けて二つです。
-
runtime.settype
のフィルタリング:RemoveUninterestingFrames
サブルーチン(関数)に、'runtime.settype'
と'runtime.settype_flush'
が「興味のないフレーム」のリストに追加されました。- このサブルーチンは、プロファイルデータから特定の関数フレームを除外する役割を担っています。これにより、プロファイル結果のコールスタックからこれらのランタイム内部関数が取り除かれ、よりアプリケーションコードに焦点を当てた分析が可能になります。
-
SVG出力時のXML妥当性修正:
misc/pprof
スクリプト内で、プログレス情報やサマリー情報などを標準出力に表示するために使用されていたprintf
関数呼び出しが、新しく導入されたInfof
サブルーチンに置き換えられました。Infof
サブルーチンは、$main::opt_svg
というグローバル変数が真(つまり--svg
オプションが指定されている)の場合には、何も出力せずにreturn
するロジックを含んでいます。- これにより、
--svg
オプションが有効な場合、"Total: %s %s\n"
や"After focusing on '%s': %s %s of %s (%0.1f%%)\n"
といった情報メッセージが標準出力に書き込まれなくなります。 - SVG出力は通常、標準出力にXMLデータとして書き込まれるため、これらの余分なテキストが混入するとXMLの構文が破壊され、結果として不正なSVGファイルが生成されていました。
Infof
の導入により、SVG出力時には純粋なXMLデータのみが出力されるようになり、XMLの妥当性が保証されます。
コアとなるコードの変更箇所
--- a/misc/pprof
+++ b/misc/pprof
@@ -634,7 +634,7 @@ sub Main() {
# (only matters when --heapcheck is given but we must be
# compatible with old branches that did not pass --heapcheck always):
if ($total != 0) {
- printf("Total: %s %s\n", Unparse($total), Units());
+ Infof("Total: %s %s\n", Unparse($total), Units());
}
PrintText($symbols, $flat, $cumulative, $total, -1);
} elsif ($main::opt_raw) {\
@@ -931,7 +931,7 @@ sub ProcessProfile {
if ($focus ne '') {
$profile = FocusProfile($symbols, $profile, $focus);
my $focus_count = TotalProfile($profile);
- printf("After focusing on '%s': %s %s of %s (%0.1f%%)\n",
+ Infof("After focusing on '%s': %s %s of %s (%0.1f%%)\n",
$focus,
Unparse($focus_count), Units(),
Unparse($total_count), ($focus_count*100.0) / $total_count);
@@ -939,7 +939,7 @@ sub ProcessProfile {
if ($ignore ne '') {
$profile = IgnoreProfile($symbols, $profile, $ignore);
my $ignore_count = TotalProfile($profile);
- printf("After ignoring '%s': %s %s of %s (%0.1f%%)\n",
+ Infof("After ignoring '%s': %s %s of %s (%0.1f%%)\n",
$ignore,
Unparse($ignore_count), Units(),
Unparse($total_count),
@@ -1115,6 +1115,15 @@ sub PrintSymbolizedProfile {
}
}
+# Print information conditionally filtered out depending on the output
+# format.
+sub Infof {
+ my $format = shift;
+ my @args = @_;\
+ return if $main::opt_svg;\
+ printf($format, @args);\
+}
+
# Print text output
sub PrintText {
my $symbols = shift;
@@ -2638,6 +2647,8 @@ sub RemoveUninterestingFrames {
'runtime.makemap_c',
'runtime.makeslice',
'runtime.mal',
+ 'runtime.settype',
+ 'runtime.settype_flush',
'runtime.slicebytetostring',
'runtime.sliceinttostring',
'runtime.stringtoslicebyte',
コアとなるコードの解説
-
Infof
サブルーチンの追加:sub Infof { ... }
という新しいPerlサブルーチンが定義されました。- このサブルーチンは、
printf
と同様にフォーマット文字列と可変個の引数を受け取ります。 return if $main::opt_svg;
という行が重要です。これは、pprof
が--svg
オプション付きで実行されている場合($main::opt_svg
が真の場合)には、このサブルーチンが即座に終了し、何も出力しないことを意味します。printf($format, @args);
の行は、--svg
オプションが指定されていない場合にのみ、通常のprintf
と同じようにメッセージを標準出力に出力します。- この変更により、SVG出力時にはプログレスやサマリーに関するテキストがXMLストリームに混入するのを防ぎ、生成されるSVGファイルのXML妥当性を確保します。
-
printf
からInfof
への置き換え:Main
サブルーチン内(Total:
の出力箇所)とProcessProfile
サブルーチン内(After focusing on:
およびAfter ignoring:
の出力箇所)で、既存のprintf
呼び出しがInfof
呼び出しに置き換えられました。- これにより、これらの情報メッセージの出力が
Infof
サブルーチンの制御下に置かれ、SVGモードでの出力抑制が可能になりました。
-
RemoveUninterestingFrames
の更新:RemoveUninterestingFrames
サブルーチン内の「興味のないフレーム」のリストに、'runtime.settype'
と'runtime.settype_flush'
が追加されました。- このリストに含まれる関数は、プロファイルデータから自動的に除外されます。これにより、Goランタイムの内部的な型関連処理がプロファイル結果に現れるのを防ぎ、よりユーザーが関心を持つアプリケーションコードのパフォーマンスに焦点を当てることができます。
これらの変更は、pprof
の出力の品質と分析のしやすさを向上させるための、実用的な改善です。
関連リンク
- Go言語のプロファイリングに関する公式ドキュメント: https://go.dev/doc/diagnostics#profiling
pprof
ツールの詳細(Goのツールとしての説明): https://pkg.go.dev/cmd/pprof- SVG (Scalable Vector Graphics) のW3C勧告: https://www.w3.org/TR/SVG/
参考にした情報源リンク
- Go言語の公式リポジトリ: https://github.com/golang/go
- Go言語のコードレビューシステム (Gerrit): https://go.dev/cl/6642043 (コミットメッセージに記載されているCLリンク)
- Perlの
printf
関数に関するドキュメント: https://perldoc.perl.org/functions/printf - Perlのサブルーチンに関するドキュメント: https://perldoc.perl.org/perlsub
- XMLの妥当性に関する一般的な情報源 (例: Wikipedia): https://ja.wikipedia.org/wiki/XML%E3%82%B9%E3%82%AD%E3%83%BC%E3%83%9E
runtime.settype
のような内部関数に関するGoのソースコード(例:src/runtime/type.go
やsrc/runtime/mprof.go
など、Goのソースコードを検索して関連する部分を特定)