5

私はかなり簡単なテストを行っています:

  1. サイズが 6Gb 程度のランダムなバイナリ情報を含む大きなファイルを用意する
  2. アルゴリズムは「SeekCount」の繰り返しのループを作成します
  3. 各繰り返しでは、次のことを行っています。
    • ファイルサイズの範囲内でランダムなオフセットを計算します
    • そのオフセットをシークします
    • データの小さなブロックを読み取ります

C#:

    public static void Test()
    {
        string fileName = @"c:\Test\big_data.dat";
        int NumberOfSeeks = 1000;
        int MaxNumberOfBytes = 1;
        long fileLength = new FileInfo(fileName).Length;
        FileStream stream = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Read, 65536, FileOptions.RandomAccess);
        Console.WriteLine("Processing file \"{0}\"", fileName);
        Random random = new Random();
        DateTime start = DateTime.Now;
        byte[] byteArray = new byte[MaxNumberOfBytes];

        for (int index = 0; index < NumberOfSeeks; ++index)
        {
            long offset = (long)(random.NextDouble() * (fileLength - MaxNumberOfBytes - 2));
            stream.Seek(offset, SeekOrigin.Begin);
            stream.Read(byteArray, 0, MaxNumberOfBytes);
        }

        Console.WriteLine(
            "Total processing time time {0} ms, speed {1} seeks/sec\r\n",
            DateTime.Now.Subtract(start).TotalMilliseconds, NumberOfSeeks / (DateTime.Now.Subtract(start).TotalMilliseconds / 1000.0));

        stream.Close();
    }

次に、 C++で同じテストを行います。

void test()
{
     FILE* file = fopen("c:\\Test\\big_data.dat", "rb");

char buf = 0;
__int64 fileSize = 6216672671;//ftell(file);
__int64 pos;

DWORD dwStart = GetTickCount();
for (int i = 0; i < kTimes; ++i)
{
    pos = (rand() % 100) * 0.01 * fileSize;
    _fseeki64(file, pos, SEEK_SET);
    fread((void*)&buf, 1 , 1,file);
}
DWORD dwEnd = GetTickCount() - dwStart;
printf(" - Raw Reading: %d times reading took %d ticks, e.g %d sec. Speed: %d items/sec\n", kTimes, dwEnd, dwEnd / CLOCKS_PER_SEC, kTimes / (dwEnd / CLOCKS_PER_SEC));
fclose(file);
}

実行時間:

  1. C#: 100-200 読み取り/秒
  2. C++: 250,000 読み取り/秒 (250,000)

質問:ファイルの読み取りなどの些細な操作で、C++ が C# よりも何千倍も高速なのはなぜですか?

追加情報:

  1. ストリーム バッファで遊んで、同じサイズ (4Kb) に設定しました
  2. ディスクはデフラグされています (0% のフラグメンテーション)
  3. OS 構成: Windows 7、NTFS、最新の 500Gb HDD (記憶が正しければ WD)、8 GB RAM (ほとんど使用されていませんが)、4 コア CPU (使用率はほぼゼロ)
4

1 に答える 1

6

テストの C++ バージョンにはエラーがあります。ランダム オフセットの計算が制限されていたため、シークが短距離でのみ行われたため、C++ の結果がより良く見えました。

オフセットを計算するための正しいコードは、@MooingDuck によって提案されました。

rand()/double(RAND_MAX)*ファイルサイズ

その変更により、パフォーマンスは C++ と C# の両方で同等になり、約 200 読み取り/秒になります。

貢献してくれてありがとう。

于 2013-02-20T17:53:23.553 に答える