[インデックス 16626] ファイルの概要
このコミットは、Go言語のランタイムプロファイリングパッケージ runtime/pprof
のテストに関する変更です。具体的には、Goの競合検出器(Race Detector)が有効な環境下でのテスト実行を一時的に無効化する変更が加えられています。
コミット
runtime/pprof
パッケージのテストファイル pprof_test.go
にビルドタグ !race
が追加されました。これにより、Goの競合検出器が有効なビルド(go build -race
など)では、このテストファイルがコンパイルおよび実行されなくなります。
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/bd105b2bcafc3b8d4e5a17608da33f31d6486946
元コミット内容
commit bd105b2bcafc3b8d4e5a17608da33f31d6486946
Author: Dmitriy Vyukov <dvyukov@google.com>
Date: Mon Jun 24 23:51:00 2013 +0400
runtime/pprof: disable testing under race detector
until we decide what to do with issues 5659/5736.
Profiling with race detector is not very useful in general,
and now it makes race builders red.
R=golang-dev, rsc
CC=golang-dev
https://golang.org/cl/10523043
---
src/pkg/runtime/pprof/pprof_test.go | 3 +++
1 file changed, 3 insertions(+)
diff --git a/src/pkg/runtime/pprof/pprof_test.go b/src/pkg/runtime/pprof/pprof_test.go
index 6d5764f4a2..94d19f741c 100644
--- a/src/pkg/runtime/pprof/pprof_test.go
+++ b/src/pkg/runtime/pprof/pprof_test.go
@@ -2,6 +2,9 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
+// See issue 5659.
+// +build !race
+
package pprof_test
import (
変更の背景
この変更の背景には、Goの競合検出器(Race Detector)とプロファイリングツールの連携における問題がありました。コミットメッセージに記載されているように、issues 5659
と issues 5736
が関連しています。
当時のGoの競合検出器は、プログラムの実行時にデータ競合を検出するための強力なツールでしたが、そのオーバーヘッドは比較的高く、特にプロファイリングのようなパフォーマンス測定を目的としたツールと組み合わせると、予期せぬ副作用やパフォーマンスの劣化を引き起こす可能性がありました。
コミットメッセージでは、「Profiling with race detector is not very useful in general, and now it makes race builders red.」(競合検出器を使ったプロファイリングは一般的にあまり有用ではなく、現在、競合検出器が有効なビルドを失敗させている)と述べられています。これは、競合検出器が有効な環境で runtime/pprof
のテストを実行すると、テストが失敗するか、あるいは競合検出器が誤ったデータ競合を報告し、CI/CDパイプライン(特に「race builders」と呼ばれる、競合検出器を有効にしてビルド・テストを行う環境)を赤く(失敗状態に)していたことを示唆しています。
このコミットは、これらの問題を一時的に回避するための措置として導入されました。根本的な解決策が決定されるまでの間、競合検出器が有効な環境での runtime/pprof
のテスト実行を停止することで、CI/CDの安定性を確保し、開発者が競合検出器の誤検出やパフォーマンス問題に煩わされることなく作業を進められるようにすることが目的でした。
前提知識の解説
Go言語のプロファイリング (runtime/pprof
)
Go言語には、プログラムのパフォーマンス特性を分析するための強力なプロファイリングツールが組み込まれています。その中心となるのが runtime/pprof
パッケージです。このパッケージは、CPU使用率、メモリ割り当て、ゴルーチン、ミューテックス競合などのプロファイルデータを収集するためのAPIを提供します。収集されたデータは、go tool pprof
コマンドを使って視覚化・分析できます。
- CPUプロファイル: プログラムがCPU時間をどこで消費しているかを特定します。
- ヒーププロファイル: メモリ割り当てのパターンと、どのコードがメモリを多く使用しているかを特定します。
- ゴルーチンプロファイル: どのゴルーチンが存在し、何をしているかを特定します。
- ミューテックスプロファイル: ミューテックスの競合によってプログラムがブロックされている場所を特定します。
プロファイリングは、アプリケーションのボトルネックを特定し、パフォーマンスを最適化するために不可欠なプロセスです。
Go言語の競合検出器 (Race Detector)
Go言語の競合検出器は、並行処理におけるデータ競合(data race)を検出するためのツールです。データ競合は、複数のゴルーチンが同時に同じメモリ位置にアクセスし、少なくとも1つのアクセスが書き込みであり、かつそれらのアクセスが同期メカニズムによって保護されていない場合に発生します。データ競合は、プログラムの動作を予測不能にし、デバッグが困難なバグの原因となります。
競合検出器は、go build -race
、go run -race
、go test -race
などのコマンドに -race
フラグを追加することで有効にできます。有効にすると、Goランタイムは実行時にメモリアクセスを監視し、データ競合が検出された場合に詳細なレポートを出力します。
競合検出器は非常に有用ですが、その実装はプログラムの実行にオーバーヘッドを追加します。これは、メモリアクセスの監視や追加の同期処理が必要となるためです。このオーバーヘッドは、特にパフォーマンスが重要なプロファイリングのシナリオでは問題となることがあります。
ビルドタグ (Build Tags)
Go言語では、ソースファイルに「ビルドタグ」と呼ばれる特別なコメントを追加することで、特定の条件に基づいてファイルのコンパイルを制御できます。ビルドタグは、ファイルの先頭に // +build tag_name
の形式で記述されます。
// +build tag1
:tag1
が有効な場合にのみコンパイルされます。// +build !tag2
:tag2
が有効でない場合にのみコンパイルされます。// +build tag1,tag2
:tag1
とtag2
の両方が有効な場合にのみコンパイルされます(AND条件)。// +build tag1 tag2
:tag1
またはtag2
のいずれかが有効な場合にコンパイルされます(OR条件)。
このコミットでは // +build !race
が使用されており、これは race
タグ(競合検出器が有効な場合に自動的に設定される)が有効でない場合にのみファイルがコンパイルされることを意味します。つまり、競合検出器が有効なビルドでは、このファイルは無視されます。
技術的詳細
このコミットの技術的詳細は、Goのビルドシステムとランタイムの相互作用にあります。
- 競合検出器の動作: Goの競合検出器は、コンパイル時に特別なインストゥルメンテーションコードを生成し、実行時にそのコードがメモリアクセスを監視します。このインストゥルメンテーションは、プログラムの実行パスを変更し、追加のメモリとCPUリソースを消費します。
- プロファイリングの性質: プロファイリングは、プログラムの「真の」パフォーマンス特性を測定することを目的としています。競合検出器のオーバーヘッドは、この測定を歪める可能性があります。例えば、競合検出器が導入する追加の同期やメモリ割り当てが、プロファイルデータにノイズとして現れ、実際のボトルネックを特定することを困難にするかもしれません。
- テストの失敗: コミットメッセージが示唆するように、
runtime/pprof
のテストが競合検出器有効下で失敗していました。これは、以下のいずれかの理由が考えられます。- 競合検出器による誤検出:
runtime/pprof
の内部実装が、競合検出器の観点からはデータ競合のように見えるが、実際には安全な並行アクセスを行っている場合。プロファイリングツール自体が低レベルの並行処理を多用するため、このような状況は起こり得ます。 - パフォーマンスの劣化によるタイムアウト: 競合検出器のオーバーヘッドにより、テストの実行時間が大幅に増加し、テストフレームワークのタイムアウトに引っかかっていた可能性。
- 競合検出器が引き起こす実際の競合:
runtime/pprof
のテストコードまたはその対象となるコードに、競合検出器がなければ顕在化しないような潜在的なデータ競合が存在し、それが競合検出器によって露呈された可能性。ただし、コミットメッセージのトーンからは、前者の「誤検出」や「有用性の低さ」が主な理由であるように見受けられます。
- 競合検出器による誤検出:
- ビルドタグの適用:
// +build !race
というビルドタグをpprof_test.go
に追加することで、Goのビルドツールは、-race
フラグが指定された場合にはこのファイルをコンパイル対象から除外します。これにより、競合検出器が有効な環境ではruntime/pprof
のテストが実行されなくなり、CI/CDの「race builders」が赤くなる問題が回避されます。 - 一時的な解決策: この変更は「until we decide what to do with issues 5659/5736.」と明記されており、一時的な回避策であることが強調されています。これは、競合検出器とプロファイリングの間の根本的な相互作用の問題を将来的に解決する必要があることを示しています。
コアとなるコードの変更箇所
変更は src/pkg/runtime/pprof/pprof_test.go
ファイルの冒頭に集中しています。
--- a/src/pkg/runtime/pprof/pprof_test.go
+++ b/src/pkg/runtime/pprof/pprof_test.go
@@ -2,6 +2,9 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
+// See issue 5659.
+// +build !race
+
package pprof_test
import (
具体的には、以下の3行が追加されました。
// See issue 5659.
// +build !race
- 空行
コアとなるコードの解説
追加された // +build !race
は、Goのビルドタグです。
+build
は、Goコンパイラに対する指示であることを示します。!
は論理NOT演算子です。race
は、go build -race
やgo test -race
のように-race
フラグが指定された場合に自動的に有効になるビルドタグです。
したがって、// +build !race
は「race
タグが有効でない場合にのみ、このファイルをコンパイルする」という意味になります。
この行が pprof_test.go
の先頭に追加されたことで、競合検出器が有効なビルド環境では、このテストファイルはコンパイル対象から除外されます。結果として、runtime/pprof
のテストは競合検出器が有効な環境では実行されなくなり、競合検出器が引き起こしていたテストの失敗やCI/CDのビルドエラーが回避されます。
// See issue 5659.
は、この変更がGoのIssueトラッカー上の特定の課題(Issue 5659)に関連していることを示すコメントです。これは、将来的にこの変更の背景や理由を追跡するための重要な情報となります。
関連リンク
- Go Issue 5659:
runtime/pprof: race detector causes false positives in tests
- https://github.com/golang/go/issues/5659
- このIssueは、競合検出器が
runtime/pprof
のテストで誤検出(false positives)を引き起こすことを報告しています。これは、プロファイリングコードが低レベルのメモリ操作や並行処理を行うため、競合検出器がそれをデータ競合と誤認するケースがあったことを示唆しています。
- Go Issue 5736:
runtime/pprof: profiling with race detector is slow
- https://github.com/golang/go/issues/5736
- このIssueは、競合検出器を有効にした状態でのプロファイリングが非常に遅くなることを報告しています。これは、競合検出器のオーバーヘッドがプロファイリングのパフォーマンスに悪影響を与え、実用性を損なうことを示しています。
- Go CL 10523043:
runtime/pprof: disable testing under race detector
- https://go.dev/cl/10523043
- このコミットに対応するGoのコードレビューシステム(Gerrit)上のチェンジリストです。
参考にした情報源リンク
- Go言語の公式ドキュメント:
- Go言語のプロファイリングに関するドキュメント:
- Go言語の競合検出器に関するドキュメント:
- Go言語のビルドタグに関するドキュメント:
- GitHubのgolang/goリポジトリ:
- Go Issue Tracker:
- Dmitriy VyukovのGo関連の活動(競合検出器の主要な貢献者の一人)に関する情報。