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

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

このコミットは、Go言語のビルドシステムにおけるARMアーキテクチャ向けのテストタイムアウト値を増加させる変更です。具体的には、src/run.bashスクリプト内で、go testコマンドに渡されるタイムアウト値をARM環境の場合に3倍にすることで、freebsd-arm-pinetbsd-arm-qemuといった特定のビルダーがテストを正常に完了できるようにすることを目的としています。

コミット

commit 0a517e458ce6c109e9516e9bfedaad9ee1667f2c
Author: Shenghou Ma <minux.ma@gmail.com>
Date:   Sun Mar 24 16:31:28 2013 +0800

    build: increase timeout for ARM
    in an effort to make builder freebsd-arm-pi and netbsd-arm-qemu pass again.
    
    R=golang-dev, r
    CC=golang-dev
    https://golang.org/cl/7621050

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

https://github.com/golang/go/commit/0a517e458ce6c109e9516e9bfedaad9ee1667f2c

元コミット内容

build: increase timeout for ARM
in an effort to make builder freebsd-arm-pi and netbsd-arm-qemu pass again.

R=golang-dev, r
CC=golang-dev
https://golang.org/cl/7621050

変更の背景

このコミットの背景には、Go言語の継続的インテグレーション(CI)システムにおける特定のARMベースのビルダー(freebsd-arm-pinetbsd-arm-qemu)が、テスト実行時にタイムアウトエラーで失敗していたという問題があります。これらの環境は、Raspberry Piのような組み込みシステムやQEMUのようなエミュレーション環境であり、一般的にx86/x64アーキテクチャの高性能なサーバー環境と比較して、CPU性能やI/O速度が劣る傾向にあります。

テストスイートが複雑であったり、計算負荷が高かったりする場合、これらのリソースが限られた環境では、設定されたデフォルトのタイムアウト時間内にテストが完了しないことが頻繁に発生します。テストの失敗は、コードのバグではなく、単に実行環境の性能不足に起因するものであるため、CIパイプラインの健全性を保つためには、これらの環境に合わせたタイムアウト調整が必要とされました。この変更は、これらのビルダーが再び正常にテストをパスできるようにするための直接的な対応策として導入されました。

前提知識の解説

  • Go言語のビルドシステム: Go言語は、ソースコードから実行可能ファイルを生成するための独自のビルドツールチェーンを持っています。go buildコマンドやgo testコマンドなどがその一部です。Goのビルドシステムは、クロスコンパイル(異なるアーキテクチャやOS向けのバイナリを生成すること)を容易にする設計が特徴です。
  • go testコマンド: Go言語の標準テストツールです。パッケージ内のテスト関数を実行し、結果を報告します。-timeoutフラグを使用すると、テスト全体の実行時間の上限を設定できます。この時間を超えると、テストは強制的に終了され、タイムアウトエラーとなります。
  • ARMアーキテクチャ: Advanced RISC Machinesの略で、モバイルデバイス、組み込みシステム、IoTデバイスなどで広く使用されているCPUアーキテクチャです。x86/x64アーキテクチャと比較して、一般的に消費電力が低く、性能あたりのコストが低いという特徴があります。しかし、その分、単一のタスク処理能力は高性能なサーバー向けCPUに劣ることが多いです。
  • freebsd-arm-pi: FreeBSDオペレーティングシステム上で動作するARMベースのRaspberry Piデバイスを指すGoのビルダー名です。Raspberry Piは、低コストで高性能なシングルボードコンピュータであり、Goのテスト環境としても利用されていました。
  • netbsd-arm-qemu: NetBSDオペレーティングシステム上で動作するARMベースのQEMUエミュレーション環境を指すGoのビルダー名です。QEMUは、異なるCPUアーキテクチャをエミュレートできる仮想化ソフトウェアであり、物理的なARMハードウェアがなくてもテスト環境を構築するために使用されます。エミュレーションは通常、ネイティブ実行よりも性能が低下します。
  • src/run.bash: Goプロジェクトのルートディレクトリにあるシェルスクリプトで、Goのテストスイートを実行するためのスクリプトです。GoのCIシステムや開発者がローカルでテストを実行する際に使用されます。
  • $GOARCH環境変数: Goのビルドシステムで使用される環境変数で、ターゲットとするCPUアーキテクチャを示します。例えば、amd64armarm64などがあります。この変数の値に基づいて、ビルドやテストの動作を調整することができます。
  • GOMAXPROCS環境変数: Goのランタイムが同時に実行できるOSスレッドの最大数を制御する環境変数です。この値は、Goのスケジューラが利用可能なCPUコア数を決定する際に影響を与えます。テストによっては、特定のGOMAXPROCS設定で実行されることがあります。

技術的詳細

このコミットの技術的な核心は、シェルスクリプトsrc/run.bash内で、$GOARCH環境変数の値に基づいてテストのタイムアウト値を動的に調整するロジックを追加した点にあります。

変更前は、go testコマンドの-timeoutフラグには固定値(例: 120s240s)が直接指定されていました。これは、高性能な環境では問題ありませんでしたが、ARMのようなリソースが限られた環境では、テストが完了する前にタイムアウトしてしまう原因となっていました。

変更後、スクリプトは以下のロジックを導入しました。

  1. timeout_scaleという変数を導入し、初期値を1とします。
  2. $GOARCHarmであるかどうかをチェックします。
  3. もし$GOARCHarmであれば、timeout_scaleの値を3に設定します。
  4. go testコマンドの-timeoutフラグに渡す値は、元の固定値に$timeout_scaleを乗算した結果を使用するように変更されました。例えば、120sだったタイムアウトは、ARM環境では$(expr 120 \* $timeout_scale)s、つまり360s(6分)になります。

このアプローチにより、ARM環境でのみテストのタイムアウト時間を延長し、他の高性能な環境では従来のタイムアウト時間を維持することができます。これにより、ARM環境でのテストの安定性を向上させつつ、他の環境でのテストが不必要に長く実行されることを防ぎます。exprコマンドは、シェルスクリプト内で算術演算を行うために使用されます。

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

変更はsrc/run.bashファイルに集中しています。

--- a/src/run.bash
+++ b/src/run.bash
@@ -35,16 +35,20 @@ fi
 # at least runtime/debug test will fail.
 unset GOROOT_FINAL
 
+# increase timeout for ARM up to 3 times the normal value
+timeout_scale=1
+[ "$GOARCH" == "arm" ] && timeout_scale=3
+
 echo '# Testing packages.'
-time go test std -short -timeout=120s
+time go test std -short -timeout=$(expr 120 \* $timeout_scale)s
 echo
 
 echo '# GOMAXPROCS=2 runtime -cpu=1,2,4'
-GOMAXPROCS=2 go test runtime -short -timeout=240s -cpu=1,2,4
+GOMAXPROCS=2 go test runtime -short -timeout=$(expr 240 \* $timeout_scale)s -cpu=1,2,4
 echo
 
 echo '# sync -cpu=10'
-go test sync -short -timeout=120s -cpu=10
+go test sync -short -timeout=$(expr 120 \* $timeout_scale)s -cpu=10
 
 # Race detector only supported on Linux and OS X,
 # and only on amd64, and only when cgo is enabled.

コアとなるコードの解説

  1. timeout_scale=1: timeout_scaleというシェル変数を定義し、デフォルト値を1に設定しています。これは、ARM以外のアーキテクチャの場合にタイムアウト値を変更しないことを意味します。

  2. [ "$GOARCH" == "arm" ] && timeout_scale=3: この行は、シェルスクリプトにおける条件分岐と論理AND演算子の組み合わせです。

    • [ "$GOARCH" == "arm" ]: $GOARCH環境変数の値が文字列"arm"と等しいかどうかをテストします。これは、GoのビルドターゲットがARMアーキテクチャである場合に真となります。
    • &&: 論理AND演算子です。左側のコマンド(ここでは[コマンド)が成功した場合(終了ステータスが0の場合)にのみ、右側のコマンドが実行されます。
    • timeout_scale=3: $GOARCHarmである場合にのみ、timeout_scale変数の値を3に設定します。

    これにより、ARMアーキテクチャでのみtimeout_scale3となり、それ以外のアーキテクチャでは1のままとなります。

  3. time go test std -short -timeout=$(expr 120 \* $timeout_scale)s: この行は、標準パッケージのテストを実行するコマンドです。

    • $(expr 120 \* $timeout_scale): シェルのコマンド置換機能を使用しています。exprコマンドは、引数として与えられた式を評価し、その結果を標準出力に出力します。ここでは、120$timeout_scaleの値を乗算しています。例えば、$timeout_scale3であれば、expr360を返します。
    • s: go test-timeoutフラグは、時間の単位(sは秒、mは分など)を必要とするため、sが追加されています。

    同様の変更が、runtimeパッケージとsyncパッケージのテストコマンドにも適用されています。これにより、各テストのタイムアウト時間が、ARM環境では3倍に延長されることになります。

この変更は、特定のハードウェア特性(ARMの処理能力)を考慮し、CIパイプラインの信頼性を向上させるための実用的な調整であり、Goのビルドシステムが多様な環境で安定して動作するための継続的な努力の一環と言えます。

関連リンク

参考にした情報源リンク

  • Go言語のソースコード(GitHubリポジトリ): https://github.com/golang/go
  • Goのコードレビューシステム(Gerrit): https://go-review.googlesource.com/ (コミットメッセージに記載されているhttps://golang.org/cl/7621050は、このGerritの変更リストへのリンクです。)
  • シェルスクリプトの基本的な構文とコマンド(expr, [など)に関する一般的な情報源。
  • ARMアーキテクチャに関する一般的な情報源。
  • 継続的インテグレーション(CI)の概念に関する一般的な情報源。