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

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

このコミットは、Go言語の標準ライブラリ net パッケージから、古くなった組み込みのネットワークポーリング機構を削除するものです。具体的には、BSD系のシステムで利用されていた kqueue ベースのポーリング実装と、一般的なUnixシステムで利用されていた汎用ポーリング実装が削除されました。

コミット

commit ed738ad354dcd6722d1d7fffcc4a27fd10148e78
Author: Mikio Hara <mikioh.mikioh@gmail.com>
Date:   Tue Aug 20 17:32:55 2013 +0900

    net: remove obsolete builtin network pollster
    
    Update #5199
    Update #6146
    
    R=golang-dev, dvyukov
    CC=golang-dev
    https://golang.org/cl/13112044

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

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

元コミット内容

net: remove obsolete builtin network pollster

このコミットは、Goのネットワークパッケージから、もはや使用されていない組み込みのネットワークポーリング機構を削除します。関連するIssueとして #5199 と #6146 が挙げられています。

変更の背景

この変更の背景には、GoランタイムにおけるネットワークI/Oの非同期処理とスケジューリングの進化があります。初期のGoランタイムでは、ネットワークI/Oの待機(pollepollkqueueなどのシステムコール)を処理するために、netパッケージ内に独自のポーリング機構を持っていました。これは、Goのゴルーチン(goroutine)がブロッキングI/OによってOSスレッドをブロックしないようにするための重要なコンポーネントでした。

しかし、Go 1.1以降、ランタイムのスケジューラとネットワークポーラーの統合が進みました。特に、runtimeパッケージ内に、より汎用的で効率的なネットワークポーラー(netpoll)が導入され、すべての非同期ネットワークI/Oがこの単一のポーラーによって処理されるようになりました。これにより、netパッケージ内に個別に存在していたポーリング関連のコードは冗長となり、保守の負担となっていました。

このコミットは、その冗長なコードを削除し、ランタイムのnetpollに処理を一元化することで、コードベースの簡素化と効率化を図るものです。参照されているIssue #5199 と #6146 は、このポーリング機構の改善と統合に関連するものです。

前提知識の解説

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

  • 非同期I/Oとポーリング:

    • ブロッキングI/O: 通常のI/O操作は、データが利用可能になるまでプログラムの実行を停止(ブロック)させます。
    • 非同期I/O: I/O操作の開始後、すぐに制御を呼び出し元に戻し、I/Oの完了は別のメカニズム(コールバック、イベントなど)で通知されます。これにより、I/O待機中に他の処理を進めることができます。
    • ポーリング (Polling): 複数のI/Oディスクリプタ(ファイルディスクリプタ、ソケットなど)の状態を定期的にチェックし、読み書き可能になったものを検出するメカニズムです。Unix系OSではselect, poll, epoll (Linux), kqueue (BSD/macOS) などのシステムコールがこれに該当します。これらは、多数のI/O操作を効率的に多重化するために使用されます。
  • Goランタイムとゴルーチン:

    • ゴルーチン (Goroutine): Go言語の軽量な並行処理単位です。OSスレッドよりもはるかに軽量で、数百万個のゴルーチンを同時に実行できます。
    • Goスケジューラ: ゴルーチンをOSスレッドにマッピングし、実行を管理するGoランタイムのコンポーネントです。ゴルーチンがブロッキングI/Oを行うと、スケジューラはそのゴルーチンをOSスレッドから切り離し、I/Oが完了するまで待機させます。I/Oが完了すると、ポーラーがスケジューラに通知し、スケジューラはゴルーチンを再び実行可能な状態に戻します。
    • ネットワークポーラー (Netpoll): Goランタイムに組み込まれた特別なポーラーで、ネットワークI/Oの非同期処理を担当します。これにより、Goのネットワーク操作は、たとえブロッキングI/Oシステムコールを使用していたとしても、ゴルーチンレベルでは非同期に振る舞い、OSスレッドをブロックしません。
  • net パッケージ:

    • Go言語の標準ライブラリで、TCP/IPネットワーク通信、UDP、Unixドメインソケットなどを扱うための機能を提供します。このパッケージの内部では、OSのネットワークI/Oシステムコールを効率的に利用するために、ランタイムのポーリング機構と連携しています。

技術的詳細

このコミットで削除されたファイルは以下の2つです。

  1. src/pkg/net/fd_bsd.go:

    • このファイルは、BSD系のOS(macOS, FreeBSDなど)で利用されるkqueue/keventシステムコールに基づいたポーリング機構を実装していました。
    • pollster構造体がkqueueファイルディスクリプタとイベントバッファを保持し、AddFDDelFDWaitFDなどのメソッドを通じてファイルディスクリプタのイベントを監視していました。
    • kqueueは、イベント駆動型のI/O多重化メカニズムであり、ファイルディスクリプタの状態変化を効率的に通知します。
  2. src/pkg/net/fd_poll_unix.go:

    • このファイルは、より一般的なUnix系OS(Linuxなど)で利用されるpollシステムコール(またはepoll)に基づいたポーリング機構を実装していました。
    • pollServer構造体がポーリングのメインループを管理し、pollDesc構造体が個々のファイルディスクリプタの状態とデッドラインを管理していました。
    • AddFDEvictWakeupWaitReadWaitWriteなどのメソッドを通じて、ネットワークI/Oの待機と完了通知を行っていました。
    • この実装は、os.Pipeを使用してポーラー自身のウェイクアップ機構を実装するなど、複雑なロジックを含んでいました。

これらのファイルが削除されたのは、Goランタイムのruntimeパッケージに、より統合されたnetpoll機構が導入されたためです。runtime/netpoll.goに実装されているnetpollは、OSごとのポーリングシステムコール(Linuxのepoll、BSDのkqueue、WindowsのI/O Completion Portsなど)を抽象化し、Goのスケジューラと密接に連携して動作します。これにより、netパッケージはI/Oの待機を直接OSに依頼するのではなく、ランタイムのnetpollに委譲する形になりました。

この変更により、netパッケージはポーリングの詳細な実装から解放され、より高レベルなネットワークプロトコルとAPIの提供に集中できるようになりました。また、ランタイムレベルでのポーリングの一元化は、パフォーマンスの向上、コードの簡素化、および保守性の向上に寄与します。

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

このコミットは、既存のコードの削除のみで構成されています。

  • src/pkg/net/fd_bsd.go: ファイル全体が削除されました。
  • src/pkg/net/fd_poll_unix.go: ファイル全体が削除されました。

変更行数としては、fd_bsd.goで123行、fd_poll_unix.goで379行、合計502行の削除が行われています。

コアとなるコードの解説

削除されたコードは、Goのnetパッケージが内部的に使用していた、OS固有の非同期I/Oポーリングメカニズムの実装でした。

fd_bsd.goは、kqueueシステムコール(syscall.Kqueue, syscall.Kevent)を直接利用して、ファイルディスクリプタの読み書きイベントを監視していました。pollster構造体はkqueueインスタンスを管理し、AddFDでイベントを登録し、WaitFDでイベントを待機していました。

fd_poll_unix.goは、より抽象化されたpollServerpollDescの概念を導入し、pollster(このファイル内ではfd_bsd.goや他のOS固有のポーラー実装をラップする形)を利用してI/Oイベントを処理していました。pollServerはゴルーチンとしてバックグラウンドで動作し、登録されたファイルディスクリプタのイベントを監視し、イベントが発生した際にpollDescのチャネル(cr, cw)にエラーを送信することで、待機しているゴルーチンをウェイクアップしていました。また、デッドライン処理や、os.Pipeを使ったポーラー自身のウェイクアップ機構も含まれていました。

これらのコードが削除されたことで、netパッケージはこれらの低レベルなポーリング実装の詳細を知る必要がなくなり、Goランタイムのruntime/netpoll.goに存在する統一されたネットワークポーラーに依存するようになりました。これにより、netパッケージのコードはよりクリーンで、OS間の差異を意識する必要がなくなりました。

関連リンク

  • Go Issue #5199: net: make net.pollServer use runtime.netpoll
    • このIssueは、netパッケージのポーラーをruntime.netpollに移行することを提案しています。
  • Go Issue #6146: net: remove obsolete pollster
    • このIssueは、本コミットで削除された古いポーラーを削除することを提案しています。
  • Go CL 13112044: net: remove obsolete builtin network pollster
    • このコミットに対応するGoのコードレビューシステム(Gerrit)のチェンジリストです。

参考にした情報源リンク

  • Goのソースコード(特にsrc/runtime/netpoll.goの現在の実装)
  • GoのIssueトラッカー(#5199, #6146)
  • Goのドキュメントやブログ記事(Go 1.1以降のネットワークI/Oの変更に関するもの)
  • kqueueepollpollなどのシステムコールに関するOSのドキュメント
  • Goの並行処理とスケジューラに関する一般的な解説記事