2017-12-27 68 views
2

SetFilePointerを検討してください。フォワードシークがシーケンシャルアクセスを構成するかどうかをMSDNのドキュメント(docs.microsoft.comも)は説明していません。これはアプリケーションのIOパフォーマンスに影響します。あなたはFILE_FLAG_RANDOM_ACCESSCreateFileを使用する場合読み取りよりも安価で、順次アクセス最適化のフォールスファウルを求めていますか?

たとえば、その後、Win32のはFILE_FLAG_SEQUENTIAL_SCANとは異なるバッファリングとキャッシング戦略を使用します - あなたが最初から最後までのファイルを読んでいるならば、あなたはランダムアクセスよりも優れたパフォーマンスを期待することができますオプション。

しかし、読み込んでいるファイルフォーマットが、ファイルのヘッダーのフラグが最初の100バイト - つまり100キロバイトを示すなど、すべてのバイト(またはバッファページ)をメモリに読み込む必要はないと仮定します。 - 有用なデータが含まれていません。 ReadFileに次の100バイト(または100キロバイト以上)を読み込むことをお勧めしますか?SetFilePointer(file, 100, NULL, FILE_CURRENT)を呼び出して100バイトをスキップするのはいつもより速いでしょうか?

SetFilePointerを使用する方が一般的に高速な場合は、ランダムアクセスと順次オプションの違いがありますか?私は、現在キャッシュされているバッファ(およびOSがあなたのためにプリロードしているかもしれない将来のバッファ)を越えて前方を追求することができるので、前方を求めることはランダムアクセスの形になると思うだろうが、その場合Windowsは常に破棄するキャッシュされたバッファとディスクから再読み込み?バッファリロードをトリガーせずにシークできる最大量を見つける方法はありますか?

(私の仮説をテストするためにプロファイル作成とベンチマークを試みますが、私のコンピュータにはすべてNVMe SSDが搭載されています - 明らかにプラッタドライブでは非常に違いがあります)。

+0

'SetFilePointer'は、[' FILE_OBJECT']( 'https://msdn.microsoft.com/en-us/library/windows/hardware/ff545834(v=vs/) 'の' CurrentByteOffset'にのみ設定されています。 85).aspx)をI/Oマネージャーから取得します。ファイルシステムも呼び出されません。この呼び出しは、ファイルオープンモード、ディスクなどとは独立しています+これは絶対無意味な呼び出しです。読み取りまたは書き込み操作で常に直接オフセットを渡すことができます – RbMm

+0

あなたは間違った前提を設定しています: 'FILE_FLAG_RANDOM_ACCESS'も' FILE_FLAG_SEQUENTIAL_SCAN'も約束する。どちらも「ファイルキャッシュを最適化するためのヒントとして使用することができます」と記載されています。*何も実行しない場合や、最適化されたキャッシング戦略が一部のシステムで利用できない場合があります。 'SetFilePointer'がシーケンシャルアクセスを構成するかどうかにかかわらず、フラグが何もしないように準備する必要があります。 – IInspectable

+0

*または最適化されたキャッシング戦略が一部のシステムで利用できない可能性があります。* - これはWindowsのソフトウェアの一部であり、すべてのWindowsバージョンで利用できます。 create fileの 'FILE_SEQUENTIAL_ONLY'と' FILE_RANDOM_ACCESS'オプションはファイルオブジェクトの 'FO_SEQUENTIAL_ONLY'と' FO_RANDOM_ACCESS'フラグに変換されます。それは先読み戦略のためにどのように使われたのですか?(具体的な実装はバージョンごとに変更されました)[こちら](https://github.com/Zer0Mem0ry/ntoskrnl/tree/master/Cache)を見ることができます。これらはすべて、 'SetFilePointer'と共通するものはありません。 – RbMm

答えて

1

最初に約SetFilePointerである。

SetFilePointerZwSetInformationFileFilePositionInformationと内部的に呼びます。 I/Oマネージャーによってフルhandled - ファイルシステムは呼び出されません。この電話で行われたことはすべてCurrentByteOffsetFILE_OBJECTからsetまでです。

この呼び出しは、ファイルのバッファリングとキャッシュの戦略から独立しています。さらに - これは時間を無駄にする絶対無意味な呼び出しです - 私たちは常にReadFileまたはWriteFileを呼び出して直接オフセットを設定できます - OVERLAPPEDOffsetOffsetHighを見てください。 SetEndOfFile?が、はるかに優れた、効果的なコールZwSetInformationFileもちろんのFileEndOfFileInfoFileEndOfFileInformationまたはSetFileInformationByHandleSetEndOfFileと内部FileEndOfFileInformationZwSetInformationFileを呼び出し、それがFilePositionInformationZwQueryInformationFileを呼び出す前FILE_OBJECTからCurrentByteOffsetを読むために - あなたは単に場合にはカーネルに2-3不必要な余分な呼び出しを行いますSetEndOfFile)。 SetFilePointerへの電話が本当に必要な場合は存在しません。

ので、位置をファイル - I/Oマネージャで主に使用される唯一のソフトウェア変数(FILE_OBJECTCurrentByteOffset)がある - ファイルシステムは、必ずと読み出し/書き込み要求を取得明示的なオフセット - としてFastIoRead引数またはIO_STACK_LOCATION.Parameters.Read.ByteOffset にI 場合/ OマネージャはByteOffsetが存在しない、これはNtReadFile又はFILE_OBJECTCurrentByteOffsetからオフセット又は明示ByteOffset値から(ByteOffsetためNULLポインタ)を取得ためByteOffset場合はNULLポインタためReadFile使用NULLポインタ、それ以外の質問についてOVERLAPPED.Offset

へのポインタを使用する - センスシーケンシャルすべてのバイトを読み込むか、単に必要なオフセットから読み取る存在していますか?

場合には、我々は(FILE_NO_INTERMEDIATE_BUFFERING)キャッシュせずにファイルを開く - 私たちはとにかく - 私たちはReadFileWriteFileに渡さはキャッシュを使用した場合のセクタサイズ

の倍数でなければならないオフセット選択肢がありません実際に必要とされるバイトを読み取る前に、何らかの追加を読み込んだら(何も私たちに必要ではない)何も得られません。いずれの場合でも、ファイルシステムはディスクからこのバイトを読み取る必要があります。まだ読み取られていない場合は、別のバイトを読み取ってもこのプロセスが加速されません。少なくなりますので、ディスク(最も高価な操作)から直接読み取りのカウント - (最低でも部分的に)キャッシュを落ちる - FILE_FLAG_SEQUENTIAL_SCANキャッシュマネージャーと

は、オフセットシーケンシャルで完全な現在の要求と次の読み取りの必要性よりも、ディスクからより多くのセクタを読みます。しかし、このオフセットの前に特定のオフセットシーケンシャルリードバイトが必要なときは、このオフセットは何らかの方法で助けられません。このバイトを読む必要があります。

言い換えれば、ファイルから特定のバイト数 - これまでに別のバイトを読み込んだ場合、パフォーマンスが向上しません。わずかに減少する

したがって、あるオフセットで読み込みファイルが必要な場合は、このオフセットで読み込みます。 SetFilePointerを使用しないでください。明示的なオフセットを使用するOVERLAPPED

+0

* "効果的な" *と "効率的な" *は同じものではありません。 'ZwSetInformationFile'は、同じ操作を実行する他の呼び出しよりも効果的ではありません。 – IInspectable

+0

@IInspectable - 'ZwSetInformationFile'(' FilePositionInformation')は全く必要ありません – RbMm

+0

それは重要ではありません。ポイントは、あなたが(おそらく)*「効率的な」*を意味するときはいつでも*「効果的」*を使用し続けるということです。 – IInspectable