Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

[インデックス 18440] ファイルの概要

このコミットは、Go言語のコマンドラインツールである cmd/gotest.go ファイルに対する変更です。test.go は、go test コマンドの動作、特にテスト実行時のプロファイリングに関するヘルプメッセージや内部ロジックを定義していると考えられます。この変更は、ヒーププロファイリングに関するユーザーへのアドバイスを改善することを目的としています。

コミット

このコミットは、Go言語のヒーププロファイリングに関する go test コマンドのヘルプメッセージを更新し、より適切で効率的なプロファイリング方法をユーザーに案内するように修正しています。具体的には、以前推奨されていた GOGC=off(ガベージコレクタの無効化)の代わりに、pprof ツールで --alloc_space フラグを使用することを推奨するように変更されました。

GitHub上でのコミットページへのリンク

https://github.com/golang/go/commit/e56e4e01935be3c310e5767e90411c76aaa1690d

元コミット内容

cmd/go: better advice for heap profiling

R=golang-codereviews, bradfitz
CC=golang-codereviews
https://golang.org/cl/60760048

変更の背景

Go言語では、プログラムのメモリ使用状況を分析するためにヒーププロファイリングが提供されています。以前の go test コマンドのヘルプメッセージでは、すべてのメモリ割り当てをプロファイルするために -test.memprofilerate=1 を設定することに加えて、環境変数 GOGC=off を設定してガベージコレクタ(GC)を無効にすることが推奨されていました。

しかし、GOGC=off を設定してGCを無効にすると、プログラムが使用可能なメモリを使い果たし、クラッシュする可能性がありました。特に、長時間実行されるテストや大量のメモリを割り当てるテストでは、この問題が顕著でした。GCを無効にすることは、メモリリークの検出には役立つかもしれませんが、純粋なメモリ割り当てのプロファイリングには過剰な手段であり、テストの実行を不安定にするリスクがありました。

このコミットは、このような問題に対処し、より安全で効果的なヒーププロファイリングの方法をユーザーに提供するために行われました。新しいアプローチは、GCを無効にすることなく、pprof ツールが提供する特定のフラグを利用することで、すべてのメモリ割り当てを正確にプロファイルできるようにします。

前提知識の解説

Go言語のメモリプロファイリング

Go言語には、プログラムの実行中にメモリ使用状況を詳細に分析するためのプロファイリングツールが組み込まれています。これにより、メモリリークの特定、メモリ使用量の最適化、パフォーマンスのボトルネックの発見が可能になります。

  • ヒーププロファイリング: プログラムがヒープ領域でどのようにメモリを割り当て、使用しているかを分析します。これにより、どのコードが最も多くのメモリを割り当てているか、またはメモリを解放せずに保持しているかなどを特定できます。
  • runtime.MemProfileRate: これはGoランタイムの変数で、メモリプロファイリングのサンプリングレートを制御します。デフォルト値は524288バイト(512KB)で、これは平均して512KBごとに1回のメモリ割り当てをサンプリングすることを意味します。この値を小さくするほど、より多くの割り当てがサンプリングされ、プロファイルの精度が向上しますが、プロファイリングのオーバーヘッドも増加します。MemProfileRate=1 に設定すると、すべてのメモリ割り当てがサンプリングされ、最も詳細なプロファイルが得られます。

pprof ツール

pprof は、Go言語のプロファイリングデータを視覚化・分析するための強力なツールです。Goプログラムから生成されたプロファイルデータ(CPUプロファイル、メモリプロファイルなど)を読み込み、グラフ、テキスト、Webインターフェースなど、さまざまな形式で表示できます。

  • pprof の使用方法: 通常、go tool pprof <profile_file> のように使用します。プロファイルファイルは、go test -memprofile=mem.prof のようにテスト実行時に生成できます。
  • --alloc_space フラグ: pprof ツールには、メモリプロファイルデータを分析する際に使用できる様々なフラグがあります。--alloc_space フラグは、ヒーププロファイルにおいて、解放されたメモリではなく、割り当てられた総メモリ量(allocated space)に基づいてデータを表示するように pprof に指示します。これにより、GCによって解放されたメモリも考慮に入れ、プログラムが実際にどれだけのメモリを割り当てたかの全体像を把握できます。

Go言語のガベージコレクタ(GC)と GOGC

Go言語は、自動メモリ管理のためにガベージコレクタ(GC)を使用しています。GCは、プログラムがもはや参照していないメモリ領域を自動的に解放し、メモリリークを防ぎ、開発者が手動でメモリを管理する負担を軽減します。

  • GOGC 環境変数: GOGC は、GoのGCの動作を制御する環境変数です。デフォルト値は100で、これはヒープサイズが前回のGC後のヒープサイズの100%増加したときにGCが実行されることを意味します。
  • GOGC=off: この値を off に設定すると、GCが無効になります。GCが無効になると、プログラムはメモリを解放しなくなり、割り当てられたすべてのメモリを保持し続けます。これは、メモリリークのデバッグや、特定の条件下でのメモリ使用量の挙動を観察する際には役立つことがありますが、通常の使用ではメモリが枯渇し、プログラムがクラッシュする原因となります。

技術的詳細

このコミットの技術的な核心は、ヒーププロファイリングの「すべてのメモリ割り当て」を捕捉する方法の変更にあります。

以前のアドバイスでは、runtime.MemProfileRate=1 を設定することに加えて、GOGC=off を推奨していました。MemProfileRate=1 は、すべてのメモリ割り当てをサンプリングするようにGoランタイムに指示します。しかし、Goのヒーププロファイルはデフォルトで「ライブなオブジェクト」(GCによってまだ解放されていないオブジェクト)のメモリ使用量を追跡します。したがって、GCが実行されると、一部の割り当てられたメモリは解放され、プロファイルには表示されなくなります。

GOGC=off を設定することで、GCが完全に停止し、割り当てられたすべてのメモリが解放されずに保持されるため、MemProfileRate=1 と組み合わせることで、プログラムが割り当てたすべてのメモリをプロファイルに含めることができました。しかし、前述の通り、これはメモリ枯渇のリスクを伴いました。

新しいアドバイスでは、GOGC=off の代わりに pprof ツールに --alloc_space フラグを渡すことを推奨しています。

  • runtime.MemProfileRate=1 は引き続き設定し、すべての割り当てをサンプリングします。
  • pprof ツールでプロファイルデータを分析する際に --alloc_space フラグを使用します。このフラグは、pprof に対して、GCによって解放されたメモリも含め、プログラムが割り当てた総メモリ量に基づいてプロファイルデータを表示するように指示します。これにより、GCの動作に影響を与えることなく、すべてのメモリ割り当てを正確に分析することが可能になります。

この変更により、ユーザーはGCを無効にするという危険な操作を行うことなく、より正確で包括的なヒーププロファイルを取得できるようになります。これは、プロファイリングの安全性と利便性を大幅に向上させます。

コアとなるコードの変更箇所

--- a/src/cmd/go/test.go
+++ b/src/cmd/go/test.go
@@ -168,9 +168,7 @@ control the execution of any test:
 	    Enable more precise (and expensive) memory profiles by setting
 	    runtime.MemProfileRate.  See 'godoc runtime MemProfileRate'.
 	    To profile all memory allocations, use -test.memprofilerate=1
-	    and set the environment variable GOGC=off to disable the
-	    garbage collector, provided the test can run in the available
-	    memory without garbage collection.
+	    and pass --alloc_space flag to pprof tool.

 	-outputdir directory
 	    Place output files from profiling in the specified directory,

コアとなるコードの解説

変更は src/cmd/go/test.go ファイル内のコメント行にあります。

  • 削除された行:

    -	    and set the environment variable GOGC=off to disable the
    -	    garbage collector, provided the test can run in the available
    -	    memory without garbage collection.
    

    これらの行は、すべてのメモリ割り当てをプロファイルするために GOGC=off を設定し、ガベージコレクタを無効にするという以前の推奨事項を削除しています。また、「テストが利用可能なメモリでガベージコレクションなしで実行できる場合」という条件付きの注意書きも削除されました。これは、この方法がもはや推奨されないためです。

  • 追加された行:

    +	    and pass --alloc_space flag to pprof tool.
    

    この行は、新しい推奨事項を追加しています。-test.memprofilerate=1 を使用してすべてのメモリ割り当てをプロファイルする際には、pprof ツールに --alloc_space フラグを渡すように指示しています。これにより、GCを無効にすることなく、割り当てられたすべてのメモリをプロファイルに含めることができます。

この変更は、ユーザーが go test コマンドのヘルプメッセージを参照した際に、より安全で効果的なヒーププロファイリングの方法を学ぶことができるように、ドキュメントを直接更新するものです。

関連リンク

参考にした情報源リンク