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

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

このコミットは、Go言語の次期リリース(Go 1.2と推測される)に向けたAPIの変更を記録する api/next.txt ファイルの更新です。具体的には、debug/goobj パッケージの型に String() メソッドが追加され、sync パッケージに Pool 型が導入され、さらにNetBSDおよびWindows向けの syscall パッケージに多数のシステムコール関連定数や関数が追加されています。

コミット

commit e598bf1c887e565d37bfccf7145fd01a2c655e31
Author: Brad Fitzpatrick <bradfitz@golang.org>
Date:   Thu Jan 9 14:31:10 2014 -0800

    api: update next.txt
    
    R=golang-codereviews, minux.ma
    CC=golang-codereviews
    https://golang.org/cl/50190043

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

https://github.com/golang/go/commit/e598bf1c887e565d37bfccf7145fd01a2c655e31

元コミット内容

このコミットは、api/next.txt ファイルを更新し、Go言語の次期バージョンで導入される予定の新しい公開API要素を追記しています。変更内容は以下の通りです。

  • debug/goobj パッケージの Sym, SymID, SymKind 型に String() メソッドが追加されました。
  • sync パッケージに Pool 型とそのメソッド (Get, Put) およびフィールド (New) が追加されました。
  • syscall パッケージに、NetBSD (386およびAMD64アーキテクチャ、CGOの有無を含む) 向けの CLONE_*, MADV_*, MAP_*, MCL_*, MS_*, PROT_* といった多数のシステムコール関連定数が追加されました。
  • syscall パッケージに、Windows (386およびAMD64アーキテクチャ) 向けの NewCallbackCDecl 関数が追加されました。

変更の背景

このコミットの背景には、Go言語の標準ライブラリの機能拡張と、異なるオペレーティングシステム(特にNetBSDとWindows)におけるシステムコールへの対応強化があります。

  1. api/next.txt の役割: api/next.txt は、Go言語のリリースプロセスにおいて非常に重要なファイルです。このファイルは、次のメジャーリリースで公開される予定のAPIの変更点(追加、削除、変更)を記録するために使用されます。Go言語の互換性ポリシーでは、既存の公開APIを破壊的に変更することは極力避けるため、新しいAPIの追加は慎重に行われ、このファイルを通じて追跡されます。このコミットは、開発中の新機能や改善がAPIとして安定し、公開される準備ができたことを示しています。

  2. debug/goobjString() メソッド: debug/goobj パッケージは、Goのオブジェクトファイル(.o ファイル)を解析するための機能を提供します。Sym(シンボル)、SymID(シンボルID)、SymKind(シンボルの種類)といった型に String() メソッドが追加されることで、これらのオブジェクトファイル内の要素を人間が読みやすい形式で表現できるようになります。これはデバッグやツール開発において非常に有用です。

  3. sync.Pool の導入: sync.Pool は、一時的なオブジェクトの再利用を目的としたGoの標準ライブラリの機能です。頻繁に生成・破棄されるオブジェクト(例: バイトスライス、バッファ)がある場合、その都度メモリを確保・解放するとガベージコレクション(GC)の負荷が増大し、パフォーマンスが低下する可能性があります。sync.Pool を使用することで、これらのオブジェクトをプールしておき、必要に応じて再利用することで、メモリ割り当てのオーバーヘッドを削減し、GCの頻度を減らすことができます。これは、特に高負荷なサーバーアプリケーションなどでパフォーマンスを向上させるための重要な最適化手段となります。

  4. syscall パッケージの拡張: syscall パッケージは、GoプログラムからOSのシステムコールを直接呼び出すためのインターフェースを提供します。

    • NetBSD: NetBSDは、UNIX系のオープンソースオペレーティングシステムであり、様々なアーキテクチャをサポートしています。CLONE_*(プロセス生成)、MADV_*(メモリ使用のヒント)、MAP_*(メモリマッピング)、MCL_*(メモリロック)、MS_*(メモリ同期)、PROT_*(メモリ保護)といった定数の追加は、GoプログラムがNetBSD上でより低レベルなシステムリソース管理やプロセス間通信、メモリ操作を直接行えるようにするためのものです。これにより、GoアプリケーションがNetBSDの特定の機能やパフォーマンス特性を最大限に活用できるようになります。
    • Windows: Windows向けの NewCallbackCDecl 関数の追加は、GoとC言語(またはC++)で書かれたライブラリとの相互運用性(CGO)を強化するためのものです。__cdecl はC言語の標準的な呼び出し規約であり、この関数を使用することで、Goの関数をC言語のライブラリが呼び出せる形式に変換できるようになります。これは、既存のWindows APIやサードパーティのC/C++ライブラリをGoから利用する際に不可欠な機能です。

これらの変更は、Go言語がより多様なプラットフォームで、より高性能かつ低レベルな操作を可能にするための継続的な進化の一環として行われました。

前提知識の解説

このコミットの技術的詳細を理解するためには、以下の前提知識が役立ちます。

  1. Go言語のAPI互換性: Go言語は、後方互換性を非常に重視しています。一度公開されたAPIは、原則として変更または削除されません。新しい機能が追加される場合、それは既存のAPIを壊さない形で行われます。api/next.txt は、この互換性ポリシーを維持しつつ、将来のAPI変更を追跡するためのメカニズムです。

  2. Goのオブジェクトファイル (.o ファイル): Goコンパイラがソースコードをコンパイルすると、中間形式としてオブジェクトファイルが生成されます。これらのファイルには、コンパイルされたコード、データ、そしてシンボル情報(関数名、変数名など)が含まれています。debug/goobj パッケージは、これらのオブジェクトファイルをプログラム的に解析するためのツールを提供します。

  3. ガベージコレクション (GC): Go言語は、自動メモリ管理(ガベージコレクション)を採用しています。プログラマは明示的にメモリを解放する必要がありません。しかし、頻繁なメモリ割り当てと解放はGCのオーバーヘッドを増加させ、アプリケーションのレイテンシやスループットに影響を与える可能性があります。

  4. オブジェクトプール: オブジェクトプールは、リソース管理のパターンの一つです。コストの高いオブジェクト(メモリ割り当て、ネットワーク接続、データベース接続など)を事前に作成しておき、必要に応じてプールから取得し、使用後にプールに戻すことで、オブジェクトの生成・破棄にかかるオーバーヘッドを削減します。

  5. システムコール (System Call): システムコールは、ユーザー空間のプログラムがオペレーティングシステム(OS)のカーネル空間のサービスを要求するためのインターフェースです。ファイルI/O、プロセス管理、メモリ管理、ネットワーク通信など、OSが提供するほとんどの機能はシステムコールを通じて利用されます。Goの syscall パッケージは、これらの低レベルなOS機能へのアクセスを提供します。

  6. メモリ管理関連のシステムコール:

    • mmap(): ファイルや匿名メモリ領域をプロセスのアドレス空間にマッピングするためのシステムコール。メモリマップドファイルや共有メモリの実現に用いられます。
    • madvise(): プロセスがメモリ領域をどのように使用するかについて、カーネルにヒントを与えるためのシステムコール。これにより、カーネルはメモリ管理の最適化を行うことができます(例: MADV_DONTNEED は、そのメモリ領域がもう必要ないことを示唆し、カーネルが解放するのを助けます)。
    • mprotect(): メモリ領域の保護属性(読み取り、書き込み、実行)を変更するためのシステムコール。
    • mlockall(): プロセスのアドレス空間全体、または指定されたメモリ領域を物理メモリにロックし、スワップアウトされないようにするためのシステムコール。リアルタイムアプリケーションなどで使用されます。
    • msync(): メモリマップドファイルの内容をディスクと同期するためのシステムコール。
  7. プロセス管理関連のシステムコール:

    • clone() (Linux/NetBSD): 新しいプロセス(またはスレッド)を作成するためのシステムコール。親プロセスと様々なリソース(メモリ空間、ファイルディスクリプタ、シグナルハンドラなど)を共有するかどうかを細かく制御できます。CLONE_* フラグは、この共有の挙動を定義します。
  8. 呼び出し規約 (Calling Convention): 関数が呼び出される際に、引数がどのようにスタックに積まれ、レジスタがどのように使用され、戻り値がどのように返されるかなどを定義するルールセットです。異なるプログラミング言語やコンパイラは、異なる呼び出し規約を使用することがあります。

    • __cdecl: C言語の標準的な呼び出し規約の一つで、呼び出し側がスタックをクリーンアップします。Windows APIなどで広く使われています。

技術的詳細

debug/goobj パッケージの拡張

debug/goobj パッケージは、Goのコンパイラやリンカが生成するオブジェクトファイル(.o ファイル)の内部構造を解析するための低レベルなAPIを提供します。このコミットでは、以下の型に String() メソッドが追加されました。

  • Sym: オブジェクトファイル内のシンボル(関数、変数など)を表す型。
  • SymID: シンボルを一意に識別するためのID。
  • SymKind: シンボルの種類(例: テキストセクション、データセクションなど)を表す列挙型。

String() メソッドは、Goの fmt パッケージによって自動的に呼び出され、その型の値を人間が読みやすい文字列形式に変換します。これにより、debug/goobj を利用するツール(例: go tool objdump のようなデバッガやプロファイラ)が、シンボル情報をより分かりやすく表示できるようになります。これは、Goのバイナリを解析したり、デバッグ情報を抽出したりする際の利便性を向上させます。

sync.Pool の導入

sync.Pool は、Go 1.3で導入された、一時的なオブジェクトを効率的に再利用するためのメカニズムです。その主な目的は、頻繁に割り当てられ、すぐに不要になるオブジェクト(例: HTTPリクエストの処理中に使用されるバッファ、JSONエンコーダ/デコーダのインスタンスなど)のガベージコレクションの負荷を軽減することです。

sync.Pool の構造は非常にシンプルです。

type Pool struct {
    New func() interface{}
    // contains filtered or unexported fields
}
  • New func() interface{}: プールが空のときに新しいオブジェクトを生成するための関数です。この関数は、Get() メソッドがプール内に利用可能なオブジェクトを見つけられなかった場合に呼び出されます。

提供されるメソッドは以下の通りです。

  • func (p *Pool) Get() interface{}: プールからオブジェクトを取得します。プールに利用可能なオブジェクトがあればそれを返し、なければ p.New 関数を呼び出して新しいオブジェクトを生成して返します。返される値は interface{} 型なので、使用する際には適切な型アサーションが必要です。
  • func (p *Pool) Put(x interface{}): オブジェクトをプールに戻します。プールに戻されたオブジェクトは、将来の Get() 呼び出しで再利用される可能性があります。

sync.Pool は、スレッドセーフであり、複数のGoroutineから安全にアクセスできます。ただし、プールされたオブジェクトはGCの対象となる可能性があり、プールされたオブジェクトがいつ解放されるかは保証されません。そのため、sync.Pool はあくまで一時的なオブジェクトの再利用に限定して使用すべきであり、永続的なオブジェクトの管理には適していません。

NetBSD向け syscall パッケージの拡張

NetBSDは、移植性の高さで知られるUNIX系OSです。このコミットでは、NetBSDの386およびAMD64アーキテクチャ(CGOの有無を含む)向けに、多数のシステムコール関連定数が追加されました。これらは、GoプログラムがNetBSD上で低レベルなOS機能にアクセスするために使用されます。

  • CLONE_* 定数: これらは、プロセスやスレッドの作成に関連する clone() システムコール(Linux由来の概念だが、NetBSDにも類似の機能や互換性レイヤーが存在する可能性がある)のフラグです。例えば、CLONE_VM は親とメモリ空間を共有、CLONE_FILES はファイルディスクリプタを共有、CLONE_SIGHAND はシグナルハンドラを共有するといった意味を持ちます。これにより、GoプログラムはNetBSD上でより柔軟なプロセス生成やスレッド管理が可能になります。

  • MADV_* 定数: madvise() システムコールで使用されるフラグです。

    • MADV_DONTNEED: 指定されたメモリ領域の内容がもう必要ないことをカーネルに通知し、解放を促します。
    • MADV_FREE: メモリ領域を解放可能であることを示唆しますが、必要になるまで物理メモリを保持します。
    • MADV_NORMAL, MADV_RANDOM, MADV_SEQUENTIAL: メモリアクセスパターンに関するヒントをカーネルに与えます。
    • MADV_WILLNEED: 指定されたメモリ領域がすぐに必要になることをカーネルに通知し、プリフェッチを促します。
  • MAP_* 定数: mmap() システムコールで使用されるフラグです。

    • MAP_ANON: ファイルではなく匿名メモリ領域をマッピングします。
    • MAP_PRIVATE: プライベートなコピーオンライトマッピングを作成します。
    • MAP_SHARED: 共有メモリマッピングを作成します。
    • MAP_FIXED: 指定されたアドレスにマッピングを試みます。
    • MAP_STACK: スタック領域として使用されるメモリをマッピングします。 その他、アライメントに関する定数 (MAP_ALIGNMENT_*) なども追加されています。
  • MCL_* 定数: mlockall() システムコールで使用されるフラグです。

    • MCL_CURRENT: 現在マッピングされているすべてのページをロックします。
    • MCL_FUTURE: 将来マッピングされるすべてのページをロックします。
  • MS_* 定数: msync() システムコールで使用されるフラグです。

    • MS_ASYNC: 非同期で変更をディスクに書き込みます。
    • MS_SYNC: 同期的に変更をディスクに書き込みます。
    • MS_INVALIDATE: キャッシュされたデータを無効化します。
  • PROT_* 定数: mmap()mprotect() システムコールで使用されるメモリ保護フラグです。

    • PROT_READ: 読み取り可能。
    • PROT_WRITE: 書き込み可能。
    • PROT_EXEC: 実行可能。
    • PROT_NONE: アクセス不可。

これらの定数の追加により、GoプログラムはNetBSD上でより高度なメモリ管理、プロセス間通信、および低レベルなリソース操作を直接行えるようになり、システムプログラミングの可能性が広がります。

Windows向け syscall パッケージの拡張

Windows向けの syscall パッケージには、NewCallbackCDecl 関数が追加されました。

  • func NewCallbackCDecl(interface{}) uintptr: この関数は、Goの関数をWindowsのC言語の呼び出し規約 (__cdecl) に従うコールバック関数として利用できるようにするためのものです。Windows APIの多くはC言語で定義されており、コールバック関数を引数として受け取るものも少なくありません。NewCallbackCDecl を使用することで、Goで実装された関数をこれらのWindows APIに渡すことが可能になります。

    具体的には、Goの関数を uintptr 型のポインタに変換し、そのポインタをCGOを通じてC言語のコードに渡すことで、C言語側からGoの関数を呼び出すことができるようになります。これは、GoプログラムがWindowsのネイティブAPIやDLL(Dynamic Link Library)と連携する上で不可欠な機能であり、WindowsプラットフォームでのGoアプリケーションの機能性を大幅に向上させます。

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

このコミットは、api/next.txt ファイルのみを変更しています。このファイルは、Go言語の公開APIの変更を記録するためのテキストファイルであり、実際のGoのソースコード(.go ファイル)の変更は含まれていません。

--- a/api/next.txt
+++ b/api/next.txt
@@ -65,6 +65,9 @@ pkg debug/goobj, const SWINDOWS SymKind
 pkg debug/goobj, const SXREF = 24
 pkg debug/goobj, const SXREF SymKind
 pkg debug/goobj, func Parse(io.ReadSeeker, string) (*Package, error)
+pkg debug/goobj, method (Sym) String() string
+pkg debug/goobj, method (SymID) String() string
+pkg debug/goobj, method (SymKind) String() string
 pkg debug/goobj, type Data struct
 pkg debug/goobj, type Data struct, Offset int64
 pkg debug/goobj, type Data struct, Size int64
@@ -110,3 +113,401 @@ pkg debug/goobj, type Var struct, Kind int
 pkg debug/goobj, type Var struct, Name string
 pkg debug/goobj, type Var struct, Offset int
 pkg debug/goobj, type Var struct, Type SymID
+pkg sync, method (*Pool) Get() interface{}
+pkg sync, method (*Pool) Put(interface{})
+pkg sync, type Pool struct
+pkg sync, type Pool struct, New func() interface{}
+pkg syscall (netbsd-386), const CLONE_CSIGNAL = 255
+pkg syscall (netbsd-386), const CLONE_CSIGNAL ideal-int
+... (以下、NetBSDおよびWindowsのsyscall関連の追加が続く)

コアとなるコードの解説

前述の通り、このコミット自体はGoのソースコードの変更を含まず、api/next.txt というAPI変更履歴ファイルを更新するものです。したがって、ここに示されている変更箇所は、Goの次期リリースで公開されるAPIの「宣言」であり、そのAPIを実装する実際のGoのコードは、このコミット以前または同時に別のコミットで追加されています。

例えば、pkg sync, type Pool struct の行は、sync パッケージに Pool という新しい型が追加されることを示しています。この Pool 型の具体的な実装(sync/pool.go など)は、この api/next.txt の更新とは別のコミットでGoのソースツリーに追加されています。

同様に、pkg syscall (netbsd-386), const CLONE_CSIGNAL = 255 のような行は、NetBSDの syscall パッケージに CLONE_CSIGNAL という定数が追加されることを示しており、この定数の定義は syscall/zsysnum_netbsd_386.go のようなファイルに存在します。

このコミットの「コアとなるコードの変更箇所」は、GoのAPI互換性ポリシーとリリースプロセスを理解する上で重要です。api/next.txt は、Goの公開APIの安定性を保証するための重要なドキュメントであり、このファイルへの追加は、新しいAPIがGoの標準ライブラリの一部として正式に公開される準備ができたことを意味します。

関連リンク

参考にした情報源リンク

  • Go言語の公式ドキュメント
  • Go言語のソースコードリポジトリ (GitHub)
  • UNIX系OSのシステムコールに関する一般的な知識
  • Windows APIおよびCGOに関する一般的な知識
  • sync.Pool の設計に関する議論 (GoのメーリングリストやIssueトラッカー)
  • NetBSDのシステムコールに関するドキュメント (必要に応じて)
  • Go 1.3 リリースノート (sync.Poolが導入されたバージョン)
  • Go 1.2 リリースノート (このコミットが対象とする可能性のあるバージョン)