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

[インデックス 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つの操作を同時に行っています。

  1. go f(): 新しいゴルーチン f を起動しています。
  2. 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言語の公式ドキュメント(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つの操作を同時に行っています。

  1. go f(): 新しいゴルーチン f を起動しています。
  2. 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言語の公式ドキュメント(init関数、ゴルーチン、スケジューラに関する一般的な情報)
  • Go言語の初期のリリースノートや設計に関する議論(特にスケジューラの進化に関する情報)
  • Go言語のソースコードリポジトリ(過去のコミット履歴や関連する変更の調査)
  • Go言語のコミュニティフォーラムやメーリングリスト(初期のバグ報告や議論)
  • time.Now() の実装に関するGo言語のソースコード
  • Goスケジューラの進化に関する記事 (例: The Go scheduler: M, P, and G - dev.to, Go's work-stealing scheduler - github.io)