[インデックス 19444] ファイルの概要
このコミットは、Goランタイムのスタック成長テストに関する変更です。具体的には、32ビットアーキテクチャ(386
およびarm
)上でTestStackGrowth
テストをスキップするように修正が加えられています。
コミット
commit 8a2fb87b996a3c4198aa8d9505fd77e560df0bbc
Author: Dave Cheney <dave@cheney.net>
Date: Sun May 25 08:38:59 2014 +1000
runtime: skip stack growth test on 32bit platforms
Update #8083
See discussion in https://groups.google.com/forum/#!topic/golang-dev/dh6Ra_xJomc
LGTM=khr
R=golang-codereviews, gobot, khr
CC=golang-codereviews
https://golang.org/cl/99440048
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/8a2fb87b996a3c4198aa8d9505fd77e560df0bbc
元コミット内容
runtime: skip stack growth test on 32bit platforms
Update #8083
See discussion in https://groups.google.com/forum/#!topic/golang-dev/dh6Ra_xJomc
LGTM=khr
R=golang-codereviews, gobot, khr
CC=golang-codereviews
https://golang.org/cl/99440048
変更の背景
このコミットの背景には、Goランタイムのスタック成長テストが32ビットプラットフォーム(386
およびarm
)で問題を引き起こしていたという事実があります。コミットメッセージに記載されている#8083
は、この問題に関連するGoのイシュートラッカーのエントリを指していると考えられます。また、https://groups.google.com/forum/#!topic/golang-dev/dh6Ra_xJomc
での議論も参照されており、この問題がコミュニティ内で認識され、議論されていたことが示唆されます。
Goのランタイムは、ゴルーチン(goroutine)のスタックを動的に成長・縮小させるメカニズムを持っています。これは、プログラムが必要とするメモリを効率的に利用するための重要な機能です。しかし、特定のアーキテクチャ、特に32ビット環境では、メモリのアドレス空間の制約や、スタックの割り当て・再割り当てに関する特定の実装上の問題により、スタック成長のテストが期待通りに動作しない、あるいは不安定になるケースがあったと推測されます。
このコミットは、テストの失敗がGoランタイムの根本的なバグではなく、32ビット環境におけるテストの制約や、テスト自体の設計上の問題に起因する可能性を考慮し、一時的にテストをスキップすることでCI/CDパイプラインの安定性を確保することを目的としています。これは、問題の根本的な解決策を探る間、開発プロセスを妨げないための一般的なアプローチです。
前提知識の解説
Goランタイムとゴルーチンスタック
Go言語は、軽量な並行処理の単位として「ゴルーチン(goroutine)」を提供します。各ゴルーチンは独自のスタックを持ち、このスタックは必要に応じて動的にサイズが変更されます。
- スタックの成長(Stack Growth): ゴルーチンが関数呼び出しを深くネストしたり、大きなローカル変数を割り当てたりして、現在のスタックサイズが不足すると、Goランタイムは自動的にスタックを拡張します。通常、これはより大きな新しいスタック領域を割り当て、古いスタックの内容を新しい領域にコピーすることで行われます。
- スタックの縮小(Stack Shrinkage): 逆に、ゴルーチンが不要なスタック領域を解放すると、ランタイムはスタックを縮小してメモリをシステムに返還することがあります。
- スタックの初期サイズ: ゴルーチンのスタックは非常に小さい初期サイズ(通常は数KB)で開始されます。これにより、数百万のゴルーチンを同時に実行してもメモリ効率が良くなります。
32ビットアーキテクチャとメモリ管理
32ビットシステムでは、メモリのアドレス空間が2^32バイト、つまり4GBに制限されます。これは、64ビットシステム(2^64バイト)と比較して大幅に小さいです。この制限は、特に大きなスタックを扱う場合や、多数のゴルーチンが同時にスタックを成長させようとする場合に、メモリの断片化やアドレス空間の枯渇といった問題を引き起こす可能性があります。
- アドレス空間の制約: 32ビット環境では、利用可能な仮想アドレス空間が限られているため、連続した大きなメモリブロックを確保することが難しい場合があります。スタックの成長は、しばしば連続したメモリ領域を必要とするため、この制約が問題となることがあります。
- ポインタのサイズ: 32ビットシステムではポインタが4バイトですが、64ビットシステムでは8バイトです。これは、メモリ使用量やアラインメントに影響を与える可能性があります。
GOARCH
環境変数
GOARCH
はGoのビルドシステムで使用される環境変数で、ターゲットとするアーキテクチャを指定します。例えば、amd64
は64ビットIntel/AMDアーキテクチャ、386
は32ビットIntel/AMDアーキテクチャ、arm
はARMアーキテクチャを指します。このコミットでは、GOARCH
の値に基づいてテストの実行を条件付けています。
技術的詳細
このコミットは、src/pkg/runtime/stack_test.go
ファイル内のTestStackGrowth
関数に条件付きスキップロジックを追加することで、特定のアーキテクチャでのテストの不安定性に対処しています。
Goのテストフレームワーク(testing
パッケージ)には、t.Skipf()
という関数が用意されています。これは、特定の条件が満たされた場合にテストの実行をスキップし、その理由を報告するために使用されます。このコミットでは、GOARCH
が386
またはarm
である場合に、TestStackGrowth
テストをスキップするように指示しています。
このアプローチは、テストが特定の環境で一貫して失敗する場合に採用される一般的なプラクティスです。テストの失敗が、テスト対象の機能のバグではなく、テスト環境の特性やテスト自体の限界に起因する場合に特に有効です。これにより、CIシステムが不必要な失敗で赤くなるのを防ぎ、開発者がより重要な問題に集中できるようになります。
ただし、テストをスキップすることは、その環境での機能の動作を検証しないことを意味します。したがって、このスキップは一時的な措置であり、将来的には32ビットプラットフォームでのスタック成長の問題を根本的に解決するか、またはその環境に適した新しいテストを設計する必要があることを示唆しています。
コアとなるコードの変更箇所
変更はsrc/pkg/runtime/stack_test.go
ファイルに集中しています。
--- a/src/pkg/runtime/stack_test.go
+++ b/src/pkg/runtime/stack_test.go
@@ -123,6 +123,10 @@ func TestStackMem(t *testing.T) {
// Test stack growing in different contexts.
func TestStackGrowth(t *testing.T) {
+ switch GOARCH {
+ case "386", "arm":
+ t.Skipf("skipping test on %q; see issue 8083", GOARCH)
+ }
t.Parallel()
var wg sync.WaitGroup
コアとなるコードの解説
追加されたコードブロックは以下の通りです。
switch GOARCH {
case "386", "arm":
t.Skipf("skipping test on %q; see issue 8083", GOARCH)
}
switch GOARCH
: これは、Goのビルド時に設定されるGOARCH
環境変数の値に基づいて処理を分岐させるGoのswitch
ステートメントです。GOARCH
は、プログラムが実行されるターゲットアーキテクチャを示します。case "386", "arm"
:GOARCH
の値が"386"
(32ビットIntel/AMDアーキテクチャ)または"arm"
(ARMアーキテクチャ)のいずれかである場合に、このcase
ブロック内のコードが実行されます。t.Skipf("skipping test on %q; see issue 8083", GOARCH)
: これはGoのtesting
パッケージが提供するメソッドです。t.Skipf()
は、現在のテストをスキップし、指定されたフォーマット文字列と引数を使用してスキップ理由を報告します。"skipping test on %q; see issue 8083"
は、スキップ理由のメッセージです。%q
は、GOARCH
の値を引用符で囲んで出力するためのフォーマット指定子です。GOARCH
は、スキップ理由メッセージに埋め込まれる現在のアーキテクチャ名です。see issue 8083
は、このスキップが関連するイシュー番号を参照しており、詳細な背景情報がそこにあることを示唆しています。
このコードは、32ビットアーキテクチャ上でTestStackGrowth
が実行されるのを防ぎ、テストスイート全体の安定性を向上させます。
関連リンク
- Go言語の公式ドキュメント: https://golang.org/doc/
- Goのテストパッケージ (
testing
): https://pkg.go.dev/testing - Goのランタイムに関する情報(一般的な概念): https://go.dev/doc/articles/go_programming_language_faq#goroutines
参考にした情報源リンク
- Goのコミット履歴: https://github.com/golang/go/commits/master
- Goのコードレビューシステム (Gerrit): https://go-review.googlesource.com/ (このコミットのCL:
https://go.googlesource.com/go/+/99440048
) - Google Groups
golang-dev
フォーラム: https://groups.google.com/forum/#!forum/golang-dev (コミットメッセージで参照されている議論:https://groups.google.com/forum/#!topic/golang-dev/dh6Ra_xJomc
)