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

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

このコミットは、Go言語のベンチマークスイートにおいて、fastaベンチマークのデータサイズをARMアーキテクチャ向けに削減し、特に32ビットARMシステムでのメモリ消費量を最適化することを目的としています。これにより、リソースが限られたARMデバイス上でもGoのベンチマークを安定して実行できるようになります。また、ベンチマーク名のサフィックス(25m)が削除され、より汎用的な名前に変更されています。

コミット

commit 166dab6993029802526804393a31cb8d080743e6
Author: Dave Cheney <dave@cheney.net>
Date:   Wed Jun 6 07:49:58 2012 +1000

    test/bench/go1: reduce fasta data size for linux/arm
    
    As discussed on golang-dev, reduce the size of the fasta
    dataset to make it possible to run the go1 benchmarks on
    small ARM systems.
    
    Also, remove the 25m suffix from fasta data and Revcomp.
    
    linux/arm: pandaboard OMAP4
    
    BenchmarkBinaryTree17          1        70892426000 ns/op
    BenchmarkFannkuch11            1        35712066000 ns/op
    BenchmarkGobDecode            10         137146000 ns/op           5.60 MB/s
    BenchmarkGobEncode            50          64953000 ns/op          11.82 MB/s
    BenchmarkGzip          1        5675690000 ns/op           3.42 MB/s
    BenchmarkGunzip        1        1207001000 ns/op          16.08 MB/s
    BenchmarkJSONEncode            5         860424800 ns/op           2.26 MB/s
    BenchmarkJSONDecode            1        3321839000 ns/op           0.58 MB/s
    BenchmarkMandelbrot200        50          45893560 ns/op
    BenchmarkRevcomp              10         135220300 ns/op          18.80 MB/s
    BenchmarkTemplate              1        6385681000 ns/op           0.30 MB/s
    
    R=rsc, minux.ma, dsymonds
    CC=golang-dev
    https://golang.org/cl/6278048
---
 test/bench/go1/fasta_test.go   | 17 ++++++++++++++++-\n test/bench/go1/revcomp_test.go |  6 +++---\n 2 files changed, 19 insertions(+), 4 deletions(-)\n\ndiff --git a/test/bench/go1/fasta_test.go b/test/bench/go1/fasta_test.go\nindex dcb2d1055d..bff056fa90 100644\n--- a/test/bench/go1/fasta_test.go\n+++ b/test/bench/go1/fasta_test.go\n@@ -4,9 +4,24 @@\n \n package go1\n \n+import \"runtime\"\n+\n // Not a benchmark; input for revcomp.\n \n-var fasta25m = fasta(25e6)\n+var fastabytes = makefasta()\n+\n+func makefasta() []byte {\n+\tvar n int = 25e6\n+\tif runtime.GOARCH == \"arm\" {\n+\t\t// TODO(dfc) remove this limitation after precise gc.\n+\t\t// A value of 25e6 consumes 465mb of heap on 32bit \n+\t\t// platforms, which is too much for most ARM systems. \n+\t\t// A value of 25e5 produces a memory layout that \n+\t\t// confuses the gc on 32bit platforms. So 25e4 it is.\n+\t\tn = 25e4\n+\t}\n+\treturn fasta(n)\n+}\n \n func fasta(n int) []byte {\n \tout := make(fastaBuffer, 0, 11*n)\ndiff --git a/test/bench/go1/revcomp_test.go b/test/bench/go1/revcomp_test.go\nindex 9256164d76..6b6c1e5772 100644\n--- a/test/bench/go1/revcomp_test.go\n+++ b/test/bench/go1/revcomp_test.go\n@@ -77,9 +77,9 @@ func revcomp(data []byte) {\n \t}\n }\n \n-func BenchmarkRevcomp25M(b *testing.B) {\n-\tb.SetBytes(int64(len(fasta25m)))\n+func BenchmarkRevcomp(b *testing.B) {\n+\tb.SetBytes(int64(len(fastabytes)))\n \tfor i := 0; i < b.N; i++ {\n-\t\trevcomp(fasta25m)\n+\t\trevcomp(fastabytes)\n \t}\n }\n```

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

https://github.com/golang/go/commit/166dab6993029802526804393a31cb8d080743e6

## 元コミット内容

test/bench/go1: reduce fasta data size for linux/arm

As discussed on golang-dev, reduce the size of the fasta dataset to make it possible to run the go1 benchmarks on small ARM systems.

Also, remove the 25m suffix from fasta data and Revcomp.

linux/arm: pandaboard OMAP4

BenchmarkBinaryTree17 1 70892426000 ns/op BenchmarkFannkuch11 1 35712066000 ns/op BenchmarkGobDecode 10 137146000 ns/op 5.60 MB/s BenchmarkGobEncode 50 64953000 ns/op 11.82 MB/s BenchmarkGzip 1 5675690000 ns/op 3.42 MB/s BenchmarkGunzip 1 1207001000 ns/op 16.08 MB/s BenchmarkJSONEncode 5 860424800 ns/op 2.26 MB/s BenchmarkJSONDecode 1 3321839000 ns/op 0.58 MB/s BenchmarkMandelbrot200 50 45893560 ns/op BenchmarkRevcomp 10 135220300 ns/op 18.80 MB/s BenchmarkTemplate 1 6385681000 ns/op 0.30 MB/s

R=rsc, minux.ma, dsymonds CC=golang-dev https://golang.org/cl/6278048


## 変更の背景

この変更の主な背景は、Go言語のベンチマークスイートが、リソースが限られたARMベースのシステム(特に32ビットARM)で実行する際に、メモリ不足の問題に直面していたことです。コミットメッセージに記載されているように、`golang-dev`メーリングリストでの議論を経て、`fasta`ベンチマークで使用されるデータセットのサイズを削減する必要性が認識されました。

具体的には、元の`fasta`データセット(2500万バイト)は、32ビットプラットフォーム上で約465MBのヒープメモリを消費していました。これは、多くのARMシステムにとって過大な量であり、ベンチマークの実行を妨げる原因となっていました。また、250万バイトに削減しても、32ビットプラットフォームのGC(ガベージコレクション)を混乱させるメモリレイアウトになるという問題も指摘されています。

この問題に対処するため、ARMアーキテクチャの場合にのみデータセットサイズを大幅に削減し、ベンチマークがこれらのシステムで実行可能になるように調整されました。これにより、Go言語のパフォーマンス測定がより広範なハードウェア環境で可能になり、ARMプラットフォームでのGoの採用と最適化を促進する狙いがあります。

また、ベンチマーク名から具体的なデータサイズを示すサフィックス(`25m`)を削除することで、ベンチマークの汎用性を高め、将来的なデータサイズ変更にも対応しやすくなっています。

## 前提知識の解説

このコミットを理解するためには、以下の前提知識が必要です。

*   **Go言語のベンチマーク**: Go言語には、`testing`パッケージに組み込みのベンチマーク機能があります。`go test -bench=.`コマンドで実行でき、関数のパフォーマンスを測定するために使用されます。ベンチマーク関数は`BenchmarkXxx(*testing.B)`というシグネチャを持ち、`b.N`回ループを実行して処理時間を測定します。`b.SetBytes(n)`は、ベンチマークが処理するバイト数を設定し、スループット(MB/sなど)を計算するために使用されます。
*   **`fasta`ベンチマーク**: `fasta`は、バイオインフォマティクス分野で広く使われるFASTA形式のシーケンスデータを生成するベンチマークです。このベンチマークは、文字列操作やメモリ割り当て、I/O処理のパフォーマンスを測定するのに適しています。
*   **`revcomp`ベンチマーク**: `revcomp`(Reverse Complement)は、DNAシーケンスの逆相補鎖を生成するバイオインフォマティクス処理を模倣したベンチマークです。これも文字列操作やメモリ効率が重要となる処理です。
*   **ARMアーキテクチャ**: ARM(Advanced RISC Machine)は、モバイルデバイス、組み込みシステム、IoTデバイスなどで広く使用されているCPUアーキテクチャです。x86アーキテクチャと比較して、一般的に消費電力が低く、リソースが限られた環境での利用が多いのが特徴です。特に、古いARMシステムや組み込みシステムでは、利用可能なRAMが少ない場合があります。
*   **`runtime.GOARCH`**: Go言語の`runtime`パッケージは、実行環境に関する情報を提供します。`runtime.GOARCH`は、プログラムが実行されているターゲットアーキテクチャ(例: "amd64", "arm", "arm64"など)を示す文字列定数です。この定数を利用することで、特定のアーキテクチャに特化したコードパスを記述できます。
*   **ガベージコレクション (GC)**: Go言語は自動メモリ管理(ガベージコレクション)を採用しています。GCは、不要になったメモリを自動的に解放し、プログラマが手動でメモリを管理する手間を省きます。しかし、GCの動作はヒープサイズやメモリ割り当てパターンに影響され、特に32ビットシステムではアドレス空間の制約やGCの効率がパフォーマンスに影響を与えることがあります。コミットメッセージにある「precise gc」は、より正確なガベージコレクションを指しており、当時のGoのGCがまだ発展途上であったことを示唆しています。

## 技術的詳細

このコミットの技術的詳細な変更点は以下の通りです。

1.  **`fasta`データ生成の条件付きサイズ調整**:
    *   `fasta_test.go`に`makefasta()`という新しい関数が導入されました。
    *   この関数内で`runtime.GOARCH`が`"arm"`であるかどうかがチェックされます。
    *   もしARMアーキテクチャであれば、`fasta`データセットのサイズ`n`は`25e6`(2500万)から`25e4`(25万)に大幅に削減されます。
    *   この削減は、32ビットARMプラットフォームでのメモリ消費(2500万バイトで465MBのヒープ消費)が過大であること、および250万バイトでもGCを混乱させる可能性があるという問題への対処です。
    *   コメントには「TODO(dfc) remove this limitation after precise gc.」とあり、将来的にGCが改善されればこの制限を解除できる可能性があることが示唆されています。
2.  **ベンチマーク名の変更**:
    *   `fasta_test.go`では、`fasta25m`という変数名が`fastabytes`に変更されました。これにより、データサイズが固定ではないことを示唆しています。
    *   `revcomp_test.go`では、`BenchmarkRevcomp25M`というベンチマーク関数名が`BenchmarkRevcomp`に変更されました。これも同様に、特定のデータサイズに依存しない汎用的なベンチマーク名にするための変更です。
3.  **`revcomp`ベンチマークでの新しいデータセットの使用**:
    *   `revcomp_test.go`内の`BenchmarkRevcomp`関数は、以前は`fasta25m`を直接使用していましたが、変更後は`makefasta()`によって生成される`fastabytes`を使用するように修正されました。これにより、`revcomp`ベンチマークもARMシステムでのデータサイズ削減の恩恵を受けます。

これらの変更により、Goのベンチマークスイートは、異なるアーキテクチャ(特にリソースが限られたARM)に対してより適応性が高まり、より信頼性の高いパフォーマンス測定が可能になりました。

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

### `test/bench/go1/fasta_test.go`

```diff
--- a/test/bench/go1/fasta_test.go
+++ b/test/bench/go1/fasta_test.go
@@ -4,9 +4,24 @@
 
 package go1
 
+import "runtime"
+
 // Not a benchmark; input for revcomp.
 
-var fasta25m = fasta(25e6)
+var fastabytes = makefasta()
+
+func makefasta() []byte {
+	var n int = 25e6
+	if runtime.GOARCH == "arm" {
+		// TODO(dfc) remove this limitation after precise gc.
+		// A value of 25e6 consumes 465mb of heap on 32bit 
+		// platforms, which is too much for most ARM systems. 
+		// A value of 25e5 produces a memory layout that 
+		// confuses the gc on 32bit platforms. So 25e4 it is.
+		n = 25e4
+	}
+	return fasta(n)
+}
 
 func fasta(n int) []byte {
 	out := make(fastaBuffer, 0, 11*n)

test/bench/go1/revcomp_test.go

--- a/test/bench/go1/revcomp_test.go
+++ b/test/bench/go1/revcomp_test.go
@@ -77,9 +77,9 @@ func revcomp(data []byte) {
 	}
 }
 
-func BenchmarkRevcomp25M(b *testing.B) {
-	b.SetBytes(int64(len(fasta25m)))
+func BenchmarkRevcomp(b *testing.B) {
+	b.SetBytes(int64(len(fastabytes)))
 	for i := 0; i < b.N; i++ {
-		revcomp(fasta25m)
+		revcomp(fastabytes)
 	}
 }

コアとなるコードの解説

fasta_test.goの変更点

  1. import "runtime"の追加:
    • runtime.GOARCHを使用して現在の実行アーキテクチャを判別するために、runtimeパッケージがインポートされました。
  2. fasta25mからfastabytesへの変更とmakefasta()の導入:
    • 以前はvar fasta25m = fasta(25e6)として、2500万バイトのfastaデータが直接初期化されていました。
    • この変更により、var fastabytes = makefasta()という形で、makefasta()関数がデータを生成するようになりました。
    • makefasta()関数は、データサイズnの初期値を25e6(2500万)としますが、if runtime.GOARCH == "arm"という条件分岐を追加しています。
    • もし実行環境がARMアーキテクチャであれば、nの値は25e4(25万)に上書きされます。これにより、ARMシステムではより小さなデータセットが使用されることになります。
    • この条件付きのデータサイズ調整は、ARMシステムでのメモリ制約を考慮したものです。コメントには、32ビットプラットフォームでのヒープ消費量(465MB)が多すぎること、および250万バイトでもGCを混乱させる可能性があることが明記されており、25e4が選択された理由が説明されています。
    • 最終的にmakefasta()は、調整されたnの値を使ってfasta(n)を呼び出し、生成されたバイトスライスを返します。

revcomp_test.goの変更点

  1. ベンチマーク関数名の変更:
    • func BenchmarkRevcomp25M(b *testing.B)func BenchmarkRevcomp(b *testing.B)に変更されました。これは、ベンチマークが特定のデータサイズ(25M)に固定されないことを示すための命名規則の変更です。
  2. 使用するデータセットの変更:
    • ベンチマーク内でb.SetBytes(int64(len(fasta25m)))revcomp(fasta25m)が、それぞれb.SetBytes(int64(len(fastabytes)))revcomp(fastabytes)に変更されました。
    • これにより、revcompベンチマークは、fasta_test.goで定義されたfastabytes変数(ARMアーキテクチャではサイズが調整されたデータセット)を使用するようになります。

これらの変更により、Goのベンチマークは、異なるアーキテクチャの特性に合わせて動的に調整されるようになり、特にリソースが限られたARMシステムでのテストの信頼性と実行可能性が向上しました。

関連リンク

参考にした情報源リンク

  • golang-devメーリングリストでの議論 (コミットメッセージに記載)
  • Go言語のtestingパッケージに関する公式ドキュメント
  • Go言語のruntimeパッケージに関する公式ドキュメント
  • ARMアーキテクチャに関する一般的な情報源 (例: Wikipedia, ARM Holdingsの公式ドキュメント)
  • ガベージコレクションに関する一般的な情報源 (例: Wikipedia, コンピュータサイエンスの教科書)
  • FASTA形式に関する一般的な情報源 (例: Wikipedia)