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

[インデックス 13474] ファイルの概要

本コミットは、Go言語のビルドシステムにおけるテスト実行スクリプト src/run.bash から、GOMAXPROCS=32 を設定して特定のテストを実行する行を元に戻す(リバートする)ものです。これは、GOMAXPROCS が1より大きい値に設定されている場合に一部のテストが失敗するという問題に対処するための暫定的な措置です。

コミット

このコミットは、以前追加された GOMAXPROCS=32 を設定してテストを実行する変更(コミットハッシュ 61d1d72136f7)を元に戻すものです。コミットメッセージによると、GOMAXPROCS が1より大きい値に設定されている場合に、いくつかのテストが現在失敗しているため、このリバートが必要とされました。

GitHub上でのコミットページへのリンク

https://github.com/golang/go/commit/d5c2154caf1d5826328a9fbc14e89001599f0a30

元コミット内容

build: revert 61d1d72136f7 (add few tests with GOMAXPROCS=32)
Some tests currently fail with GOMAXPROCS>1

R=golang-dev
CC=golang-dev
https://golang.org/cl/6398044

変更の背景

この変更の背景には、Go言語の並行処理モデルとテストの安定性に関する課題があります。Go言語はゴルーチンとチャネルを用いた並行処理を強力にサポートしていますが、その動作は GOMAXPROCS 環境変数によって影響を受けます。GOMAXPROCS は、Goランタイムが同時に実行できるOSスレッドの最大数を制御します。

以前のコミット 61d1d72136f7 では、GOMAXPROCS=32 という高い並行度でテストを実行することで、より多くのCPUコアが利用可能な環境でのGoプログラムの挙動を検証しようとしました。しかし、この設定でテストを実行したところ、一部のテストが予期せず失敗することが判明しました。これは、テストコード自体が並行処理の競合条件やデッドロック、あるいは特定のタイミングに依存するバグを抱えていた可能性を示唆しています。

テストの失敗は、Go言語の安定性と信頼性にとって重大な問題であるため、開発チームは一時的にこの高並行度テストの実行を停止し、問題の根本原因を特定して修正する時間を確保するために、関連する変更をリバートすることを決定しました。

前提知識の解説

Go言語の並行処理とGOMAXPROCS

Go言語は、軽量なスレッドである「ゴルーチン(goroutine)」と、ゴルーチン間の通信を安全に行うための「チャネル(channel)」を言語レベルでサポートしています。これにより、並行処理を容易に記述できます。

GOMAXPROCS は、Goランタイムが同時に実行できるOSスレッド(M: Machine)の最大数を設定する環境変数です。Goのスケジューラは、このMの上に多数のゴルーチン(G: Goroutine)を多重化して実行します。

  • GOMAXPROCS=1: Goランタイムは1つのOSスレッドのみを使用します。これにより、ゴルーチンは協調的マルチタスク(cooperative multitasking)のように動作し、真の並行実行は行われません。これは、デバッグや特定の競合条件を再現する際に役立つことがあります。
  • GOMAXPROCS > 1: Goランタイムは指定された数のOSスレッドを使用し、複数のゴルーチンが真に並行して実行される可能性があります。これにより、マルチコアプロセッサの性能を最大限に活用できますが、並行処理に起因する競合条件やデッドロックなどのバグが顕在化しやすくなります。

このコミットが行われた2012年頃のGo言語では、GOMAXPROCS のデフォルト値は1でした。つまり、明示的に設定しない限り、Goプログラムは単一のOSスレッド上で動作していました。そのため、GOMAXPROCS > 1 でのテストは、より現実的なマルチコア環境での挙動を検証するために重要でしたが、同時に新たな問題を発見するきっかけにもなりました。

go test コマンド

go test は、Go言語の標準的なテスト実行ツールです。Goのソースコード内に記述されたテスト関数(TestXxx という命名規則に従う関数)を自動的に発見し、実行します。

  • go test [パッケージ名]:指定されたパッケージのテストを実行します。
  • -cpu=N:テストをN個のCPUで並行して実行します。これは GOMAXPROCS の設定とは異なり、テストスイート内のテスト関数を並行実行するためのものです。
  • -short:実行時間の長いテストをスキップします。
  • -timeout=D:テストの実行時間制限を設定します。

src/run.bash スクリプト

src/run.bash は、Goプロジェクトのテストスイート全体を実行するためのシェルスクリプトです。GoのビルドシステムやCI/CDパイプラインの一部として利用され、様々な設定や条件でテストを実行することで、Go言語の安定性と品質を保証する役割を担っています。

技術的詳細

このコミットの技術的詳細は、Go言語の並行処理におけるテストの難しさと、GOMAXPROCS の設定がテスト結果に与える影響に集約されます。

GOMAXPROCS=32 のような高い値でテストを実行することは、以下のような目的があります。

  1. 並行処理バグの顕在化: 複数のOSスレッド上でゴルーチンが並行して実行されることで、単一スレッドでは発生しにくい競合条件、デッドロック、ライブロックなどの並行処理バグが露呈しやすくなります。これは、Go言語の並行処理モデルの堅牢性を検証するために非常に重要です。
  2. スケジューラのストレステスト: 多数のゴルーチンが多数のOSスレッド上で動作することで、Goランタイムのスケジューラが効率的かつ公平にゴルーチンをスケジュールできるかどうかのストレステストになります。

しかし、今回のケースでは、この高並行度テストが既存のテストの失敗を引き起こしました。これは以下のいずれかの理由が考えられます。

  • テストコードの不備: テスト自体が並行処理を考慮して設計されておらず、GOMAXPROCS > 1 の環境で非決定的な失敗を引き起こす競合条件を含んでいた。
  • Goランタイム/標準ライブラリのバグ: テスト対象のGoランタイムや標準ライブラリ自体に、特定の並行条件下で発生するバグが存在した。コミットメッセージの「Some tests currently fail with GOMAXPROCS>1」という記述から、後者の可能性も示唆されます。特に runtime, net/http, crypto/tls, encoding/base64 といったコアなパッケージのテストが対象になっていることから、Goランタイムや標準ライブラリの並行処理に関する問題が疑われます。

このリバートは、問題の根本原因を特定し、修正するまでの間、CI/CDパイプラインが安定して動作し、他の開発作業がブロックされないようにするための実用的な判断です。

コアとなるコードの変更箇所

src/run.bash ファイルから以下の5行が削除されました。

--- a/src/run.bash
+++ b/src/run.bash
@@ -39,11 +39,6 @@ echo
 
 echo '# sync -cpu=10'
 go test sync -short -timeout=120s -cpu=10
-echo
-
-echo '# GOMAXPROCS=32 go test runtime net/http crypto/tls encoding/base64'
-GOMAXPROCS=32 go test runtime net/http crypto/tls encoding/base64
-echo
 
 xcd() {
 	echo

コアとなるコードの解説

削除された行は、src/run.bash スクリプト内で特定のGoパッケージ(runtime, net/http, crypto/tls, encoding/base64)のテストを GOMAXPROCS=32 という環境変数設定で実行する部分でした。

具体的には:

  1. echo '# GOMAXPROCS=32 go test runtime net/http crypto/tls encoding/base64':これは単に、次に実行されるコマンドの内容を標準出力に表示するための行です。
  2. GOMAXPROCS=32 go test runtime net/http crypto/tls encoding/base64:この行が、問題を引き起こしていたテスト実行コマンドの本体です。
    • GOMAXPROCS=32:このコマンドの実行中のみ、GOMAXPROCS 環境変数を32に設定します。これにより、Goランタイムは最大32個のOSスレッドを使用してゴルーチンをスケジュールしようとします。
    • go test runtime net/http crypto/tls encoding/base64runtime(Goランタイム自体)、net/http(HTTPクライアント/サーバー)、crypto/tls(TLS/SSL暗号化)、encoding/base64(Base64エンコーディング)といった、Go言語の非常に基本的なかつ並行処理が頻繁に利用される可能性のあるパッケージのテストを実行します。

これらの行を削除することで、GOMAXPROCS=32 の設定下でのテスト実行が停止され、CI/CDパイプラインにおけるテストの失敗が回避されます。これはあくまで一時的な解決策であり、根本的な問題(GOMAXPROCS > 1 でテストが失敗する原因)は別途調査・修正される必要があります。

関連リンク

参考にした情報源リンク