[インデックス 16081] ファイルの概要
このコミットは、Go言語のデータ競合検出器に関するドキュメントの改善と、関連するツールの機能強化を目的としています。具体的には、以下の3つのファイルが変更されています。
doc/articles/race_detector.html
: データ競合検出器に関する主要な記事。このコミットでは、記事内の表現の微調整と、より明確な説明が追加されています。doc/go1.1.html
: Go 1.1のリリースノート。データ競合検出器に関する新しいセクションが追加され、その機能と利用方法が紹介されています。src/cmd/go/env.go
:go env
コマンドのソースコード。GORACE
環境変数がgo env
コマンドの出力に含まれるように変更されています。
コミット
- コミットハッシュ:
c4e82bb923d0dac8c97077fd4711b7c00396f957
- 作者: Rob Pike r@golang.org
- 日付: Wed Apr 3 13:56:24 2013 -0700
- 概要: ドキュメント: データ競合検出器のドキュメントをリリースノートにリンクする
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/c4e82bb923d0dac8c97077fd4711b7c00396f957
元コミット内容
doc: link the race detector document into the release notes
Also:
- put GORACE into the go env command
- do minor housekeeping on the race detector article
Fixes #4995.
R=golang-dev, adg
CC=golang-dev
https://golang.org/cl/8319044
変更の背景
このコミットの主な背景は、Go言語における並行処理のバグ、特にデータ競合の検出とデバッグを容易にすることです。Go 1.1のリリースに合わせて、データ競合検出器がGoツールチェーンに組み込まれることになり、その利用を促進するためのドキュメント整備と、関連する環境変数の可視化が必要とされました。
具体的には、以下の点が挙げられます。
- データ競合検出器の導入: Go 1.1でデータ競合検出器が正式に導入されるにあたり、その存在と利用方法をユーザーに広く知らせる必要がありました。リリースノートにリンクを張ることで、新規ユーザーや既存ユーザーがこの重要な機能に気づきやすくなります。
- ドキュメントの改善: データ競合検出器の利用方法、レポート形式、オプション、一般的なデータ競合の例とその修正方法を解説する記事(
race_detector.html
)の内容を、より正確で分かりやすいものに修正する必要がありました。 - 環境変数の可視化: データ競合検出器の動作を制御する
GORACE
環境変数が存在しますが、ユーザーがその存在や設定値を確認しやすくするために、go env
コマンドの出力に含めることが望まれました。これにより、デバッグや設定の確認が容易になります。 - バグ修正 (#4995): このコミットは、GoのIssue #4995を修正するものです。このIssueは、データ競合検出器のドキュメントがリリースノートからリンクされていないこと、および
GORACE
環境変数がgo env
で表示されないことに関するものでした。
前提知識の解説
データ競合 (Data Race)
データ競合とは、複数の並行に実行される処理(Goにおいてはゴルーチン)が、同時に同じメモリ領域にアクセスし、そのうち少なくとも1つのアクセスが書き込みである場合に発生するバグです。データ競合は、プログラムの実行結果を予測不能にし、デバッグを非常に困難にします。Go言語では、Goメモリモデル(The Go Memory Model)によって、データ競合が発生した場合の動作は未定義とされています。
ゴルーチン (Goroutine)
ゴルーチンは、Go言語における軽量な並行実行単位です。スレッドよりもはるかに軽量で、数千、数万のゴルーチンを同時に実行することが可能です。ゴルーチン間の通信は、主にチャネル(channel)を通じて行われますが、共有メモリを介したアクセスも可能です。データ競合は、この共有メモリへのアクセスが適切に同期されていない場合に発生します。
Goメモリモデル (The Go Memory Model)
Goメモリモデルは、Goプログラムにおけるメモリ操作の順序付けと可視性に関するルールを定義しています。これにより、プログラマは並行プログラムの動作を理解し、データ競合を避けるための同期メカニズム(チャネル、ミューテックスなど)を適切に使用することができます。
データ競合検出器 (Race Detector)
データ競合検出器は、Goプログラムの実行中にデータ競合を動的に検出するツールです。プログラムを-race
フラグ付きでビルドまたはテストすることで有効になります。データ競合が検出されると、競合が発生した場所のスタックトレースや、関連するゴルーチンの生成場所などの詳細なレポートが出力されます。
ビルドタグ (Build Tags)
Goのビルドタグは、コンパイル時に特定のコードを含めるか除外するかを制御するためのメカニズムです。ソースファイルの先頭に// +build tagname
のようなコメントを追加することで、そのファイルが特定のビルドタグが有効な場合にのみコンパイルされるように指定できます。データ競合検出器を有効にする-race
フラグを使用すると、race
というビルドタグが自動的に定義され、これを利用して競合検出器が有効な場合にのみ実行されるコードや、逆に競合検出器が有効な場合に除外されるコードを記述できます。
GORACE
環境変数
GORACE
は、Goのデータ競合検出器の動作を制御するための環境変数です。この変数を通じて、レポートの出力先、スタックトレースのパスの短縮、メモリ履歴のサイズなどのオプションを設定できます。
go env
コマンド
go env
コマンドは、Goの環境変数の現在の設定を表示するコマンドです。Goのツールチェーンがどのように設定されているかを確認する際に非常に役立ちます。
技術的詳細
このコミットは、Go言語のデータ競合検出器の導入と利用促進のための重要なステップです。
-
doc/articles/race_detector.html
の更新:- 記事の冒頭で、データ競合が「最も一般的でデバッグが最も困難なバグ」の一つであることが強調されています。
- データ競合検出器の利用方法として、
go build -race
やgo test -race
といったコマンドラインフラグが明確に示されています。 - レポート形式の例が提供され、競合するアクセスとゴルーチンの生成場所のスタックトレースが含まれることが説明されています。
GORACE
環境変数のオプション(log_path
,strip_path_prefix
,history_size
)に関する説明が微調整され、より正確な表現になっています。特にlog_path
のファイル名がlog_path.pid
であることが明記されました。- ビルドタグ
race
を使用して特定のコードやテストをデータ競合検出器の対象から除外する方法が、より簡潔な表現で説明されています。 - データ競合の一般的な例(ループ変数のキャプチャ、保護されていないグローバル変数、プリミティブ型の変数への非アトミックなアクセス)とその修正方法が、コード例を交えて詳細に解説されています。特に、プリミティブ型変数の競合が「無害に見える」ものであっても、非アトミック性、コンパイラ最適化との干渉、プロセッサのメモリアクセス順序変更によってデバッグが困難な問題を引き起こす可能性があることが強調されています。
-
doc/go1.1.html
(Go 1.1 リリースノート) の更新:- Go 1.1のリリースノートに「Race detector」という新しいセクションが追加されました。
- このセクションでは、データ競合検出器が「同じ変数への並行変更のような問題によって引き起こされるプログラムのバグを見つける方法」として紹介されています。
go
ツールに組み込まれていること、および-race
フラグを使用して有効にできることが説明されています。- データ競合検出器に関する詳細なドキュメントへのリンク(
/doc/articles/race_detector.html
)が提供され、ユーザーがさらに深く学ぶことができるようになっています。
-
src/cmd/go/env.go
の更新:go env
コマンドが環境変数の一覧を表示する際に、GORACE
環境変数の値も表示されるように変更されました。これにより、ユーザーはGORACE
の設定を簡単に確認できるようになります。
これらの変更は、Go言語の並行プログラミングにおけるデバッグ体験を大幅に向上させるデータ競合検出器の利用を促進し、その理解を深めることを目的としています。
コアとなるコードの変更箇所
doc/articles/race_detector.html
--- a/doc/articles/race_detector.html
+++ b/doc/articles/race_detector.html
@@ -6,7 +6,9 @@
<h2 id=\"Introduction\">Introduction</h2>
<p>
-Data races are one of the most common and hardest to debug types of bugs in concurrent systems. A data race occurs when two goroutines access the same variable concurrently and at least one of the accesses is a write. See the <a href=\"/ref/mem/\">The Go Memory Model</a> for details.\n+Data races are among the most common and hardest to debug types of bugs in concurrent systems.\n+A data race occurs when two goroutines access the same variable concurrently and at least one of the accesses is a write.\n+See the <a href=\"/ref/mem/\">The Go Memory Model</a> for details.\n </p>
<p>
@@ -32,7 +34,8 @@ func main() {
<h2 id=\"Usage\">Usage</h2>
<p>
-Fortunately, Go includes a built-in data race detector. To use it, add the <code>-race</code> flag to the go command:\n+To help diangose such bugs, Go includes a built-in data race detector.\n+To use it, add the <code>-race</code> flag to the go command:\n </p>
<pre>
@@ -45,7 +48,9 @@ $ go install -race mypkg // to install the package
<h2 id=\"Report_Format\">Report Format</h2>
<p>
-When the race detector finds a data race in the program, it prints a report. The report contains stack traces for conflicting accesses, as well as stacks where the involved goroutines were created. For example:\n+When the race detector finds a data race in the program, it prints a report.\n+The report contains stack traces for conflicting accesses, as well as stacks where the involved goroutines were created.\n+Here is an example:\n </p>
<pre>
@@ -86,7 +91,8 @@ Goroutine 184 (running) created at:\n <h2 id=\"Options\">Options</h2>
<p>
-The <code>GORACE</code> environment variable sets race detector options. The format is:\n+The <code>GORACE</code> environment variable sets race detector options.\n+The format is:\n </p>
<pre>
@@ -100,7 +106,8 @@ The options are:\n <ul>\n <li>\n <code>log_path</code> (default <code>stderr</code>): The race detector writes\n-its report to a file named log_path.pid. The special names <code>stdout</code>\n+its report to a file named <code>log_path.<em>pid</em></code>.\n+The special names <code>stdout</code>\n and <code>stderr</code> cause reports to be written to standard output and\n standard error, respectively.\n </li>\n@@ -117,8 +124,8 @@ from all reported file paths, to make reports more concise.\n \n <li>\n <code>history_size</code> (default <code>1</code>): The per-goroutine memory\n-access history is <code>32K * 2**history_size elements</code>. Increasing this\n-value can avoid a \"failed to restore the stack\" error in reports, but at the\n+access history is <code>32K * 2**history_size elements</code>.\n+Increasing this value can avoid a \"failed to restore the stack\" error in reports, at the\n cost of increased memory usage.\n </li>\n </ul>\n@@ -134,9 +141,10 @@ $ GORACE=\"log_path=/tmp/race/report strip_path_prefix=/my/go/sources/\" go test -\n <h2 id=\"Excluding_Tests\">Excluding Tests</h2>\n \n <p>\n-When you build with <code>-race</code> flag, go command defines additional\n+When you build with <code>-race</code> flag, the <code>go</code> command defines additional\n <a href=\"/pkg/go/build/#Build_Constraints\">build tag</a> <code>race</code>.\n-You can use it to exclude some code/tests under the race detector. For example:\n+You can use the tag to exclude some code and tests when running the race detector.\n+Some examples:\n </p>\n
<pre>
@@ -165,7 +173,8 @@ func TestBaz(t *testing.T) {\n <p>\n To start, run your tests using the race detector (<code>go test -race</code>).\n The race detector only finds races that happen at runtime, so it can\'t find\n-races in code paths that are not executed. If your tests have incomplete coverage,\n+races in code paths that are not executed.\n+If your tests have incomplete coverage,\n you may find more races by running a binary built with <code>-race</code> under a realistic\n workload.\n </p>\n@@ -194,9 +203,9 @@ func main() {\n \n <p>\n The variable <code>i</code> in the function literal is the same variable used by the loop, so\n-the read in the goroutine races with the loop increment. (This program typically\n-prints 55555, not 01234.) The program can be fixed by making a copy of the\n-variable:\n+the read in the goroutine races with the loop increment.\n+(This program typically prints 55555, not 01234.)\n+The program can be fixed by making a copy of the variable:\n </p>\n
<pre>
@@ -246,7 +255,7 @@ func ParallelWrite(data []byte) chan error {\n </pre>\n \n <p>\n-The fix is to introduce new variables in the goroutines (note <code>:=</code>):\n+The fix is to introduce new variables in the goroutines (note the use of <code>:=</code>):\n </p>\n
<pre>
@@ -260,8 +269,8 @@ The fix is to introduce new variables in the goroutines (note <code>:=</code>):\n <h3 id=\"Unprotected_global_variable\">Unprotected global variable</h3>\n \n <p>\n-If the following code is called from several goroutines, it leads to bad races on the <code>service</code> map.\n-Concurrent reads and writes of a map are not safe:\n+If the following code is called from several goroutines, it leads to races on the <code>service</code> map.\n+Concurrent reads and writes of the same map are not safe:\n </p>\n
<pre>
@@ -302,7 +311,8 @@ func LookupService(name string) net.Addr {\n <h3 id=\"Primitive_unprotected_variable\">Primitive unprotected variable</h3>\n \n <p>\n-Data races can happen on variables of primitive types as well (<code>bool</code>, <code>int</code>, <code>int64</code>, etc.), like in the following example:\n+Data races can happen on variables of primitive types as well (<code>bool</code>, <code>int</code>, <code>int64</code>, etc.),\n+as in this example:\n </p>\n
<pre>
@@ -327,12 +337,16 @@ func (w *Watchdog) Start() {\n </pre>\n \n <p>\n-Even such “innocent” data races can lead to hard to debug problems caused by (1) non-atomicity of the memory accesses, (2) interference with compiler optimizations and (3) processor memory access reordering issues.\n+Even such \"innocent\" data races can lead to hard-to-debug problems caused by\n+non-atomicity of the memory accesses,\n+interference with compiler optimizations,\n+or reordering issues accessing processor memory .\n </p>\n
<p>\n A typical fix for this race is to use a channel or a mutex.\n-To preserve the lock-free behavior, one can also use the <a href=\"/pkg/sync/atomic/\"><code>sync/atomic</code></a> package.\n+To preserve the lock-free behavior, one can also use the\n+<a href=\"/pkg/sync/atomic/\"><code>sync/atomic</code></a> package.\n </p>\n ```
### `doc/go1.1.html`
```diff
--- a/doc/go1.1.html
+++ b/doc/go1.1.html
@@ -285,6 +285,17 @@ Programs that depend on the old behavior should be modified to avoid the issue.\n The byte-order-mark change is strictly backward-compatible.\n </p>\n
+<h3 id=\"race\">Race detector</h3>\n+\n+<p>\n+A major addition to the tools is a <em>race detector</em>, a way to find\n+bugs in programs caused by problems like concurrent changes to the same variable.\n+This new facility is built into the <code>go</code> tool.\n+To enable it, set the the <code>-race</code> flag when building or testing your program \n+(for instance, <code>go test -race</code>).\n+The race detector is documented in <a href=\"/doc/articles/race_detector.html\">a separate article</a>.\n+</p>\n+\n <h3 id=\"gc_asm\">The gc assemblers</h3>\n
<p>\n ```
### `src/cmd/go/env.go`
```diff
--- a/src/cmd/go/env.go
+++ b/src/cmd/go/env.go
@@ -42,6 +42,7 @@ func mkEnv() []envVar {\n \t\t{\"GOHOSTOS\", runtime.GOOS},\n \t\t{\"GOOS\", goos},\n \t\t{\"GOPATH\", os.Getenv(\"GOPATH\")},\n+\t\t{\"GORACE\", os.Getenv(\"GORACE\")},\n \t\t{\"GOROOT\", goroot},\n \t\t{\"GOTOOLDIR\", toolDir},\n \t}\n```
## コアとなるコードの解説
### `doc/articles/race_detector.html` の変更点
このファイルへの変更は、データ競合検出器に関する記事の明確性、正確性、および網羅性を向上させることを目的としています。
* **表現の微調整**: 「one of the most common and hardest to debug types of bugs」から「among the most common and hardest to debug types of bugs」への変更や、「Fortunately, Go includes...」から「To help diangose such bugs, Go includes...」への変更は、より客観的で専門的なトーンに調整されています。
* **レポート形式の明確化**: レポート例の導入部分に「Here is an example:」が追加され、読者が続くコードブロックが例であることをより明確に認識できるようになりました。
* **`log_path`の正確な記述**: `GORACE`オプションの`log_path`について、レポートが「`log_path.pid`という名前のファイルに書き込まれる」という詳細が追加されました。これは、複数のプロセスが同時にレポートを生成する場合にファイル名の衝突を避けるための重要な情報です。
* **`history_size`の説明の改善**: `history_size`オプションの説明で、「at the cost of increased memory usage」という表現がより自然な英語に修正されました。
* **ビルドタグの説明の簡潔化**: ビルドタグ`race`の使用方法に関する説明が、「You can use it to exclude some code/tests under the race detector. For example:」から「You can use the tag to exclude some code and tests when running the race detector. Some examples:」に変更され、より簡潔で分かりやすくなっています。
* **データ競合の例の改善**:
* ループ変数のキャプチャの例で、「(This program typically prints 55555, not 01234.)」という補足が、修正前のコードの典型的な動作をより明確に示しています。
* マップへの並行アクセスに関する説明で、「Concurrent reads and writes of a map are not safe:」から「Concurrent reads and writes of the same map are not safe:」に変更され、同じマップへのアクセスであることが強調されています。
* プリミティブ型変数の競合に関する説明で、競合が引き起こす問題の箇条書きがより明確に整理され、可読性が向上しています。
* `sync/atomic`パッケージへのリンクが、より標準的なHTMLのアンカータグの書き方に修正されています。
これらの変更は、ユーザーがデータ競合検出器を効果的に使用し、Goプログラムにおける並行処理のバグを理解し修正するのに役立つように、ドキュメントの品質を高めています。
### `doc/go1.1.html` の変更点
このファイルへの変更は、Go 1.1のリリースノートにデータ競合検出器に関する情報を追加し、その重要性を強調することを目的としています。
* **新しいセクションの追加**: `<h3 id="race">Race detector</h3>`という新しい見出しが追加され、データ競合検出器がGo 1.1の主要な新機能の一つとして位置づけられています。
* **機能の紹介**: データ競合検出器が「同じ変数への並行変更のような問題によって引き起こされるプログラムのバグを見つける方法」として簡潔に紹介されています。
* **利用方法の提示**: `go`ツールに組み込まれており、`go test -race`のように`-race`フラグを使用することで有効にできることが明記されています。
* **詳細ドキュメントへのリンク**: データ競合検出器に関する詳細な情報が記載されている`doc/articles/race_detector.html`へのリンクが提供されています。これにより、リリースノートを読んだユーザーが、さらに詳しい情報を容易に参照できるようになります。
この変更は、Go 1.1のリリースにおけるデータ競合検出器の重要性をユーザーに伝え、その利用を促すための広報的な役割を果たしています。
### `src/cmd/go/env.go` の変更点
このファイルへの変更は、`go env`コマンドの出力に`GORACE`環境変数を追加することを目的としています。
* **`GORACE`の追加**: `mkEnv`関数内で、`os.Getenv("GORACE")`を使用して`GORACE`環境変数の値を取得し、`envVar`スライスに追加しています。これにより、`go env`コマンドを実行した際に、`GORACE`の現在の設定値が表示されるようになります。
この変更は、ユーザーがデータ競合検出器の動作を制御する`GORACE`環境変数の設定を、Goツールを通じて簡単に確認できるようにすることで、デバッグや設定の管理をより便利にするものです。
## 関連リンク
* Go Memory Model: [https://golang.org/ref/mem/](https://golang.org/ref/mem/)
* Go Build Constraints: [https://golang.org/pkg/go/build/#Build_Constraints](https://golang.org/pkg/go/build/#Build_Constraints)
* `sync/atomic`パッケージ: [https://golang.org/pkg/sync/atomic/](https://golang.org/pkg/sync/atomic/)
* Go CL 8319044: [https://golang.org/cl/8319044](https://golang.org/cl/8319044)
* Go Issue #4995: [https://golang.org/issue/4995](https://golang.org/issue/4995)
## 参考にした情報源リンク
* なし (提供されたコミット情報とファイル内容のみに基づいて解説を生成しました。)