C#でランダムファイルの作成方法と読み込み速度計測ベンチマークテスト

コンピュータ

SSDを判定方法調べましたが、良い方法が見つからなかったので、読み取り速度を計測してみました。

using System;
using System.Diagnostics;
using System.IO;
using System.Threading.Tasks.Dataflow;

class Program
{
    const string FilePath = "test_random.dat";
    const int FileSizeMB = 100; // 作成するファイルサイズ(MB)
    const int BufferSize = 4 * 1024 * 1024; // 4MBのバッファで読み込み

    static void Main()
    {
        var sw = Stopwatch.StartNew();

        sw.Restart();
        DriveInfo[] drives = DriveInfo.GetDrives();
        foreach (DriveInfo drive in drives)
        {
            if (!drive.IsReady) continue;
            string path = Path.Join(drive.Name, FilePath);
            if (drive.Name == "C:\\")
            {
                path = Path.Join(Path.GetTempPath(), FilePath);
            }

            //Console.WriteLine("ランダムファイルを作成中...");
            CreateRandomFile(path, FileSizeMB);
            //Console.WriteLine("完了.");

            //Console.WriteLine("読み込み速度を計測中...");
            double result = BenchmarkRead(path);

            Console.WriteLine($"{Path.GetPathRoot(path)}  速度: {result:F2} MB/s");

            // 削除
            File.Delete(path);
        }
        sw.Stop();
        Console.WriteLine($"所要時間:{sw.ElapsedMilliseconds}ms");
    }

    static void CreateRandomFile(string path, int sizeMB)
    {
        var rand = new Random();
        byte[] buffer = new byte[BufferSize];
        using var fs = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.None);

        long bytesToWrite = sizeMB * 1024L * 1024L;
        while (bytesToWrite > 0)
        {
            rand.NextBytes(buffer);
            int writeSize = (int)Math.Min(buffer.Length, bytesToWrite);
            fs.Write(buffer, 0, writeSize);
            bytesToWrite -= writeSize;
        }
    }

    static double BenchmarkRead(string path)
    {
        byte[] buffer = new byte[BufferSize];
        Stopwatch sw = Stopwatch.StartNew();
        long totalBytesRead = 0;

        using var fs = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read);
        int bytesRead;
        while ((bytesRead = fs.Read(buffer, 0, buffer.Length)) > 0)
        {
            totalBytesRead += bytesRead;
        }

        sw.Stop();

        double seconds = sw.Elapsed.TotalSeconds;
        double mbRead = totalBytesRead / 1024.0 / 1024.0;
        double speedMBps = mbRead / seconds;

        //Console.WriteLine($"読み込み完了: {mbRead:F2} MB を {seconds:F2} 秒で読み込み。速度: {speedMBps:F2} MB/s");
        return speedMBps;
    }
}

実行結果

C:\  速度: 5451.58 MB/s
D:\  速度: 5028.54 MB/s
E:\  速度: 5100.66 MB/s
F:\  速度: 5089.60 MB/s
G:\  速度: 5353.86 MB/s
X:\  速度: 230.20 MB/s
Y:\  速度: 223.41 MB/s
Z:\  速度: 227.88 MB/s
所要時間:3908ms

C~GドライブまでがSSD
X~ZドライブがNAS

SSDの速度がディスクキャッシュのためか、かなり速い速度が出ているドライブもありますが、とりあえず500MBあたりをしきい値にNASとSSDとの判定には使えそう。

計測にかかる時間が4秒程(NASが遅い)ですので、実行するとしたらアプリの初期化のタイミングが良さそう。
できれば、初回だけすべてのドライブを計測し結果を記録、次回以降はドライブチェックして変化があった場合のみの計測するコードにしたい。

コメント