[インデックス 12062] ファイルの概要
このコミットは、test/initsyscall.go
というテストファイルを削除するものです。このファイルは、Go言語の古い特性をテストしており、もはや関連性がなくなったため削除されました。
コミット
- コミットハッシュ:
f03a5796e399d613172aa9a7bb33760bdb5f0d09
- 作者: Rob Pike r@golang.org
- 日付: Mon Feb 20 07:44:41 2012 +1100
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/f03a5796e399d613172aa9a7bb33760bdb5f0d09
元コミット内容
test/initsyscall.go: delete
It's testing an old property of the language and is no longer relevant.
R=golang-dev, rsc
CC=golang-dev
https://golang.org/cl/5676104
変更の背景
このコミットの背景には、Go言語の進化、特にスケジューラとinit
関数の挙動に関する変更があります。削除された test/initsyscall.go
ファイルのコメントには、かつてこのテストが「スケジューラが time.Nanoseconds
がシステムコールに入ったときに、f
のために新しいスケジューリングスレッドを起動しようとしたためにクラッシュした」と書かれています。そして、「main
が開始されるまで新しいゴルーチンをスケジュールすることは許されない」という記述があります。
これは、Go言語の初期バージョンにおいて、init
関数内でゴルーチンを起動したり、システムコールを呼び出したりする際の挙動が不安定であったことを示唆しています。特に、main
関数が開始される前にスケジューラが完全に初期化されていない状態で、システムコールを伴う処理や新しいゴルーチンの起動が行われると、クラッシュやデッドロックなどの問題が発生する可能性がありました。
Go言語の開発が進むにつれて、これらの初期の制約やバグは修正され、スケジューラの堅牢性が向上しました。その結果、init
関数内でのゴルーチン起動やシステムコール呼び出しがより安全に行えるようになり、この特定のテストケースがカバーしていた「古い言語の特性」はもはや存在しなくなったため、テストファイル自体が不要になったという背景があります。
前提知識の解説
このコミットを理解するためには、以下のGo言語の概念と初期の挙動に関する知識が必要です。
1. Go言語の init
関数
Go言語では、各パッケージにinit
関数を定義できます。init
関数は、パッケージがインポートされた際に、main
関数が実行されるよりも前に自動的に実行されます。複数のinit
関数がある場合、それらは定義された順序で実行されます。init
関数は、プログラムの初期化処理(例: グローバル変数の設定、データベース接続の確立、設定ファイルの読み込みなど)に使用されます。
2. ゴルーチン (Goroutines)
ゴルーチンはGo言語における軽量な並行処理の単位です。go
キーワードを使って関数を呼び出すことで、新しいゴルーチンが生成され、その関数は他の処理と並行して実行されます。ゴルーチンはOSのスレッドよりもはるかに軽量であり、数百万のゴルーチンを同時に実行することも可能です。
3. Goスケジューラ
Goランタイムには、ゴルーチンをOSスレッドにマッピングし、実行を管理する独自のスケジューラが組み込まれています。このスケジューラは、ゴルーチンの生成、実行、ブロック、再開などを効率的に処理し、並行処理を透過的に実現します。初期のGoスケジューラは、特にinit
フェーズでの挙動において、現在ほど堅牢ではありませんでした。
4. システムコール (System Calls)
システムコールは、プログラムがオペレーティングシステム(OS)のサービス(例: ファイルI/O、ネットワーク通信、メモリ管理、時間取得など)を要求するためのメカニズムです。Goプログラムがtime.Now()
のような関数を呼び出すと、内部的にはOSの時刻取得サービスを利用するためのシステムコールが発行されます。システムコールは、ユーザーモードからカーネルモードへのコンテキストスイッチを伴うため、通常の関数呼び出しよりもオーバーヘッドが大きくなります。
5. 初期Go言語のスケジューラの制約(特に init
フェーズ)
Go言語の初期バージョンでは、init
関数が実行される段階では、Goランタイムのスケジューラが完全に初期化されていない、あるいは安定していない状態でした。この時期に、init
関数内で以下のような操作を行うと、予期せぬ挙動やクラッシュを引き起こす可能性がありました。
- 新しいゴルーチンの起動:
init
関数内でgo
キーワードを使って新しいゴルーチンを起動すると、スケジューラがまだ準備できていないために、そのゴルーチンの実行が適切に管理されず、問題が発生することがありました。 - システムコールの呼び出し:
time.Nanoseconds()
(現在のtime.Now()
に相当)のようなシステムコールを伴う処理は、OSとのやり取りを必要とします。スケジューラが不安定な状態でシステムコールが発行されると、スケジューラが新しいスレッドを起動しようとして失敗したり、デッドロックに陥ったりする可能性がありました。
test/initsyscall.go
は、まさにこの「init
関数内でシステムコールを呼び出し、かつゴルーチンを起動する」というシナリオが、初期のGo言語でクラッシュを引き起こしていたことをテストするためのものでした。
技術的詳細
削除された test/initsyscall.go
ファイルは、Go言語の初期のスケジューラが抱えていた特定のバグ、または設計上の制約を浮き彫りにするものでした。
このテストファイルは、init
関数内で以下の2つの操作を同時に行っています。
go f()
: 新しいゴルーチンf
を起動しています。time.Now()
: 時刻を取得するシステムコールを呼び出しています。
コミットメッセージとファイル内のコメントが示唆するように、Go言語の初期のスケジューラは、main
関数が開始される前にこれらの操作が同時に行われると、適切に処理できないことがありました。具体的には、time.Now()
がシステムコールに入った際に、スケジューラがf
のために新しいスケジューリングスレッドを起動しようと試み、その過程でクラッシュが発生していたようです。これは、スケジューラがまだ完全に初期化されておらず、新しいゴルーチンやシステムコールからの復帰を適切に扱えなかったためと考えられます。
Go言語の開発チームは、スケジューラの設計と実装を継続的に改善してきました。特に、Go 1.0のリリースに向けて、ランタイムとスケジューラの安定性と堅牢性は大幅に向上しました。これにより、init
関数内でのゴルーチン起動やシステムコール呼び出しが安全に行えるようになり、かつて問題を引き起こしたようなエッジケースが解消されました。
このコミットは、Go言語のランタイムとスケジューラの成熟を示すものです。かつてはクラッシュを引き起こす可能性があった特定のコードパターンが、言語の進化とスケジューラの改善によって安全になったため、その問題をテストするための専用のテストケースが不要になったことを意味します。これは、Go言語が初期の不安定な状態から、より予測可能で堅牢な実行環境へと進化した証拠と言えます。
コアとなるコードの変更箇所
このコミットによる変更は、単一のファイルの削除です。
--- a/test/initsyscall.go
+++ /dev/null
@@ -1,26 +0,0 @@
-// run
-
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// This used to crash because the scheduler
-// tried to kick off a new scheduling thread for f
-// when time.Nanoseconds went into the system call.
-// It's not okay to schedule new goroutines
-// until main has started.
-
-package main
-
-import "time"
-
-func f() {
-}
-
-func init() {
- go f()
- time.Now()
-}
-
-func main() {
-}
コアとなるコードの解説
削除された test/initsyscall.go
ファイルは、以下のGoコードを含んでいました。
// run
// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// This used to crash because the scheduler
// tried to kick off a new scheduling thread for f
// when time.Nanoseconds went into the system call.
// It's not okay to schedule new goroutines
// until main has started.
package main
import "time"
func f() {
}
func init() {
go f()
time.Now()
}
func main() {
}
このコードの主要な部分は init
関数です。
go f()
:init
関数内でf
という空の関数を新しいゴルーチンとして起動しています。time.Now()
:init
関数内で現在の時刻を取得しています。これは内部的にシステムコールを伴います。
ファイル内のコメントが明確に示しているように、この組み合わせ(init
関数内でのゴルーチン起動とシステムコール呼び出し)が、Go言語の初期バージョンではスケジューラの問題によりクラッシュを引き起こしていました。具体的には、time.Now()
がシステムコールを実行している最中に、スケジューラがf
ゴルーチンのために新しいスレッドを起動しようとして失敗していた、という状況です。
このテストファイルが削除されたということは、Goランタイムとスケジューラの改善により、このようなシナリオがもはやクラッシュを引き起こさなくなったことを意味します。つまり、init
関数内でのゴルーチン起動やシステムコール呼び出しが、main
関数が開始される前であっても安全かつ安定して実行されるようになった、というGo言語の進化を示しています。
関連リンク
- Go CL (Change List) へのリンク: https://golang.org/cl/5676104
参考にした情報源リンク
- Go言語の公式ドキュメント(
init
関数、ゴルーチン、スケジューラに関する一般的な情報) - Go言語の初期のリリースノートや設計に関する議論(特にスケジューラの進化に関する情報)
- Go言語のソースコードリポジトリ(過去のコミット履歴や関連する変更の調査)
- Go言語のコミュニティフォーラムやメーリングリスト(初期のバグ報告や議論)
time.Now()
の実装に関するGo言語のソースコード
[インデックス 12062] ファイルの概要
このコミットは、test/initsyscall.go
というテストファイルを削除するものです。このファイルは、Go言語の古い特性をテストしており、もはや関連性がなくなったため削除されました。
コミット
- コミットハッシュ:
f03a5796e399d613172aa9a7bb33760bdb5f0d09
- 作者: Rob Pike r@golang.org
- 日付: Mon Feb 20 07:44:41 2012 +1100
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/f03a5796e399d613172aa9a7bb33760bdb5f0d09
元コミット内容
test/initsyscall.go: delete
It's testing an old property of the language and is no longer relevant.
R=golang-dev, rsc
CC=golang-dev
https://golang.org/cl/5676104
変更の背景
このコミットの背景には、Go言語の進化、特にスケジューラとinit
関数の挙動に関する変更があります。削除された test/initsyscall.go
ファイルのコメントには、かつてこのテストが「スケジューラが time.Nanoseconds
がシステムコールに入ったときに、f
のために新しいスケジューリングスレッドを起動しようとしたためにクラッシュした」と書かれています。そして、「main
が開始されるまで新しいゴルーチンをスケジュールすることは許されない」という記述があります。
これは、Go言語の初期バージョンにおいて、init
関数内でゴルーチンを起動したり、システムコールを呼び出したりする際の挙動が不安定であったことを示唆しています。特に、main
関数が開始される前にスケジューラが完全に初期化されていない状態で、システムコールを伴う処理や新しいゴルーチンの起動が行われると、クラッシュやデッドロックなどの問題が発生する可能性がありました。
Go言語の開発が進むにつれて、これらの初期の制約やバグは修正され、スケジューラの堅牢性が向上しました。その結果、init
関数内でのゴルーチン起動やシステムコール呼び出しがより安全に行えるようになり、この特定のテストケースがカバーしていた「古い言語の特性」はもはや存在しなくなったため、テストファイル自体が不要になったという背景があります。
前提知識の解説
このコミットを理解するためには、以下のGo言語の概念と初期の挙動に関する知識が必要です。
1. Go言語の init
関数
Go言語では、各パッケージにinit
関数を定義できます。init
関数は、パッケージがインポートされた際に、main
関数が実行されるよりも前に自動的に実行されます。複数のinit
関数がある場合、それらは定義された順序で実行されます。init
関数は、プログラムの初期化処理(例: グローバル変数の設定、データベース接続の確立、設定ファイルの読み込みなど)に使用されます。
2. ゴルーチン (Goroutines)
ゴルーチンはGo言語における軽量な並行処理の単位です。go
キーワードを使って関数を呼び出すことで、新しいゴルーチンが生成され、その関数は他の処理と並行して実行されます。ゴルーチンはOSのスレッドよりもはるかに軽量であり、数百万のゴルーチンを同時に実行することも可能です。
3. Goスケジューラ
Goランタイムには、ゴルーチンをOSスレッドにマッピングし、実行を管理する独自のスケジューラが組み込まれています。このスケジューラは、ゴルーチンの生成、実行、ブロック、再開などを効率的に処理し、並行処理を透過的に実現します。初期のGoスケジューラは、特にinit
フェーズでの挙動において、現在ほど堅牢ではありませんでした。
4. システムコール (System Calls)
システムコールは、プログラムがオペレーティングシステム(OS)のサービス(例: ファイルI/O、ネットワーク通信、メモリ管理、時間取得など)を要求するためのメカニズムです。Goプログラムがtime.Now()
のような関数を呼び出すと、内部的にはOSの時刻取得サービスを利用するためのシステムコールが発行されます。システムコールは、ユーザーモードからカーネルモードへのコンテキストスイッチを伴うため、通常の関数呼び出しよりもオーバーヘッドが大きくなります。
5. 初期Go言語のスケジューラの制約(特に init
フェーズ)
Go言語の初期バージョンでは、init
関数が実行される段階では、Goランタイムのスケジューラが完全に初期化されていない、あるいは安定していない状態でした。この時期に、init
関数内で以下のような操作を行うと、予期せぬ挙動やクラッシュを引き起こす可能性がありました。
- 新しいゴルーチンの起動:
init
関数内でgo
キーワードを使って新しいゴルーチンを起動すると、スケジューラがまだ準備できていないために、そのゴルーチンの実行が適切に管理されず、問題が発生することがありました。 - システムコールの呼び出し:
time.Nanoseconds()
(現在のtime.Now()
に相当)のようなシステムコールを伴う処理は、OSとのやり取りを必要とします。スケジューラが不安定な状態でシステムコールが発行されると、スケジューラが新しいスレッドを起動しようとして失敗したり、デッドロックに陥ったりする可能性がありました。
test/initsyscall.go
は、まさにこの「init
関数内でシステムコールを呼び出し、かつゴルーチンを起動する」というシナリオが、初期のGo言語でクラッシュを引き起こしていたことをテストするためのものでした。
技術的詳細
削除された test/initsyscall.go
ファイルは、Go言語の初期のスケジューラが抱えていた特定のバグ、または設計上の制約を浮き彫りにするものでした。
このテストファイルは、init
関数内で以下の2つの操作を同時に行っています。
go f()
: 新しいゴルーチンf
を起動しています。time.Now()
: 時刻を取得するシステムコールを呼び出しています。
コミットメッセージとファイル内のコメントが示唆するように、Go言語の初期のスケジューラは、main
関数が開始される前にこれらの操作が同時に行われると、適切に処理できないことがありました。具体的には、time.Now()
がシステムコールに入った際に、スケジューラがf
のために新しいスケジューリングスレッドを起動しようと試み、その過程でクラッシュが発生していたようです。これは、スケジューラがまだ完全に初期化されておらず、新しいゴルーチンやシステムコールからの復帰を適切に扱えなかったためと考えられます。
Go言語の開発チームは、スケジューラの設計と実装を継続的に改善してきました。特に、Go 1.1で導入されたGPM (Goroutine, Processor, Machine/OS Thread) モデルのような新しいスケジューラモデルにより、ランタイムとスケジューラの安定性と堅牢性は大幅に向上しました。このモデルでは、ゴルーチンがブロッキングシステムコールを実行した場合、そのゴルーチンを実行していたOSスレッド(M)は、そのゴルーチンから切り離され、プロセッサ(P)は他の実行可能なゴルーチンを実行するために解放されます。システムコールが完了すると、ゴルーチンは実行を再開するためにPを再取得しようとします。このメカニズムにより、init
関数内でシステムコールがブロックされたとしても、プログラム全体の初期化や実行が停止することはありません。
このコミットは、Go言語のランタイムとスケジューラの成熟を示すものです。かつてはクラッシュを引き起こす可能性があった特定のコードパターンが、言語の進化とスケジューラの改善によって安全になったため、その問題をテストするための専用のテストケースが不要になったことを意味します。これは、Go言語が初期の不安定な状態から、より予測可能で堅牢な実行環境へと進化した証拠と言えます。
コアとなるコードの変更箇所
このコミットによる変更は、単一のファイルの削除です。
--- a/test/initsyscall.go
+++ /dev/null
@@ -1,26 +0,0 @@
-// run
-
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// This used to crash because the scheduler
-// tried to kick off a new scheduling thread for f
-// when time.Nanoseconds went into the system call.
-// It's not okay to schedule new goroutines
-// until main has started.
-
-package main
-
-import "time"
-
-func f() {
-}
-
-func init() {
- go f()
- time.Now()
-}
-
-func main() {
-}
コアとなるコードの解説
削除された test/initsyscall.go
ファイルは、以下のGoコードを含んでいました。
// run
// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// This used to crash because the scheduler
// tried to kick off a new scheduling thread for f
// when time.Nanoseconds went into the system call.
// It's not okay to schedule new goroutines
// until main has started.
package main
import "time"
func f() {
}
func init() {
go f()
time.Now()
}
func main() {
}
このコードの主要な部分は init
関数です。
go f()
:init
関数内でf
という空の関数を新しいゴルーチンとして起動しています。time.Now()
:init
関数内で現在の時刻を取得しています。これは内部的にシステムコールを伴います。
ファイル内のコメントが明確に示しているように、この組み合わせ(init
関数内でのゴルーチン起動とシステムコール呼び出し)が、Go言語の初期バージョンではスケジューラの問題によりクラッシュを引き起こしていました。具体的には、time.Now()
がシステムコールを実行している最中に、スケジューラがf
ゴルーチンのために新しいスレッドを起動しようとして失敗していた、という状況です。
このテストファイルが削除されたということは、Goランタイムとスケジューラの改善により、このようなシナリオがもはやクラッシュを引き起こさなくなったことを意味します。つまり、init
関数内でのゴルーチン起動やシステムコール呼び出しが、main
関数が開始される前であっても安全かつ安定して実行されるようになった、というGo言語の進化を示しています。
関連リンク
- Go CL (Change List) へのリンク: https://golang.org/cl/5676104
参考にした情報源リンク
- Go言語の公式ドキュメント(
init
関数、ゴルーチン、スケジューラに関する一般的な情報) - Go言語の初期のリリースノートや設計に関する議論(特にスケジューラの進化に関する情報)
- Go言語のソースコードリポジトリ(過去のコミット履歴や関連する変更の調査)
- Go言語のコミュニティフォーラムやメーリングリスト(初期のバグ報告や議論)
time.Now()
の実装に関するGo言語のソースコード- Goスケジューラの進化に関する記事 (例: The Go scheduler: M, P, and G - dev.to, Go's work-stealing scheduler - github.io)