問題タブ [overlapped-io]
For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.
operating-system - システム全体が数百ミリ秒から数千ミリ秒ハングしているように見える原因は何ですか?
私は Windows ゲームに取り組んでおり、レンダリング中に一部のコンピューターで断続的な一時停止が発生します (適切な用語がないため「ヒッチ」)。プロファイリングすると、コード内の一見ランダムな場所に表示されます。最終的に、影響を受けたのは自分のプロセスだけでなく、(一見) システム上のすべてのプロセスであることに気付きました。アプリケーションのすべてのスレッドが一度にヒッチします。これらのヒッチの間に CPU 使用率が低下し、ほとんどのプロセスが進行していないように見えます。
これにより、これはオペレーティング システムまたはドライバーの問題であると思われますが、ゲームのプレイ中にのみ発生します (一部のシステムでのみ発生します)。カーネルがすべてのユーザースレッドを一時停止してブロックする必要がある、オペレーティングシステムが実行している可能性のある操作の種類。ある種のI/O?最初はページングを考えましたが、それは単一のプロセスにしか影響しないという印象ですよね?
使用中の一部のシステム: Windows、DirectX (3d)、nVidia カード (ATI でレプリケートするかどうかは不明)、ストリーミングにオーバーラップ io を使用
winapi - 非同期 NtQueryDirectoryFile?
NtQueryDirectoryFileへの非同期呼び出しがどのように機能するかを理解できた人はいますか?
非同期呼び出しとは、FILE_SYNCHRONOUS_IO_ALERTまたは FILE_SYNCHRONOUS_IO_NONALERT で開かれていないNtQueryDirectoryFile
ディレクトリを呼び出すことを意味します。
私にとっては、通常のNtReadFileリクエストが通常のファイルに対して行うのとSTATUS_PENDING
同じように返されるようですが、ディレクトリでNtWaitForSingleObjectを使用しようとすると、正しく終了せず、まだすべてのデータを取得していません...なぜこれは起こりますか?
windows - 小さな読み取り (オーバーラップ、バッファリング) の説明は、大きな連続した読み取りよりも優れていますか?
(ちょっと前置きが長くなってすみません)
後で実際の実行を高速化するために、大きなファイル全体 (>400MB) をバッファ キャッシュにプレフォールトするアプリケーションの開発中に、一度に 4MB を読み取ることが、一度に 1MB のチャンクのみを読み取る場合よりも顕著な利点があるかどうかをテストしました。驚くべきことに、実際には小さなリクエストの方が高速であることが判明しました。これは直感に反するように思えたので、より広範なテストを実行しました。
テストを実行する前に、バッファ キャッシュを消去しました (笑いのために、私もバッファ内のファイルで 1 回実行しました。バッファ キャッシュは、要求のサイズに関係なく 2GB/秒以上を提供しますが、驚くべきことに +/- 30% です)。ランダム分散)。
すべての読み取りは、同じターゲット バッファーを持つオーバーラップした ReadFile を使用しました (ハンドルは を使用して、または使用せずに開かれましFILE_FLAG_OVERLAPPED
た) FILE_FLAG_NO_BUFFERING
。使用されているハードディスクはやや古いものですが、完全に機能しており、NTFS のクラスター サイズは 8kB です。ディスクは最初の実行後に最適化されました (6 つのフラグメントと非フラグメント、ゼロの差)。より良い数値を得るために、私はより大きなファイルも使用しました.以下の数値は1GBを読み取るためのものです.
結果は本当に驚くべきものでした:
したがって、これは、 2 クラスタの長さで 1 万件のリクエストを送信する方が、数百の大規模な連続した読み取りを送信するよりも実際には優れていることを示唆しています。送信時間 (ReadFile が返されるまでの時間) は、要求の数が増えるにつれて大幅に増加しますが、非同期完了時間はほぼ半分になります。
非同期読み取りが完了している間、カーネルの CPU 時間はすべてのケースで約 5 ~ 6% です (クアッドコアでは、実際には 20 ~ 30% と言うべきです)。これは CPU の驚くべき量です。忙しい待機時間も無視できます。2.6 GHz で 25 秒間 30% の CPU。これは、「何もしない」ためのかなりの数のサイクルです。
これをどのように説明できますか?ここにいる誰かが、Windows オーバーラップ IO の内部動作についてより深い洞察を持っているのではないでしょうか? それとも、ReadFile を使用して 1 メガバイトのデータを読み取ることができるという考えに、何か根本的な間違いがありますか?
特にリクエストがランダム アクセスの場合 (ランダム アクセスではない場合)、IO スケジューラがシークを最小限に抑えることで複数のリクエストを最適化できることがわかります。また、NCQ でいくつかの要求が与えられた場合に、ハードディスクが同様の最適化をどのように実行できるかを確認できます。
しかし、私たちは途方もなく小さな要求の途方もない数について話しているのです。
補足:明らかな勝者はメモリ マッピングです。私はメモリマッピングの大ファンなので、「当然のことながら」追加する傾向がありますが、この場合、「要求」がさらに小さくなり、OS が予測して実行する能力がさらに低下するため、実際には驚きます。 IO をスケジュールします。最初はメモリ マッピングをテストしませんでした。リモートでも競合できる可能性があると直感に反するように思えたからです。あなたの直感はこれで終わりです。
ビューを異なるオフセットで繰り返しマッピング/マッピング解除すると、実質的に時間がかかりません。16MB のビューを使用し、ページごとに 1 バイトを読み取る単純な for() ループですべてのページをフォールトすると、9.2 秒 @ ~111 MB/秒で完了します。CPU 使用率は常に 3% (1 コア) 未満です。同じコンピューター、同じディスク、すべて同じ。
また、Windows は一度に 8 ページをバッファ キャッシュにロードするように見えますが、実際には 1 ページしか作成されません。8 ページごとにフォールトすると、同じ速度で実行され、ディスクから同じ量のデータが読み込まれますが、「物理メモリ」と「システム キャッシュ」のメトリックが低くなり、ページ フォールトの 1/8 しか表示されません。その後の読み取りでは、ページが確実にバッファ キャッシュ内にあることが証明されます (遅延やディスク アクティビティはありません)。
(おそらく、 Memory-Mapped File is Faster on Huge Sequential Read と非常に、非常に遠い関係がありますか? )
もう少しわかりやすくするために、次のようにします。
アップデート:
を使用するFILE_FLAG_SEQUENTIAL_SCAN
と、128k の読み取りの「バランス」がとれているように見え、パフォーマンスが 100% 向上します。一方、これは 512k と 256k の読み取りに深刻な影響を与え (なぜだろうか?)、それ以外には実際の影響はありません。より小さいブロック サイズの MB/秒グラフは、間違いなくもう少し「均一」に見えますが、実行時間には違いはありません。
ブロックサイズが小さいほどパフォーマンスが向上するという説明も見つけたかもしれません。ご存じのとおり、非同期リクエストは、OS がリクエストを即座に処理できる場合、つまりバッファから (およびさまざまなバージョン固有の技術的制限により) リクエストを処理できる場合、同期的に実行される場合があります。
実際の非同期読み取りと「即時」の非同期読み取りを比較すると、 256kを超えると、Windows はすべての非同期要求を非同期的に実行することに気付きます。ブロックサイズが小さいほど、すぐに利用できない場合でも、より多くの要求が「すぐに」処理されます(つまり、ReadFile は単に同期的に実行されます)。明確なパターン(「最初の100リクエスト」や「1000以上のリクエスト」など)は分かりませんが、リクエストサイズと同期性には逆相関があるようです。ブロックサイズが 8k の場合、すべての非同期リクエストは同期的に処理されます。
バッファリングされた同期転送は、何らかの理由で非同期転送の 2 倍の速さです (理由はわかりません)。したがって、要求サイズが小さいほど、より多くの転送が同期的に行われるため、転送全体が高速になります。
メモリ マップド プレフォールトの場合、FILE_FLAG_SEQUENTIAL_SCAN によってパフォーマンス グラフの形状がわずかに異なります (少し後ろに移動した「ノッチ」があります) が、所要時間の合計はまったく同じです (これも驚くべきことですが、私にはわかりません)。それを助ける)。
更新 2:
バッファリングされていない IO により、1M、4M、および 512k リクエストのテストケースのパフォーマンス グラフは、最大値が 90 GB/s で、やや高くなり、より「スパイキー」になりますが、最小値も厳しく、1GB の全体的な実行時間は +/- 0.5 以内です。バッファリングされた実行の s (ただし、2558 を超える進行中のリクエストでは、ERROR_WORKING_SET_QUOTA が返されるため、バッファ サイズが小さいリクエストは大幅に高速に完了します)。発生するすべての IO は DMA 経由で実行されるため、測定された CPU 使用率はすべての非バッファリングのケースでゼロです。これは当然のことです。
もう 1 つの非常に興味深い観察結果FILE_FLAG_NO_BUFFERING
は、API の動作が大幅に変わることです。少なくともIO をキャンセルCancelIO
するという意味では機能しません。バッファリングされていない進行中のリクエストでは、すべてのリクエストが完了するまで単純にブロックされます。弁護士はおそらく、関数が戻ったときに実行中のリクエストが残っていないため、関数がその義務を怠ったことについて責任を負うことはできないと主張するでしょう。は多少異なります。バッファリングされ、オーバーラップされた IO を
使用すると、単純にロープが切断され、実行中のすべての操作がすぐに終了します。CancelIO
CancelIO
もう 1 つの面白い点は、すべての要求が完了するか失敗するまで、プロセスを強制終了できないことです。OSがそのアドレス空間にDMAを実行している場合、この種のことは理にかなっていますが、それでも驚くべき「機能」です.
c++ - 重複したソケット IO でのエラー処理
重複したソケット IO と IOCP を使用している場合に、システム エラーを処理する信頼できる方法を誰か提案してもらえますか?
この点に関して、MSDN の説明は扱いにくいです。戻りコードがGetQueuedCompletionStatus
FALSE の場合GetLastError
、失敗した操作のエラー コードを取得するために、後続の呼び出しが必要であることが示されています。WSAGetLastError
ただし、WSA 関数については、代わりに呼び出す必要があることがわかっています (GetLastError
ソケット エラーの場合は 0 を返します)。質問の最初の部分は、実際にはどのように機能するのかということです。
もう 1 つの問題は、完了パケットが によって抽出された場合のエラー処理GetQueuedCompletionStatusEx
です。MSDN では、この呼び出し自体のエラー処理についてのみ説明しており、個々の失敗した操作のエラー コードの取得については何も述べていません。
すべての応答とコメントに事前に感謝します。
c++ - 2 回目のパスで WaitCommEvent が無効なパラメータに失敗する
私のアプリケーションは、オーバーラップしたイベントでシリアル I/O を使用しています。何らかの理由で、::WaitCommEvent
を使用したループの 2 回目のパスで一貫して失敗しますERROR_INVALID_PARAMETER
。誰かが私が違うことをする必要があることを説明できれば、それは大歓迎です。私のシリアルポートの初期化/オープンコードとスレッド関数が続きます。init/open コードは、スレッド関数が開始された後に実行されることに注意してください。これが for の呼び出し::WaitForSingleObject
です。
さらに、::WaitForSingleObject( pobjSerialPort->m_hSerialPort, INFINITE );
シリアルポートがいつ開いているかを判断する非ブロッキング手段として、次のようなものが有効かどうか疑問に思っていました。
シリアル ポートの初期化:
シリアル ポート通信イベント スレッド:
通信イベント処理関数
受信データ通信イベント関数の処理
受信スレッド機能
c++ - デバッガーでの Winsock2 データ損失
オーバーラップ I/O と組み合わせて Winsock2 を使用しています。これは、WSAOVERLAPPED 構造を使用して WSARecv を呼び出し、後でデータを WSAWaitForMultipleEvents で待機することを意味します。
デバッガーでアプリケーションを停止している間に、アプリケーションに送信されたデータが失われているように見えるという奇妙な観察をしました。このデータは OS のどこかに蓄積され、次に WSARecv が呼び出されたときに配信されると思いました。
私の仮定は間違っていますか?
c - FILE_FLAG_OVERLAPPED で開かれたファイルへの同期書き込み
を使用してファイルを開きました
ファイル ハンドルは、非同期読み取り操作に使用されます。
これは機能します。ただし、今は同期書き込みを行いたいです。WriteFile
ドキュメンテーションは次のように述べています
hFile が FILE_FLAG_OVERLAPPED で開かれた場合、次の条件が
有効になります。
lpOverlapepd
パラメータが省略された場合、ERROR_INVALID_PARAMETER
によって返されGetLastError()
ます。2 つのハンドル (1 つは読み取り用、もう 1 つは書き込み用) を開くことも、2 番目のハンドルがERROR_ACCESS_DENIED
エラーを生成するため機能しません。
非同期読み取りおよび同期書き込み用にファイルを開くにはどうすればよいですか? コードの複雑さを不必要に増やしたくありません。
c++ - Winsock:重複したAcceptExは、クライアントが接続していないときに新しい接続を示します
私のプログラムでは、重複したバージョンを使用してAcceptEx()
新しい接続を受け入れています。新しい接続が受け入れられた後、プログラムは、AcceptEx()
さらに接続を受け入れるために、への別の重複呼び出しを開始します。これは正常に機能し、複数のクライアントをサーバーに正常に接続できます。
しかし、1つのクライアントを接続し、サーバーアプリケーションにこのソケットでWSARecv(オーバーラップ)を呼び出させると、 AcceptEx()
魔法のように新しい「ゴースト」接続を受け入れます(最初のクライアントは何も実行していません)。もちろん、私がそれを呼び出すとWSARecv
、エラーが発生します。
プログラムには、重複するすべての呼び出し用のI/O完了ポートが組み込まれています。
偽の接続がどこから来ているのかわかりません。しかし、それは私が見つけることができない私のコードのバグのようです。
エラーの理由から明確に除外できるもの:1。使用する重複構造とキャストのパラメーターは正しく機能します。2.IOCPラッパークラス。
以下は関連するコードです(私の意見では)-もっと必要な場合は教えてください:)
編集:問題なく動作するテストサーバーを作成しました
c++ - recv へのオーバーラップ呼び出しが ERROR_NO_MORE_ITEMS(259) を返すのはなぜですか?
I/O-Completion ポートと winsock ソケットを使っていくつかのテストを行いました。接続からデータを受信し、隣接してそのソケットで WSARecv を再度呼び出すと、すぐにエラー 259 (ERROR_NO_MORE_ITEMS) が返されることがありました。
recv 呼び出しをブロック/着信データの待機状態に保つのではなく、システムが重複したトランザクションにこのエラーのフラグを立てる理由を知りたいです。
これがどういう意味かわかりますか?
お考えをお聞かせいただければ幸いです。
編集:コード
エラーチェックをカット...
Recv-member-function は、WSABUF と受信バッファ自体を作成する WSARecv-call の単純なラッパーです (freewsabuf を介してユーザーがクリーンアップする必要があります - 言及するだけです)...
winapi - I/Oが重複しているTCP接続
I / Oが重複しているTCP接続要求を開始し、Windowsで接続が完了する前にキャンセルすることはできますか?少なくともWindowsXPSP2をサポートする必要があります。