NMVe SSD Fedora スループットテストが高すぎます。

NMVe SSD Fedora スループットテストが高すぎます。

NVMeプロトコルを使用してSamsung 950 Pro SSDカードのスループットをテストしています。現在のテスト方法は、パーティションにファイルシステムをマウントし、Xバイトサイズのファイルをファイルシステムに書き込むことです。これを実行するのにかかる時間を記録することで、バイト/秒を計算できます。

私のテストには、より高いレベルのforループで指定されているように、一度に1ブロックずつ可変ブロックサイズでXバイトを書き込むwhileループがあります。これに加えて、N個のアプリケーションを並列に実行し、それぞれSSDの他のパーティションに書き込む別のループがあります。

現在、Samsung 950 Proデータシートで指定されている理論上の最大転送速度よりわずかに速い読み書き速度が表示されます。 Samsungは、950 Proの最大順次書き込み速度を1.5 GB / s、最大順次読み取り速度を2.5 GB / sと指定します。

https://www.samsung.com/us/computing/memory-storage/solid-state-drives/ssd-950-pro-nvme-512gb-mz-v5p512bw/#specs

実行するアプリケーションの数とチャンクサイズを繰り返すbashスクリプトの主な機能は次のとおりです。

appInstances=1
while [ $appInstances -le 4 ]
do
    for blocksize in 4096 32768 131072 524288 1048576 67108864 268435456 1073741824
    do
       # Run the test
       datetime
       echo "[$datetime_v]: Test blocksize: $blocksize appInstances: $appInstances"
       run_single_perf_test $blocksize

    done

    appInstances=`expr $appInstances \* 2`

done
exit 0

run_perf_test の書き込み部分です。このセクションの後には、書き込みスループット速度テストを含む読み取りセクションがあります。テストの間にSSD内のすべてのパーティションをアンマウントして再マウントして、すべてのNVMeトランザクションが完了し、書き込み操作のキャッシュが読み取り操作のスループット測定に影響を与えないようにしました。

instCnt=1
childpids=""
while [ $instCnt -le $appInstances ]
do
fsrw -w $blocksize /fsmnt/fs${instCnt}/usernumber1/j.j &

# Save the process ID
childpids="$childpids $!"

# Increment the instace count.
instCnt=`expr $instCnt + 1`
done

fsrw は、最初の引数 "-r" または "-w"、2 番目の引数 (ブロックサイズ)、3 番目の引数 (SSD パーティションのファイル名) に基づいて文字列を作成し、SSD でファイルを開こうとする C++ アプリケーションです。 。パーティションを分割して文字列を書き込みます。これは、最初の引数として「-w」が指定されたときに呼び出される書き込み関数の実装です。

/*! \fn perform_writeop()
 *  \brief The function returns true when the write operation completes successfully. 
 *
 *  The function will run until the read is complete or a 35 second timeout is reached.
 *  It will record the time before the write begins, then also record the time afterward.
 *  If the timeout is reached this should be about 35 seconds
 */
bool perform_writeop ()
{
    // File descriptor.
    int32_t fd = -1;

    // Function status.
    bool status = false;

    // Zero writes
    int zero_writes = 0;

    // Buffer fill index.
    int32_t bfidx = 0;

    // Character value.
    int8_t cv = 33;

    // Fill the buffer with printable characters.
    for (; bfidx < blocksize; bfidx++, cv++)
    {
        // Verify the character value is in range.
        if (cv >= 127)
        {
            cv = 33;
        }
        else
        {
            // Add to the buffer.
            buf[bfidx] = cv;
        }
    }

    // Open the file.
    fd = open (fname.c_str (), O_WRONLY | O_CREAT, 0660);

    // Verify the file has been opened.
    if (fd == -1)
    {
        cout << get_datetime_string() << "Write open of " << fname 
        << " failed.  Errno: " << errno << endl;
    }
    else
    {
        // Total bytes written.
        uint64_t written = 0;

        // Notify the start of the test.
        cout << get_datetime_string() << "Write test started" << endl;

        // Elapsed time.
        struct timeval tv = { 0 };
        get_elapsed_time (&tv);
        struct timeval write_tv = tv;

        // Run until it is time for the test to stop.
        while (written < READ_LIMIT && zero_writes < 10)
        {
            ssize_t writesize = write (fd, &buf[0], blocksize);
            if (writesize == -1)
            {
                cout << get_datetime_string << "Write failure.  Errno: " << errno << endl;
                zero_writes = 10;
            }
            else if (0 == writesize)
            {
                cout << get_datetime_string() << "Zero bytes written" << endl;
                zero_writes++;
            }
            else
            {
                written += writesize;
            }
        }

    string flush_command = "nvme flush /dev/nvme0n1p";
    flush_command += fname[9];
    system(flush_command.c_str());


    // Get the elapsed time.
    get_elapsed_time (&write_tv);

    // Report the number of bytes written.
    cout << get_datetime_string() << "Write " << written << " bytes in "
     << write_tv.tv_sec << "." << write_tv.tv_usec
     << " seconds" << endl;

    // Close the file.
    close (fd);

    // Get the elapsed time.
    get_elapsed_time (&tv);

    // Report the number of bytes read.
    cout << get_datetime_string() << "Write closed.  " << written 
    << " Bytes written in " << tv.tv_sec << "." << tv.tv_usec 
    << " seconds" << endl;

    // Report the number of bytes per second.
    cout << get_datetime_string() << "Bytes per second " 
    << bytes_per_second (&tv, written) << endl;

    // Report the cache flush time.
    struct timeval flush_tv = { 0 };
    timersub (&tv, &write_tv, &flush_tv);
    cout << get_datetime_string() << "System cache flush completed in " 
    << flush_tv.tv_sec << "." << flush_tv.tv_usec << "seconds" << endl;

    // Set the function return status when all write operations have
    // been successful.
    if (zero_writes < 10)
    {
      status = true;
    }
  }
  return status;
}

私が取得するデータは次のとおりです。 ここに画像の説明を入力してください。

この数値はSamsung 950 Proの理論上最大スループットに近いですが、いくつかの数値は高すぎて気になります。私が得た数値がSamsung 950 Proの理論的最大スループットより高いのはなぜですか?

ベストアンサー1

おすすめ記事