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

[インデックス 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()という関数が用意されています。これは、特定の条件が満たされた場合にテストの実行をスキップし、その理由を報告するために使用されます。このコミットでは、GOARCH386または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が実行されるのを防ぎ、テストスイート全体の安定性を向上させます。

関連リンク

参考にした情報源リンク