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

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

このコミットは、Go言語の math/rand パッケージにおけるテストの実行時間を短縮することを目的としています。特に、TestNonStandardNormalValues テストの実行時間を、go test -short フラグが指定された「ショートモード」の場合に大幅に削減します。これにより、低速なマシン、エミュレータ、動的ツール上でのテスト実行時のパフォーマンスが改善されます。

コミット

f2f0059307e3ff555858b2d51493187f467c17e2

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

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

元コミット内容

math/rand: decrease test duration in short mode
TestNonStandardNormalValues runs 1.5s,
the change reduces it to 0.2s in short mode.
The problem is with slow machines, emulators and dynamic tools.

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

変更の背景

このコミットの主な背景は、math/rand パッケージ内の TestNonStandardNormalValues というテストが、一部の環境(特に低速なマシン、エミュレータ、または動的解析ツールを使用している場合)で実行に時間がかかりすぎることでした。元のテストでは、標準偏差(sd)と平均(m)の値を広範囲にわたって繰り返しテストしており、これがテスト時間の増大につながっていました。

開発者は、通常の開発サイクルやCI/CDパイプラインにおいて、すべてのテストを常にフルで実行する必要がない場合があることを認識していました。特に、クイックチェックやリソースが限られた環境での実行時には、テスト時間を短縮することが重要です。Goのテストフレームワークには、このようなシナリオのために testing.Short() という機能が提供されており、これを利用してテストの実行時間を調整することが可能になります。

この変更は、テストの網羅性を維持しつつ、開発者の生産性を向上させ、より多様な環境でのテスト実行を容易にすることを目的としています。

前提知識の解説

Go言語の testing パッケージと testing.Short()

Go言語には、ユニットテストやベンチマークテストを記述するための標準パッケージ testing が用意されています。テスト関数は Test で始まる名前を持ち、*testing.T 型の引数を取ります。

testing.Short() は、testing パッケージが提供する関数の一つで、go test -short コマンドが実行された場合に true を返します。このフラグは、開発者がテストの実行時間を短縮したい場合に利用されます。例えば、ネットワークアクセスを伴うテストや、大量の計算を伴うテストなど、時間がかかるテストの一部をスキップしたり、テストのイテレーション回数を減らしたりするために使用されます。これにより、CI/CDパイプラインでの高速なフィードバックや、ローカル開発環境での迅速なテスト実行が可能になります。

math/rand パッケージ

math/rand パッケージは、Go言語で擬似乱数を生成するための機能を提供します。このパッケージは、様々な分布(一様分布、正規分布など)に従う乱数を生成する関数を含んでいます。

正規分布 (Normal Distribution)

正規分布(ガウス分布とも呼ばれる)は、統計学において最も重要な確率分布の一つです。平均値の周りにデータが対称的に分布し、平均値から離れるにつれてデータの頻度が減少するという特徴を持ちます。その形状はベル型(釣鐘型)をしており、多くの自然現象や社会現象がこの分布に従うとされています。

  • 平均 (Mean, μ): 分布の中心を示し、データの期待値です。
  • 標準偏差 (Standard Deviation, σ): データの散らばり具合、つまり平均値からのばらつきの度合いを示します。標準偏差が大きいほどデータは広範囲に散らばり、小さいほど平均値の周りに集中します。

math/rand パッケージの NormFloat64() 関数は、標準正規分布(平均0、標準偏差1)に従う乱数を生成します。テスト対象の TestNonStandardNormalValues は、この標準正規分布から生成された乱数を、任意の平均と標準偏差を持つ非標準正規分布に変換するロジックをテストしていると考えられます。

技術的詳細

このコミットは、src/pkg/math/rand/rand_test.go ファイル内の TestNonStandardNormalValues 関数に変更を加えています。

元の TestNonStandardNormalValues 関数では、標準偏差 sd と平均 m の両方について、0.5 から 1000 まで 2 倍ずつ増加させながらテストを実行していました。これにより、sdm の組み合わせが多数生成され、テストの実行時間が長くなっていました。

変更後のコードでは、sdmaxmmax という新しい変数が導入されています。これらの変数は、sdm のループの上限を制御します。

	sdmax := 1000.0
	mmax := 1000.0
	if testing.Short() {
		sdmax = 5
		mmax = 5
	}

このコードブロックは、testing.Short()true を返す(つまり、go test -short が実行された)場合に、sdmaxmmax の値を 1000.0 から 5 に大幅に削減します。これにより、sdm のループのイテレーション回数が劇的に減少します。

具体的には、sdm のループは 0.5 から始まり、2 倍ずつ増加します。

  • 元の 1000 までのループでは、0.5, 1, 2, 4, 8, 16, 32, 64, 128, 256, 512 といった値がテストされます。
  • short モードでの 5 までのループでは、0.5, 1, 2, 4 といった値のみがテストされます。

このように、テスト対象となる sdm の組み合わせの数を減らすことで、テスト全体の実行時間を短縮しています。コミットメッセージにあるように、これによりテスト時間は 1.5s から 0.2s に削減されます。

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

--- a/src/pkg/math/rand/rand_test.go
+++ b/src/pkg/math/rand/rand_test.go
@@ -131,8 +131,14 @@ func TestStandardNormalValues(t *testing.T) {
 }
 
 func TestNonStandardNormalValues(t *testing.T) {
-	for sd := 0.5; sd < 1000; sd *= 2 {
-		for m := 0.5; m < 1000; m *= 2 {
+	sdmax := 1000.0
+	mmax := 1000.0
+	if testing.Short() {
+		sdmax = 5
+		mmax = 5
+	}
+	for sd := 0.5; sd < sdmax; sd *= 2 {
+		for m := 0.5; m < mmax; m *= 2 {
 			for _, seed := range testSeeds {
 				testNormalDistribution(t, numTestSamples, m, sd, seed)
 			}

コアとなるコードの解説

変更の中心は、TestNonStandardNormalValues 関数内の二重ループの条件です。

  1. sdmaxmmax の導入:

    	sdmax := 1000.0
    	mmax := 1000.0
    

    まず、sdmaxmmax という2つの float64 型の変数が導入され、それぞれ 1000.0 で初期化されます。これらは、標準偏差 sd と平均 m のテスト範囲の上限を定義します。

  2. testing.Short() による条件分岐:

    	if testing.Short() {
    		sdmax = 5
    		mmax = 5
    	}
    

    ここで testing.Short() 関数が呼び出されます。もし go test -short コマンドが実行されている場合、この条件は true となり、sdmaxmmax の値が 5 に上書きされます。これにより、テストのイテレーション回数が大幅に削減されます。

  3. ループ条件の変更:

    -	for sd := 0.5; sd < 1000; sd *= 2 {
    -		for m := 0.5; m < 1000; m *= 2 {
    +	for sd := 0.5; sd < sdmax; sd *= 2 {
    +		for m := 0.5; m < mmax; m *= 2 {
    

    元のコードでは、sdm のループ条件が直接 1000 とハードコードされていました。この変更により、ループ条件が新しく導入された sdmaxmmax に置き換えられます。

この変更により、go test を通常実行した場合はこれまで通り広範囲のテストが実行されますが、go test -short を実行した場合は、テスト範囲が限定され、実行時間が大幅に短縮されるようになります。これは、テストの網羅性と実行速度のバランスを取るための一般的なプラクティスです。

関連リンク

参考にした情報源リンク