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

[インデックス 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 5659issues 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 -racego run -racego test -race などのコマンドに -race フラグを追加することで有効にできます。有効にすると、Goランタイムは実行時にメモリアクセスを監視し、データ競合が検出された場合に詳細なレポートを出力します。

競合検出器は非常に有用ですが、その実装はプログラムの実行にオーバーヘッドを追加します。これは、メモリアクセスの監視や追加の同期処理が必要となるためです。このオーバーヘッドは、特にパフォーマンスが重要なプロファイリングのシナリオでは問題となることがあります。

ビルドタグ (Build Tags)

Go言語では、ソースファイルに「ビルドタグ」と呼ばれる特別なコメントを追加することで、特定の条件に基づいてファイルのコンパイルを制御できます。ビルドタグは、ファイルの先頭に // +build tag_name の形式で記述されます。

  • // +build tag1tag1 が有効な場合にのみコンパイルされます。
  • // +build !tag2tag2 が有効でない場合にのみコンパイルされます。
  • // +build tag1,tag2tag1tag2 の両方が有効な場合にのみコンパイルされます(AND条件)。
  • // +build tag1 tag2tag1 または tag2 のいずれかが有効な場合にコンパイルされます(OR条件)。

このコミットでは // +build !race が使用されており、これは race タグ(競合検出器が有効な場合に自動的に設定される)が有効でない場合にのみファイルがコンパイルされることを意味します。つまり、競合検出器が有効なビルドでは、このファイルは無視されます。

技術的詳細

このコミットの技術的詳細は、Goのビルドシステムとランタイムの相互作用にあります。

  1. 競合検出器の動作: Goの競合検出器は、コンパイル時に特別なインストゥルメンテーションコードを生成し、実行時にそのコードがメモリアクセスを監視します。このインストゥルメンテーションは、プログラムの実行パスを変更し、追加のメモリとCPUリソースを消費します。
  2. プロファイリングの性質: プロファイリングは、プログラムの「真の」パフォーマンス特性を測定することを目的としています。競合検出器のオーバーヘッドは、この測定を歪める可能性があります。例えば、競合検出器が導入する追加の同期やメモリ割り当てが、プロファイルデータにノイズとして現れ、実際のボトルネックを特定することを困難にするかもしれません。
  3. テストの失敗: コミットメッセージが示唆するように、runtime/pprof のテストが競合検出器有効下で失敗していました。これは、以下のいずれかの理由が考えられます。
    • 競合検出器による誤検出: runtime/pprof の内部実装が、競合検出器の観点からはデータ競合のように見えるが、実際には安全な並行アクセスを行っている場合。プロファイリングツール自体が低レベルの並行処理を多用するため、このような状況は起こり得ます。
    • パフォーマンスの劣化によるタイムアウト: 競合検出器のオーバーヘッドにより、テストの実行時間が大幅に増加し、テストフレームワークのタイムアウトに引っかかっていた可能性。
    • 競合検出器が引き起こす実際の競合: runtime/pprof のテストコードまたはその対象となるコードに、競合検出器がなければ顕在化しないような潜在的なデータ競合が存在し、それが競合検出器によって露呈された可能性。ただし、コミットメッセージのトーンからは、前者の「誤検出」や「有用性の低さ」が主な理由であるように見受けられます。
  4. ビルドタグの適用: // +build !race というビルドタグを pprof_test.go に追加することで、Goのビルドツールは、-race フラグが指定された場合にはこのファイルをコンパイル対象から除外します。これにより、競合検出器が有効な環境では runtime/pprof のテストが実行されなくなり、CI/CDの「race builders」が赤くなる問題が回避されます。
  5. 一時的な解決策: この変更は「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行が追加されました。

  1. // See issue 5659.
  2. // +build !race
  3. 空行

コアとなるコードの解説

追加された // +build !race は、Goのビルドタグです。

  • +build は、Goコンパイラに対する指示であることを示します。
  • ! は論理NOT演算子です。
  • race は、go build -racego 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)上のチェンジリストです。

参考にした情報源リンク