知識マップ: Windows I/Oの深層(第3回) ── I/O完了ポート(IOCP)と.NETスレッドプール:async/awaitの地下室
記事「Windows I/Oの深層(第3回) ── I/O完了ポート(IOCP)と.NETスレッドプール:async/awaitの地下室」の主張を、概念と関係(エッジ)に分解した知識グラフの全体です。各関係には根拠・確認日・確度が付いています。
I/O完了ポート(IOCP)は、非同期I/Oの完了パケットをFIFOのキューに集約しつつ、実行可能なスレッド数をコンカレンシー値以下に抑えるスケジューリング機構でもあります。待機スレッドはLIFOで起こされるため、忙しいときほど同じスレッドが回り続けてコンテキストスイッチを抑えられます。.NETスレッドプールはワーカースレッドとI/O完了スレッドの2階建てで、非同期ハンドルはThreadPoolBoundHandle経由でプール自身のIOCPに結び付き、awaitのI/O待ちにスレッドは存在せず完了後の継続だけがスレッドに乗ります。継続の行き先は捕捉されたSynchronizationContext次第で、ConfigureAwait(false)は捕捉をやめる指示にすぎません。継続やワーカーへの同期待ちの混入(sync-over-async)は、スレッドプール飢餓の主因です。
flowchart LR
accTitle: I/O完了ポート(IOCP)と.NETスレッドプールの知識マップ
accDescr: I/O完了ポートが完了通知のFIFOキューと実行可能スレッド数の制御(コンカレンシー値)を一体化していること、待機スレッドがLIFOで起こされること、CompletionKeyとOVERLAPPEDによる完了パケットの識別、.NETスレッドプールがワーカースレッドとI/O完了スレッドの2階建てでThreadPoolBoundHandle/NativeOverlappedを介してIOCPに結び付くこと、awaitの継続先がSynchronizationContextとConfigureAwait(false)で決まること、同期待ちの混入がスレッドプール飢餓を招くことを示す図
iocp["I/O完了ポート(IOCP)"]
dotnet_threadpool[".NETスレッドプール"]
completion_key["CompletionKey"]
createiocompletionport["CreateIoCompletionPort"]
getqueuedcompletionstatus["GetQueuedCompletionStatus"]
overlapped_structure["OVERLAPPED構造体"]
getqueuedcompletionstatusex["GetQueuedCompletionStatusEx"]
postqueuedcompletionstatus["PostQueuedCompletionStatus"]
concurrency_value["コンカレンシー値"]
threadpool_io_api["Windowsスレッドプールの I/O API"]
overlapped_io["Overlapped I/O"]
worker_thread_dotnet["ワーカースレッド(.NET)"]
io_completion_thread_dotnet["I/O完了スレッド(.NET)"]
threadpoolboundhandle["ThreadPoolBoundHandle.BindHandle"]
nativeoverlapped["NativeOverlapped"]
fileoptions_asynchronous["FileOptions.Asynchronous"]
asynchronous_io["非同期I/O"]
synchronizationcontext["SynchronizationContext"]
configureawait_false["ConfigureAwait(false)"]
sync_over_async["同期待ちの混入(sync-over-async)"]
threadpool_starvation["スレッドプール飢餓(starvation)"]
taskrun_dotnet["Task.Run"]
lifo_thread_scheduling["LIFOスレッド解放"]
getavailablethreads_dotnet["ThreadPool.GetAvailableThreads"]
error_operation_aborted["ERROR_OPERATION_ABORTED"]
fake_async["見せかけの非同期"]
file_handle["ファイルハンドル"]
iocp -->|"利用する"| completion_key
iocp -->|"利用する"| createiocompletionport
iocp -->|"利用する"| getqueuedcompletionstatus
getqueuedcompletionstatus -->|"利用する"| completion_key
getqueuedcompletionstatus -->|"前提とする"| overlapped_structure
getqueuedcompletionstatusex -->|"前提とする"| iocp
postqueuedcompletionstatus -->|"前提とする"| iocp
postqueuedcompletionstatus -.->|"利用する"| completion_key
concurrency_value -->|"で構成できる"| createiocompletionport
iocp -->|"利用する"| concurrency_value
threadpool_io_api -->|"利用する"| iocp
threadpool_io_api -->|"推奨される対応"| overlapped_io
dotnet_threadpool -->|"利用する"| iocp
dotnet_threadpool -->|"利用する"| worker_thread_dotnet
dotnet_threadpool -->|"利用する"| io_completion_thread_dotnet
threadpoolboundhandle -->|"前提とする"| iocp
threadpoolboundhandle -->|"利用する"| nativeoverlapped
nativeoverlapped -->|"実装を担う"| overlapped_structure
fileoptions_asynchronous -.->|"前提とする"| threadpoolboundhandle
io_completion_thread_dotnet -->|"利用する"| getqueuedcompletionstatus
asynchronous_io -.->|"利用する"| synchronizationcontext
configureawait_false -->|"両立しない"| synchronizationcontext
sync_over_async -->|"原因になり得る"| threadpool_starvation
sync_over_async -->|"用いるのは非推奨"| dotnet_threadpool
taskrun_dotnet -->|"前提とする"| worker_thread_dotnet
iocp -->|"利用する"| lifo_thread_scheduling
dotnet_threadpool -->|"で確認できる"| getavailablethreads_dotnet
threadpool_starvation -->|"で確認できる"| getavailablethreads_dotnet
getqueuedcompletionstatus -.->|"原因になり得る"| error_operation_aborted
io_completion_thread_dotnet -->|"前提とする"| asynchronous_io
fake_async -->|"利用する"| worker_thread_dotnet
createiocompletionport -->|"利用する"| completion_key
iocp -->|"前提とする"| file_handle
概念間の関係(全33件)
図と同じ関係を文章でも列挙します。表示している文と機械可読な意味データ(RDFa)は同じ要素に載っています。確度が「確立した関係」のものは直接の関係として、「条件付きの関係」のものは成立条件つきの言明(rdf:Statement)として表現しています。
- I/O完了ポート(IOCP)はCompletionKeyを利用します。
- I/O完了ポート(IOCP)はCreateIoCompletionPortを利用します。
- I/O完了ポート(IOCP)はGetQueuedCompletionStatusを利用します。
- GetQueuedCompletionStatusはCompletionKeyを利用します。
- GetQueuedCompletionStatusはOVERLAPPED構造体を前提とします。
- GetQueuedCompletionStatusExはI/O完了ポート(IOCP)を前提とします。
- PostQueuedCompletionStatusはI/O完了ポート(IOCP)を前提とします。
- PostQueuedCompletionStatusはCompletionKeyを利用します。
- コンカレンシー値はCreateIoCompletionPortで構成できます。
- I/O完了ポート(IOCP)はコンカレンシー値を利用します。
- Windowsスレッドプールの I/O APIはI/O完了ポート(IOCP)を利用します。
- Windowsスレッドプールの I/O APIはOverlapped I/Oに対する本記事の推奨です。
- .NETスレッドプールはI/O完了ポート(IOCP)を利用します。
- .NETスレッドプールはワーカースレッド(.NET)を利用します。
- .NETスレッドプールはI/O完了スレッド(.NET)を利用します。
- ThreadPoolBoundHandle.BindHandleはI/O完了ポート(IOCP)を前提とします。
- ThreadPoolBoundHandle.BindHandleはNativeOverlappedを利用します。
- NativeOverlappedはOVERLAPPED構造体の実装を担います。
- FileOptions.AsynchronousはThreadPoolBoundHandle.BindHandleを前提とします。
- I/O完了スレッド(.NET)はGetQueuedCompletionStatusを利用します。
- 非同期I/OはSynchronizationContextを利用します。
- ConfigureAwait(false)はSynchronizationContextと両立しません。
- 同期待ちの混入(sync-over-async)はスレッドプール飢餓(starvation)の原因になることがあります。
- 同期待ちの混入(sync-over-async)を.NETスレッドプールに用いることは推奨されません。
- Task.Runはワーカースレッド(.NET)を前提とします。
- I/O完了ポート(IOCP)はLIFOスレッド解放を利用します。
- .NETスレッドプールはThreadPool.GetAvailableThreadsで確認できます。
- スレッドプール飢餓(starvation)はThreadPool.GetAvailableThreadsで確認できます。
- GetQueuedCompletionStatusはERROR_OPERATION_ABORTEDの原因になることがあります。
- I/O完了スレッド(.NET)は非同期I/Oを前提とします。
- 見せかけの非同期はワーカースレッド(.NET)を利用します。
- CreateIoCompletionPortはCompletionKeyを利用します。
- I/O完了ポート(IOCP)はファイルハンドルを前提とします。
主要概念の定義
機械可読データ
このページはサイトの知識グラフ(_data/knowledge/)から自動生成されています。誤りの指摘はお問い合わせからお願いします。