I searched the web on some technical details about blocking I/O and non blocking I/O and I found several people stating that non-blocking I/O would be faster than blocking I/O. For example in このドキュメント。
ブロッキング I/O を使用する場合、現在ブロックされているスレッドは、ブロックされているため、他の操作を行うことはできません。ただし、スレッドがブロックされ始めるとすぐに、OS は別のスレッドに切り替えることができ、ブロックされたスレッドに何か処理が行われるまで元に戻ることはありません。したがって、CPU を必要とし、ブロックされていない別のスレッドがシステムに存在する限り、イベント ベースの非ブロッキング アプローチと比較して、CPU のアイドル時間は増えないはずです。
CPU のアイドル時間を減らすこと以外に、コンピューターが一定時間内に実行できるタスクの数を増やすためのもう 1 つの方法があります。スレッドの切り替えによって生じるオーバーヘッドを減らすことです。しかし、これはどのように実行できるのでしょうか。また、オーバーヘッドは測定可能な効果を示すほど大きいのでしょうか。これがどのように機能するかについて、私の考えを以下に示します。
- ファイルの内容をロードするために、アプリケーションはこのタスクをイベントベースのI/Oフレームワークに委任し、ファイル名とともにコールバック関数を渡します。
- イベントフレームワークはオペレーティングシステムに委任し、オペレーティングシステムはハードディスクのDMAコントローラをプログラムしてファイルを直接メモリに書き込む。
- イベント フレームワークにより、さらにコードを実行できます。
- ディスクからメモリへのコピーが完了すると、DMA コントローラは割り込みを発生させます。
- オペレーティング システムの割り込みハンドラは、ファイルが完全にメモリにロードされたことをイベントベースの I/O フレームワークに通知します。これはどのように行われるのでしょうか。シグナルを使用するのでしょうか。
- イベント I/O フレームワーク内で現在実行されているコードが終了します。
- イベントベースの I/O フレームワークはキューをチェックし、ステップ 5 からのオペレーティング システムのメッセージを確認し、ステップ 1 で取得したコールバックを実行します。
それはそのように動作するのでしょうか? そうでない場合、どのように動作するのでしょうか? つまり、イベント システムは、スタックに明示的に触れる必要なしに動作できるということです (実際のスケジューラでは、スタックをバックアップし、スレッドを切り替えるときに別のスレッドのスタックをメモリにコピーする必要があります)。これにより、実際にどのくらいの時間が節約されますか? 他にも何かありますか?
ベストアンサー1
非ブロッキングまたは非同期 I/O の最大の利点は、スレッドが並行して作業を継続できることです。もちろん、追加のスレッドを使用してもこれを実現できます。おっしゃるとおり、全体的な (システム) パフォーマンスを最大化するには、複数のスレッドではなく非同期 I/O を使用する方がよいと思います (スレッドの切り替えが減ります)。
並列に接続された 1000 台のクライアントを処理するネットワーク サーバー プログラムの実装例を見てみましょう。
- 接続ごとに 1 つのスレッド (ブロッキング I/O も可能ですが、非ブロッキング I/O も可能です)。
各スレッドにはメモリ リソース (カーネル メモリも) が必要であり、これは不利です。また、スレッドが追加されるたびに、スケジューラの作業が増えることになります。 - すべての接続に対して 1 つのスレッド。
これにより、スレッドが少なくなるため、システムの負荷が軽減されます。ただし、1 つのプロセッサを 100% まで駆動し、他のすべてのプロセッサをアイドル状態にしてしまう可能性があるため、マシンのパフォーマンスを最大限に活用できなくなります。 - いくつかのスレッドがあり、各スレッドが接続の一部を処理します。
スレッド数が少なくなるため、システムの負荷が軽減されます。また、利用可能なすべてのプロセッサを使用できます。Windowsでは、このアプローチはスレッドプール API。
もちろん、スレッド数が多いこと自体は問題ではありません。お気づきかもしれませんが、私はかなり多くの接続/スレッドを選択しました。12 個のスレッドだけの話であれば、3 つの実装の違いがわかるとは思えません (これは Raymond Chen が MSDN のブログ投稿で提案していることでもあります)。Windows ではプロセスあたり 2000 スレッドの制限がありますか?)。
Windowsの場合バッファなしファイルI/O書き込みはページ サイズの倍数でなければならないことを意味します。テストはしていませんが、バッファリングされた同期書き込みと非同期書き込みの書き込みパフォーマンスにも良い影響を与える可能性があるようです。
説明されている手順 1 から 7 を見れば、それがどのように動作するかがよくわかります。Windows では、オペレーティング システムはイベントまたはコールバックを使用して、非同期 I/O (構造体WriteFile
を使用) の完了を通知します。コールバック関数は、たとえば、コードが に設定されて をOVERLAPPED
呼び出す場合にのみ呼び出されます。WaitForMultipleObjectsEx
bAlertable
true
ウェブ上でさらに読む:
- ユーザーインターフェースの複数のスレッドMSDNでは、スレッド作成のコストもすぐに処理します
- セクションスレッドとスレッドプール「スレッドの作成と使用は比較的簡単ですが、オペレーティング システムはスレッドの管理にかなりの時間とその他のリソースを割り当てます。」
- MSDN の CreateThread ドキュメント「ただし、プロセッサごとに 1 つのスレッドを作成し、アプリケーションがコンテキスト情報を保持する要求のキューを構築すると、アプリケーションのパフォーマンスが向上します。」と述べています。
- 古い記事スレッドが多すぎるとパフォーマンスが低下する理由とその対処法