[インデックス 14009] ファイルの概要
このコミットは、Go言語の標準ライブラリであるtesting
パッケージのドキュメントを更新し、ベンチマークテストにおけるタイマーのリセット方法に関する推奨プラクティスを変更するものです。具体的には、StopTimer()
とStartTimer()
のペアを使用する代わりに、ResetTimer()
関数を使用するようにドキュメントの記述が修正されています。
コミット
commit 727e5ce95fe11653b4ba197771173c80359bdada
Author: Shenghou Ma <minux.ma@gmail.com>
Date: Wed Oct 3 11:41:18 2012 +0800
testing: update package docs to use ResetTimer() instead of StopTimer/StartTimer()
R=golang-dev, rsc, r
CC=golang-dev
https://golang.org/cl/6591051
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/727e5ce95fe11653b4ba197771173c80359bdada
元コミット内容
testing: update package docs to use ResetTimer() instead of StopTimer/StartTimer()
R=golang-dev, rsc, r
CC=golang-dev
https://golang.org/cl/6591051
変更の背景
Go言語のtesting
パッケージは、ユニットテストとベンチマークテストのための機能を提供します。ベンチマークテストでは、特定のコードブロックの実行時間を正確に測定することが目的です。しかし、ベンチマーク対象のコードを実行する前に、初期化やセットアップに時間がかかる場合があります。このようなセットアップ時間は、ベンチマークの測定結果に含めるべきではありません。
以前は、このような場合にb.StopTimer()
とb.StartTimer()
のペアを使用して、セットアップコードの実行中にタイマーを一時停止し、セットアップ完了後に再開するという方法が推奨されていました。しかし、この方法はコードが冗長になりがちで、またタイマーの停止と再開のロジックが複雑になる可能性がありました。
b.ResetTimer()
関数は、ベンチマークのタイマーをリセットし、それまでの経過時間をゼロにする機能を提供します。これにより、ベンチマーク対象のコードが実行される直前にタイマーをリセットすることで、セットアップ時間を測定から除外するという、より簡潔で意図が明確な方法が提供されました。このコミットは、この新しい、より良いプラクティスをドキュメントに反映させることを目的としています。
また、ベンチマークの出力形式に関するドキュメントの記述も、より簡潔な形式(BenchmarkHello
からtesting.BenchmarkHello
を削除)に更新されています。これは、Goのパッケージ名が通常、ベンチマーク関数の出力には含まれないという慣習に合わせたものです。
前提知識の解説
Go言語のtesting
パッケージ
Go言語には、標準でテストフレームワークが組み込まれており、testing
パッケージを通じて提供されます。このパッケージは、ユニットテスト、ベンチマークテスト、および例(Example)の記述をサポートします。
- ユニットテスト:
func TestXxx(*testing.T)
という形式の関数で記述され、コードの特定の単位が正しく動作するかを検証します。 - ベンチマークテスト:
func BenchmarkXxx(*testing.B)
という形式の関数で記述され、コードのパフォーマンスを測定します。*testing.B
型の引数b
は、ベンチマークの実行回数(b.N
)やタイマー制御のためのメソッドを提供します。
ベンチマークテストの基本的な考え方
Goのベンチマークテストは、b.N
というループ回数を自動的に調整することで、信頼性の高い測定結果を得ようとします。b.N
は、ベンチマーク関数が十分に長い時間(通常は1秒以上)実行されるように、go test
コマンドによって動的に決定されます。
*testing.B
のメソッド
b.N
: ベンチマーク関数が実行されるループの回数。ベンチマーク対象のコードはこの回数だけループ内で実行されます。b.StopTimer()
: ベンチマークのタイマーを一時停止します。b.StartTimer()
: 一時停止したタイマーを再開します。b.ResetTimer()
: タイマーをリセットし、それまでの経過時間をゼロにします。これは、ベンチマーク対象のコードが始まる直前に、セットアップ時間を測定から除外するために使用されます。
技術的詳細
このコミットの技術的な変更点は、src/pkg/testing/testing.go
ファイルのコメントと例のコードスニペットの修正に集約されます。
変更前は、ベンチマークのセットアップ時間を測定から除外するために、以下のようなコードが例として示されていました。
// If a benchmark needs some expensive setup before running, the timer
// may be stopped:
// func BenchmarkBigLen(b *testing.B) {
// b.StopTimer()
// big := NewBig()
// b.StartTimer()
// for i := 0; i < b.N; i++ {
// big.Len()
// }
// }
この例では、NewBig()
という高コストなセットアップ関数の実行中にb.StopTimer()
とb.StartTimer()
でタイマーを一時停止・再開しています。
変更後は、この部分が以下のように修正されました。
// If a benchmark needs some expensive setup before running, the timer
// may be reset:
// func BenchmarkBigLen(b *testing.B) {
// big := NewBig()
// b.ResetTimer()
// for i := 0; i < b.N; i++ {
// big.Len()
// }
// }
この修正により、NewBig()
の実行後にb.ResetTimer()
を呼び出すことで、それまでの経過時間をリセットし、for
ループ内のbig.Len()
の実行時間のみが測定対象となることが明確に示されています。この方法は、StopTimer()
とStartTimer()
のペアを使用するよりも簡潔で、意図が明確です。
また、ベンチマークの出力例も変更されています。
変更前:
testing.BenchmarkHello 10000000 282 ns/op
変更後:
BenchmarkHello 10000000 282 ns/op
これは、go test -bench
コマンドの出力において、ベンチマーク関数の名前の前にパッケージ名(testing.
)が付かないのが一般的であるため、ドキュメントの記述を実際の出力に合わせるための修正です。
コアとなるコードの変更箇所
--- a/src/pkg/testing/testing.go
+++ b/src/pkg/testing/testing.go
@@ -27,15 +27,14 @@
//
// The benchmark package will vary b.N until the benchmark function lasts
// long enough to be timed reliably. The output
-// testing.BenchmarkHello 10000000 282 ns/op
+// BenchmarkHello 10000000 282 ns/op
// means that the loop ran 10000000 times at a speed of 282 ns per loop.
//
// If a benchmark needs some expensive setup before running, the timer
-// may be stopped:\n+// may be reset:\n // func BenchmarkBigLen(b *testing.B) {
-// b.StopTimer()\n // big := NewBig()\n-// b.StartTimer()\n+// b.ResetTimer()\n // for i := 0; i < b.N; i++ {\n // big.Len()\n // }\n```
## コアとなるコードの解説
このdiffは、`src/pkg/testing/testing.go`ファイル内のコメントブロック、特にベンチマークテストのタイマー制御に関する説明部分を修正しています。
1. **出力例の修正**:
`- testing.BenchmarkHello 10000000 282 ns/op`
`+ BenchmarkHello 10000000 282 ns/op`
これは、ベンチマーク結果の出力例から`testing.`というプレフィックスを削除しています。実際の`go test -bench`の出力では、通常、ベンチマーク関数の名前のみが表示され、パッケージ名は含まれません。この変更は、ドキュメントが実際の挙動と一致するようにするためのものです。
2. **タイマー制御の推奨方法の変更**:
`- // If a benchmark needs some expensive setup before running, the timer`
`- // may be stopped:`
`+ // If a benchmark needs some expensive setup before running, the timer`
`+ // may be reset:`
この変更は、高コストなセットアップを伴うベンチマークにおいて、タイマーを「停止する(stopped)」のではなく、「リセットする(reset)」という表現に修正しています。これは、`b.StopTimer()`と`b.StartTimer()`のペアを使うよりも、`b.ResetTimer()`を使う方が推奨されるようになったことを示唆しています。
3. **コード例の修正**:
`- b.StopTimer()`
`- big := NewBig()`
`- b.StartTimer()`
`+ big := NewBig()`
`+ b.ResetTimer()`
この部分が最も重要な変更です。以前の例では、セットアップコード(`big := NewBig()`)の前後で`b.StopTimer()`と`b.StartTimer()`を呼び出してタイマーを一時停止・再開していました。新しい例では、セットアップコードの実行後に`b.ResetTimer()`を一度呼び出すだけで、タイマーをリセットし、その後のループの実行時間のみを測定対象としています。
この変更は、Goの`testing`パッケージにおけるベンチマークのベストプラクティスが進化し、より簡潔で効率的な`b.ResetTimer()`の使用が推奨されるようになったことを明確に示しています。これにより、ベンチマークコードの可読性が向上し、セットアップ時間の除外がより直感的に行えるようになります。
## 関連リンク
* Go言語の`testing`パッケージのドキュメント: [https://pkg.go.dev/testing](https://pkg.go.dev/testing)
* Go言語のベンチマークに関する公式ブログ記事(関連する可能性のあるもの): Goのバージョンアップに伴い、ベンチマークの機能や推奨事項が更新されることがあります。
## 参考にした情報源リンク
* Go言語の公式ドキュメント
* Go言語の`testing`パッケージのソースコード
* Go言語のコミット履歴と関連するコードレビュー(Gerrit CL: `https://golang.org/cl/6591051`)
* Go言語のベンチマークに関する一般的な情報源(ブログ、チュートリアルなど)
# [インデックス 14009] ファイルの概要
このコミットは、Go言語の標準ライブラリである`testing`パッケージのドキュメントを更新し、ベンチマークテストにおけるタイマーのリセット方法に関する推奨プラクティスを変更するものです。具体的には、`StopTimer()`と`StartTimer()`のペアを使用する代わりに、`ResetTimer()`関数を使用するようにドキュメントの記述が修正されています。
## コミット
commit 727e5ce95fe11653b4ba197771173c80359bdada Author: Shenghou Ma minux.ma@gmail.com Date: Wed Oct 3 11:41:18 2012 +0800
testing: update package docs to use ResetTimer() instead of StopTimer/StartTimer()
R=golang-dev, rsc, r
CC=golang-dev
https://golang.org/cl/6591051
## GitHub上でのコミットページへのリンク
[https://github.com/golang/go/commit/727e5ce95fe11653b4ba197771173c80359bdada](https://github.com/golang/go/commit/727e5ce95fe11653b4ba197771173c80359bdada)
## 元コミット内容
testing: update package docs to use ResetTimer() instead of StopTimer/StartTimer()
R=golang-dev, rsc, r CC=golang-dev https://golang.org/cl/6591051
## 変更の背景
Go言語の`testing`パッケージは、ユニットテストとベンチマークテストのための機能を提供します。ベンチマークテストでは、特定のコードブロックの実行時間を正確に測定することが目的です。しかし、ベンチマーク対象のコードを実行する前に、初期化やセットアップに時間がかかる場合があります。このようなセットアップ時間は、ベンチマークの測定結果に含めるべきではありません。
以前は、このような場合に`b.StopTimer()`と`b.StartTimer()`のペアを使用して、セットアップコードの実行中にタイマーを一時停止し、セットアップ完了後に再開するという方法が推奨されていました。しかし、この方法はコードが冗長になりがちで、またタイマーの停止と再開のロジックが複雑になる可能性がありました。
`b.ResetTimer()`関数は、ベンチマークのタイマーをリセットし、それまでの経過時間をゼロにする機能を提供します。これにより、ベンチマーク対象のコードが実行される直前にタイマーをリセットすることで、セットアップ時間を測定から除外するという、より簡潔で意図が明確な方法が提供されました。このコミットは、この新しい、より良いプラクティスをドキュメントに反映させることを目的としています。
また、ベンチマークの出力形式に関するドキュメントの記述も、より簡潔な形式(`BenchmarkHello`から`testing.BenchmarkHello`を削除)に更新されています。これは、Goのパッケージ名が通常、ベンチマーク関数の出力には含まれないという慣習に合わせたものです。
## 前提知識の解説
### Go言語の`testing`パッケージ
Go言語には、標準でテストフレームワークが組み込まれており、`testing`パッケージを通じて提供されます。このパッケージは、ユニットテスト、ベンチマークテスト、および例(Example)の記述をサポートします。
* **ユニットテスト**: `func TestXxx(*testing.T)`という形式の関数で記述され、コードの特定の単位が正しく動作するかを検証します。
* **ベンチマークテスト**: `func BenchmarkXxx(*testing.B)`という形式の関数で記述され、コードのパフォーマンスを測定します。`*testing.B`型の引数`b`は、ベンチマークの実行回数(`b.N`)やタイマー制御のためのメソッドを提供します。
### ベンチマークテストの基本的な考え方
Goのベンチマークテストは、`b.N`というループ回数を自動的に調整することで、信頼性の高い測定結果を得ようとします。`b.N`は、ベンチマーク関数が十分に長い時間(通常は1秒以上)実行されるように、`go test`コマンドによって動的に決定されます。
### `*testing.B`のメソッド
* **`b.N`**: ベンチマーク関数が実行されるループの回数。ベンチマーク対象のコードはこの回数だけループ内で実行されます。
* **`b.StopTimer()`**: ベンチマークのタイマーを一時停止します。この関数は、`b.N`ループ内で、測定対象外の処理(例:各イテレーションごとのセットアップやティアダウン)を実行する際に使用されます。
* **`b.StartTimer()`**: 一時停止したタイマーを再開します。`b.StopTimer()`と対で使用され、測定対象の処理が始まる直前に呼び出されます。
* **`b.ResetTimer()`**: タイマーをリセットし、それまでの経過時間をゼロにします。これは、ベンチマーク対象のコードが始まる直前に、ベンチマーク関数全体の初期セットアップ時間を測定から除外するために使用されます。`b.N`ループに入る前に一度だけ呼び出すのが一般的です。
`b.ResetTimer()`と`b.StopTimer()/b.StartTimer()`の主な違いは、`ResetTimer`がタイマーをゼロにリセットするのに対し、`StopTimer`/`StartTimer`はタイマーを一時停止/再開する点です。`ResetTimer`は主にベンチマークループに入る前の高コストなセットアップを除外するために使われ、`StopTimer`/`StartTimer`はベンチマークループ内の各イテレーションで発生する測定対象外の処理を除外するために使われます。
## 技術的詳細
このコミットの技術的な変更点は、`src/pkg/testing/testing.go`ファイルのコメントと例のコードスニペットの修正に集約されます。
変更前は、ベンチマークのセットアップ時間を測定から除外するために、以下のようなコードが例として示されていました。
```go
// If a benchmark needs some expensive setup before running, the timer
// may be stopped:
// func BenchmarkBigLen(b *testing.B) {
// b.StopTimer()
// big := NewBig()
// b.StartTimer()
// for i := 0; i < b.N; i++ {
// big.Len()
// }
// }
この例では、NewBig()
という高コストなセットアップ関数の実行中にb.StopTimer()
とb.StartTimer()
でタイマーを一時停止・再開していました。これは、セットアップ処理がベンチマークの測定対象から除外されることを意図しています。
変更後は、この部分が以下のように修正されました。
// If a benchmark needs some expensive setup before running, the timer
// may be reset:
// func BenchmarkBigLen(b *testing.B) {
// big := NewBig()
// b.ResetTimer()
// for i := 0; i < b.N; i++ {
// big.Len()
// }
// }
この修正により、NewBig()
の実行後にb.ResetTimer()
を呼び出すことで、それまでの経過時間をリセットし、for
ループ内のbig.Len()
の実行時間のみが測定対象となることが明確に示されています。この方法は、StopTimer()
とStartTimer()
のペアを使用するよりも簡潔で、意図が明確です。ResetTimer()
は、ベンチマークの初期化フェーズで発生する一度きりの高コストな処理を測定から除外するのに適しています。
また、ベンチマークの出力例も変更されています。
変更前:
testing.BenchmarkHello 10000000 282 ns/op
変更後:
BenchmarkHello 10000000 282 ns/op
これは、go test -bench
コマンドの出力において、ベンチマーク関数の名前の前にパッケージ名(testing.
)が付かないのが一般的であるため、ドキュメントの記述を実際の出力に合わせるための修正です。これにより、ドキュメントの正確性が向上しています。
コアとなるコードの変更箇所
--- a/src/pkg/testing/testing.go
+++ b/src/pkg/testing/testing.go
@@ -27,15 +27,14 @@
//
// The benchmark package will vary b.N until the benchmark function lasts
// long enough to be timed reliably. The output
-// testing.BenchmarkHello 10000000 282 ns/op
+// BenchmarkHello 10000000 282 ns/op
// means that the loop ran 10000000 times at a speed of 282 ns per loop.\n //
// If a benchmark needs some expensive setup before running, the timer
-// may be stopped:\n+// may be reset:\n // func BenchmarkBigLen(b *testing.B) {
-// b.StopTimer()\n // big := NewBig()\n-// b.StartTimer()\n+// b.ResetTimer()\n // for i := 0; i < b.N; i++ {\n // big.Len()\n // }\n```
## コアとなるコードの解説
このdiffは、`src/pkg/testing/testing.go`ファイル内のコメントブロック、特にベンチマークテストのタイマー制御に関する説明部分を修正しています。
1. **出力例の修正**:
`- testing.BenchmarkHello 10000000 282 ns/op`
`+ BenchmarkHello 10000000 282 ns/op`
この変更は、ベンチマーク結果の出力例から`testing.`というプレフィックスを削除しています。実際の`go test -bench`の出力では、通常、ベンチマーク関数の名前のみが表示され、パッケージ名は含まれません。この変更は、ドキュメントが実際の挙動と一致するようにするための、細かながらも重要な修正です。
2. **タイマー制御の推奨方法の変更**:
`- // If a benchmark needs some expensive setup before running, the timer`
`- // may be stopped:`
`+ // If a benchmark needs some expensive setup before running, the timer`
`+ // may be reset:`
この変更は、高コストなセットアップを伴うベンチマークにおいて、タイマーを「停止する(stopped)」のではなく、「リセットする(reset)」という表現に修正しています。これは、`b.StopTimer()`と`b.StartTimer()`のペアを使うよりも、`b.ResetTimer()`を使う方が推奨されるようになったことを示唆しています。`ResetTimer()`は、ベンチマークの測定開始時点を明確に定義し、それ以前の処理時間を完全に無視できるため、よりクリーンな測定が可能です。
3. **コード例の修正**:
`- b.StopTimer()`
`- big := NewBig()`
`- b.StartTimer()`
`+ big := NewBig()`
`+ b.ResetTimer()`
この部分が最も重要な変更です。以前の例では、セットアップコード(`big := NewBig()`)の前後で`b.StopTimer()`と`b.StartTimer()`を呼び出してタイマーを一時停止・再開していました。これは、セットアップ処理の時間をベンチマークの合計時間から除外するための一般的なパターンでした。
新しい例では、セットアップコードの実行後に`b.ResetTimer()`を一度呼び出すだけで、タイマーをリセットし、その後のループの実行時間のみを測定対象としています。このアプローチは、`StopTimer()`と`StartTimer()`のペアを使用するよりもコードが簡潔になり、意図がより明確になります。`ResetTimer()`は、ベンチマーク関数が呼び出されてから`ResetTimer()`が呼び出されるまでの時間を、ベンチマークの測定対象から完全に除外します。
この変更は、Goの`testing`パッケージにおけるベンチマークのベストプラクティスが進化し、より簡潔で効率的な`b.ResetTimer()`の使用が推奨されるようになったことを明確に示しています。これにより、ベンチマークコードの可読性が向上し、セットアップ時間の除外がより直感的に行えるようになります。
## 関連リンク
* Go言語の`testing`パッケージのドキュメント: [https://pkg.go.dev/testing](https://pkg.go.dev/testing)
* Go言語のベンチマークに関する公式ブログ記事(関連する可能性のあるもの): Goのバージョンアップに伴い、ベンチマークの機能や推奨事項が更新されることがあります。例えば、Goの公式ブログで「Writing benchmarks in Go」のような記事を探すと、より詳細な情報が得られる可能性があります。
## 参考にした情報源リンク
* Go言語の公式ドキュメント
* Go言語の`testing`パッケージのソースコード
* Go言語のコミット履歴と関連するコードレビュー(Gerrit CL: `https://golang.org/cl/6591051`)
* Go言語のベンチマークに関する一般的な情報源(ブログ、チュートリアルなど)
* Web検索結果: "Go testing.ResetTimer vs StopTimer/StartTimer"