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

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

このコミットは、Go言語のランタイムパッケージ内のガベージコレクション(GC)テスト、具体的には TestGcSys の挙動を調整するものです。テストが特定のアーキテクチャ(64-bit)で時折失敗する問題を修正し、32-bitアーキテクチャでのテストも再有効化することを目的としています。主な変更点は、テストにおけるシステムメモリ使用量の許容範囲を緩和し、以前はスキップされていた非amd64システムでのテスト実行を再開することです。

コミット

commit 85266dfd4dd9932672258e0a9f68e3fc96a44ec8
Author: Russ Cox <rsc@golang.org>
Date:   Tue May 22 00:07:13 2012 -0400

    runtime: relax TestGcSys
    
    This fixes occasional 64-bit failures.
    Maybe it will fix the 32-bit failures too,
    so re-enable on 32-bit for now.
    
    R=golang-dev, bradfitz, r, dvyukov
    CC=golang-dev
    https://golang.org/cl/6218050

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

https://github.com/golang/go/commit/85266dfd4dd9932672258e0a9f68e3fc96a44ec8

元コミット内容

このコミットの元のメッセージは以下の通りです。

「runtime: TestGcSys を緩和する

これは、時折発生する 64-bit での失敗を修正します。 32-bit での失敗も修正するかもしれないので、 今のところ 32-bit でも再有効化します。」

変更の背景

TestGcSys は、Goランタイムのガベージコレクタがシステムメモリを効率的に管理しているかを検証するためのテストです。コミットメッセージによると、このテストは以前から64-bitシステムで「時折失敗」していました。これは、テストが設定しているメモリ使用量の閾値が厳しすぎるか、または特定の環境やタイミングによってガベージコレクタの挙動がわずかに異なり、テストが意図せず失敗していた可能性を示唆しています。

また、このテストは以前、runtime.GOARCH != "amd64" という条件で非amd64システム(例えば32-bitシステム)ではスキップされていました。これは、当時のGoのガベージコレクタがまだ「precise gc」(正確なGC)を実装しておらず、特定のアーキテクチャでの挙動が不安定であったためと考えられます。コミットの目的は、この不安定性を解消し、テストの信頼性を向上させるとともに、より広範なアーキテクチャでテストを実行できるようにすることにあります。特に、32-bitシステムでのテストも再有効化することで、より多くの環境での品質保証を目指しています。

前提知識の解説

Goのガベージコレクション (GC)

Go言語は、メモリ管理にガベージコレクションを採用しています。開発者が手動でメモリを解放する必要がなく、ランタイムが不要になったメモリを自動的に回収します。GoのGCは並行(concurrent)かつ低遅延(low-latency)を目指しており、プログラムの実行を長時間停止させることなく動作します。

runtime パッケージ

runtime パッケージは、Goランタイムとのインタラクションを提供します。これには、ガベージコレクションの制御、メモリ統計の取得、ゴルーチンの管理など、低レベルの機能が含まれます。

runtime.GC()

runtime.GC() 関数は、ガベージコレクタを明示的に実行するよう要求します。通常、GCはランタイムによって自動的にトリガーされますが、テストや特定のパフォーマンス測定のために手動で呼び出すことがあります。

runtime.MemStats

runtime.MemStats 構造体は、Goランタイムのメモリ割り当てに関する統計情報を提供します。これには、ヒープの使用量、システムから取得したメモリの総量、GCの実行回数などが含まれます。

runtime.ReadMemStats(memstats *MemStats)

この関数は、現在のメモリ統計を memstats 引数に格納します。これにより、プログラムはランタイムのメモリ使用状況を詳細に把握できます。

memstats.Sys

runtime.MemStats 構造体内の Sys フィールドは、Goランタイムがシステムから取得したメモリの総量(バイト単位)を示します。これは、GoプログラムがOSからどれだけのメモリを確保しているかを示す指標となります。

TestGcSys

TestGcSys は、Goのランタイムパッケージ内のテスト関数の一つで、ガベージコレクタがシステムメモリを適切に解放しているか、または過剰に保持していないかを検証します。このテストは、大量のメモリを割り当てた後、GCを実行し、その後システムメモリの使用量が特定の閾値以下に収まっていることを確認します。

runtime.GOARCH

runtime.GOARCH は、Goプログラムが実行されているターゲットアーキテクチャ(例: "amd64", "386", "arm" など)を示す文字列定数です。これを使って、特定のアーキテクチャに依存するコードの条件分岐を行うことができます。

ビットシフト演算子 <<

Goを含む多くのプログラミング言語では、<< は左ビットシフト演算子です。A << B は、A のビットを B ビットだけ左にシフトすることを意味します。これは A * (2^B) と等価です。 例えば、4 << 204 * (2^20) を意味し、2^20 は1メガバイト(MB)なので、4MB を表します。同様に、16 << 2016MB を表します。

技術的詳細

このコミットの技術的な変更点は、src/pkg/runtime/gc_test.go ファイル内の TestGcSys 関数に集中しています。

  1. アーキテクチャによるスキップの削除: 変更前は、TestGcSys 関数は runtime.GOARCH != "amd64" という条件で、amd64以外のシステムではテストをスキップしていました。これは、当時のGoのガベージコレクタが非amd64システムで不安定であったり、正確なGCが実装されていなかったりしたためと考えられます。このコミットでは、この条件分岐が削除され、TestGcSys がすべてのアーキテクチャで実行されるようになりました。これは、ガベージコレクタの安定性が向上したか、または32-bitシステムでのテストの必要性が高まったことを示唆しています。

    -	if runtime.GOARCH != "amd64" {
    -		// TODO(adg): remove this when precise gc is implemented
    -		t.Logf("skipping on non-amd64 systems")
    -		return
    -	}
    
  2. システムメモリ使用量閾値の緩和: TestGcSys は、大量のメモリを割り当てた後にGCを実行し、システムが保持しているメモリ量(memstats.Sys)が特定の閾値を超えていないかをチェックします。 変更前は、この閾値は 4 << 20 バイト(4MB)でした。 変更後は、この閾値が 16 << 20 バイト(16MB)に引き上げられました。

    -	if sys > 4<<20 {
    +	if sys > 16<<20 {
    

    この変更は、テストが時折失敗していた原因が、ガベージコレクタがシステムメモリを解放する速度やタイミング、あるいはテスト環境のわずかな変動によって、4MBという厳しすぎる閾値を超えてしまうことにあったためと考えられます。閾値を16MBに緩和することで、テストの安定性を向上させ、偶発的な失敗を防ぎます。これは、ガベージコレクタが完全にメモリを解放するまでにわずかな遅延があることや、OSレベルでのメモリ管理のオーバーヘッドを考慮した調整である可能性があります。

  3. メモリ割り当てに関するコメントの追加: 閾値のチェックの直前に、以下のコメントが追加されました。

    	// We allocated 100 MB or (if not short) 1 GB.
    

    このコメントは、テスト内で実際に割り当てられるメモリの量が100MBまたは1GBであることを示しており、テストが検証しようとしているメモリ使用量のスケールを明確にしています。この情報があることで、閾値が4MBから16MBに引き上げられた理由が、割り当てられた大量のメモリに対して、GC後のシステムメモリ使用量が妥当な範囲に収まっているかをより現実的に評価するためであることが理解できます。

これらの変更は、Goのガベージコレクタのテストが、より堅牢で、様々な環境やアーキテクチャで信頼性高く動作するように調整されたことを示しています。

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

diff --git a/src/pkg/runtime/gc_test.go b/src/pkg/runtime/gc_test.go
index fdbe13ebbe..783409b689 100644
--- a/src/pkg/runtime/gc_test.go
+++ b/src/pkg/runtime/gc_test.go
@@ -10,11 +10,6 @@ import (
 )
 
 func TestGcSys(t *testing.T) {
-	if runtime.GOARCH != "amd64" {
-		// TODO(adg): remove this when precise gc is implemented
-		t.Logf("skipping on non-amd64 systems")
-		return
-	}
 	memstats := new(runtime.MemStats)
 	runtime.GC()
 	runtime.ReadMemStats(memstats)
@@ -31,6 +26,7 @@ func TestGcSys(t *testing.T) {
 	}
 
 	// Should only be using a few MB.
+	// We allocated 100 MB or (if not short) 1 GB.
 	runtime.ReadMemStats(memstats)
 	if sys > memstats.Sys {
 		sys = 0
@@ -38,7 +34,7 @@ func TestGcSys(t *testing.T) {
 		sys = memstats.Sys - sys
 	}
 	t.Logf("used %d extra bytes", sys)
-	if sys > 4<<20 {
+	if sys > 16<<20 {
 		t.Fatalf("using too much memory: %d bytes", sys)
 	}
 }

コアとなるコードの解説

src/pkg/runtime/gc_test.go 内の TestGcSys 関数は、Goランタイムのガベージコレクタがシステムメモリを効率的に管理しているかをテストします。

  1. アーキテクチャチェックの削除:

    -	if runtime.GOARCH != "amd64" {
    -		// TODO(adg): remove this when precise gc is implemented
    -		t.Logf("skipping on non-amd64 systems")
    -		return
    -	}
    

    この削除により、TestGcSysamd64 以外のアーキテクチャ(例えば 386arm など)でも実行されるようになりました。以前は、amd64 以外のシステムではテストがスキップされ、"skipping on non-amd64 systems" というログが出力されていました。この変更は、Goのガベージコレクタがより広範なアーキテクチャで安定して動作するようになったことを示唆しており、テストカバレッジを向上させます。

  2. メモリ割り当てに関するコメントの追加:

    +	// We allocated 100 MB or (if not short) 1 GB.
    

    この行は、テストのメモリ使用量チェックの直前に挿入されました。これは、テストの初期段階で大量のメモリ(100MBまたは1GB)が割り当てられていることを開発者に明確に伝えます。この情報は、後続のメモリ使用量チェックの文脈を理解する上で重要です。

  3. システムメモリ使用量閾値の緩和:

    -	if sys > 4<<20 {
    +	if sys > 16<<20 {
    

    この変更は、テストの核心部分です。sys 変数は、GC実行後にシステムが保持している余分なメモリ量を示します。変更前は、この sys4MB (4 << 20 バイト) を超えるとテストが失敗していました。変更後は、この閾値が 16MB (16 << 20 バイト) に引き上げられました。 この緩和は、テストが時折失敗していた問題を解決するためです。ガベージコレクタがメモリをOSに完全に解放するまでにわずかな遅延がある場合や、OSのメモリ管理の特性、あるいはテスト実行環境の負荷などによって、一時的に4MBを超えるメモリが保持されることがあったと考えられます。閾値を16MBに広げることで、これらの偶発的な失敗を許容し、テストの信頼性を高めつつ、依然としてガベージコレクタが過剰なメモリを保持していないことを確認します。

これらの変更により、TestGcSys はより堅牢になり、Goのガベージコレクタのクロスアーキテクチャな安定性をより適切に検証できるようになりました。

関連リンク

参考にした情報源リンク

  • 特になし(提供されたコミット情報と一般的なGoの知識に基づいて解説を生成しました)。