0

win32 I/Oのパフォーマンスに問題があります。OpenFile/WriteFileを使用して適切な書き込み速度を達成しようとしています。リソースモニター(Windowsに付属)を使用して、次のコードの書き込み速度を測定したところ、2MB/秒で書き込みが行われていることがわかりました...

HANDLE hFile = INVALID_HANDLE_VALUE;
hFile = CreateFile(
    L"test",
    (GENERIC_READ | GENERIC_WRITE),
    FILE_SHARE_READ,
    NULL,
    OPEN_ALWAYS,
    (FILE_ATTRIBUTE_NORMAL |
    FILE_FLAG_WRITE_THROUGH |
    FILE_FLAG_NO_BUFFERING),
    NULL);
if (hFile != INVALID_HANDLE_VALUE)
{
    //OK
    unsigned long bytesWritten = 0;
    unsigned long* Buffer = (unsigned long*)malloc(4096*sizeof(unsigned long));
    ZeroMemory(Buffer, 4096); //thanks to 'bash.d'
    while (true)
    {
        /*the infinite loop is intentional
          because I wanted to see if the writing speed of 2MB/sec
          was right */
        WriteFile(hFile,
            Buffer,
            4096,
            &bytesWritten,
            NULL);
        if (bytesWritten <= 0)
        {
            break;
        }
    }
}

以下で試してみましたが、同じです...

hFile = CreateFile(
    L"test",
    (GENERIC_READ | GENERIC_WRITE),
    FILE_SHARE_READ,
    NULL,
    OPEN_ALWAYS,
    (FILE_ATTRIBUTE_NORMAL);

私は何を間違っていますか(書き込み速度について)?どうすれば書き込み速度を向上させることができますか?ありがとう、私の英語をごめんなさい

編集:私はローカルディスクに書いています

4

2 に答える 2

0
  1. 完了ポートにバインドされた非同期 IO を使用する
  2. SetFileValidDataを使用してファイルを事前に拡張する
  3. でハンドルを開きますFILE_FLAG_NO_BUFFERING | FILE_FLAG_WRITE_THROUGH

コンシューマー グレードのドライブ (5400RPM であっても) は、最大 130MB/秒 (シングル スピンドル、RAID なし) の書き込みが可能です。他の IO が同時に発生することはありません (頭の動きはありません)。

例については、 https://github.com/rusanu/writing-a-binary-file-in-c-very-fastを参照してください。

于 2013-02-20T11:31:27.440 に答える
0

これは非常に興味深く、私が抱えている問題に似ており、Windows Server 2003 SP2 64 ビット (RAID ではなく単一のハード ドライブ) を搭載した 2 台の異なるサーバーで再現できます。単純に 36 バイトの WriteFile() を実行し、次にループで 99964 バイトを実行すると、同様の動作が生成されます (1 回の書き込みと、Windows の他のバージョンでも同じであると推測しています。これは、私がたまたま使用していたものです)。 . CPU 使用率は最初は非常に低く、その後徐々に増加します。あるサーバーでは、テストでは約 175GB で約 50% の CPU 使用率でした (その約 95% はカーネル時間です。私のプログラムでは 60%、「システム」では 40% です)。 )。

テストのパフォーマンスを得るために非同期 IO を試すこともできます。つまり、FILE_FLAG_OVERLAPPED でファイルを開き、WriteFile の LPOVERLAPPED 引数を使用しています。FILE_FLAG_NO_BUFFERING を使用すると、パフォーマンスが向上する場合とされない場合があります。確認するには、テストする必要があります。

FILE_FLAG_NO_BUFFERING を使用すると、通常、速度が安定し、ストリーミング動作が向上します。また、ディスク キャッシュが不要なデータで汚染されるのを回避できますが、全体的に必ずしも高速であるとは限りません。

また、テストして、IO の各ブロックに最適なサイズを確認する必要があります。私の経験では、一度に 4k のファイルをコピーする場合と、一度に 1Mb のファイルをコピーする場合では、パフォーマンスに大きな違いがあります。

これに関する私の過去のテスト (数年前) では、約 64kB 未満のブロック サイズはオーバーヘッドが支配的であり、約 512KB までのより大きなブロック サイズで合計スループットが向上し続けることがわかりました。今日のドライブで、最大のスループットを得るために 1MB を超えるブロック サイズを使用する必要があったとしても、私は驚かないでしょう。

現在使用している数値は適切に見えますが、最適ではない可能性があります。また、FILE_FLAG_WRITE_THROUGH がオンディスク キャッシュの使用を妨げているため、かなりのパフォーマンスが犠牲になることは確かです。

以下のことを試す価値があるでしょう...

1) FILE_FLAG_SEQUENTIAL_SCAN フラグを有効にする

2) デバイス マネージャーの「ディスク ポリシー」で「高度なパフォーマンスを有効にする」

3) ディスク チャンク サイズを 64 KB から 4096 に変更 ...

4) FILE_FLAG_NO_BUFFERING を試す

于 2013-02-20T11:06:25.697 に答える