檔案IO操作開發筆記(二):使用Cpp的ofstream對磁碟檔案儲存進行效能測試及工具

21497936發表於2023-01-10

前言

  在做到個別專案對日誌要求較高,要求並行寫入的資料較多,儘管寫入資料的執行緒放在子執行緒,仍然會造成介面程式的假死(實際上Qt還是在跑,只是磁碟消耗超過瓶頸,造成假死(注意:控制檯還能看到列印輸出,linux則能看到列印輸出)。
  本篇升級了測試工具,並且測試了ofstream在USB3.0和M.2SSD上的寫入效能。

版本v1.1.0

  更新版本版本,新增了c++的ofstream寫入方式。
   在這裡插入圖片描述

測試工具v1.1.0下載地址

  請自行溯源搜尋,發不出

使用C++的ofstream測試結果

USB3.0行動硬碟測試結果

    在這裡插入圖片描述
     在這裡插入圖片描述

   所以,執行緒越開越多,在某一個閾值執行緒數(實際開啟操作的檔案數)會導致效能大幅下降,而且會持續有多個閾值類似的。

M.2主機板上SSD測試結果

     在這裡插入圖片描述
    在這裡插入圖片描述

使用C++的ofstream(用flush)測試結果

USB3.0行動硬碟測試結果

     在這裡插入圖片描述
     在這裡插入圖片描述

M.2主機板上SSD測試結果

   在這裡插入圖片描述
   在這裡插入圖片描述
  結論:這個明顯受到硬碟資料傳輸的影響。

關鍵程式碼

void FileIoTestManager::slot_optFileUseCppOfstream(int loopTime, int loopWrite, int dataSize, bool flush){
    QDir dir;
    QString dirPath = QString("%1/%2")
                            .arg(QApplication::applicationDirPath())
                            .arg(QDateTime::currentDateTime().toString("yyyy-MM-dd hh_mm_ss_zzz"));
    if(dir.mkpath(dirPath))
    {
        message(QString("建立資料夾成功: %1").arg(dirPath));
    }else{
        message(QString("建立資料夾失敗: %1").arg(dirPath));
    }
    // 生成資料
    message(QString("生成測試資料,資料長度: %1").arg(dataSize));
    QByteArray byteArray;
    byteArray.append(dataSize, 0xFF);
    message(QString("==========================測試開始=============================="));
    double totalTime = 0;           // 總計時間
    double fileTotalTime = 0;       // 操作單個檔案總時間
    double writeFileTime = 0;       // 單個檔案單詞寫入時間
    totalTime = QDateTime::currentDateTime().toMSecsSinceEpoch() * 1.0f;
    for(int loopIndex = 0; loopIndex < loopTime; loopIndex++)
    {
        QString filePath = QString("%1/%2_%3")
                .arg(dirPath)
                .arg(QDateTime::currentDateTime().toString("hh_mm_ss_zzz"))
                .arg(loopIndex, 6, 10, QChar('0'));
        std::ofstream outFile;
        outFile.open(filePath.toUtf8().constData());
        writeFileTime = QDateTime::currentDateTime().toMSecsSinceEpoch();
        for(int writeIndex = 0; writeIndex < loopWrite; writeIndex++)
        {//            message(QString("  第%1次寫入檔案,寫入長度%2位元組").arg(writeIndex + 1).arg(dataSize));
            outFile << byteArray.constData();
            if(flush)
            {
                outFile.flush();
            }
            if(_stop)
            {
                outFile.close();
                message(QString("==========================測試手動停止==========================="));
                _stop = false;
                emit signal_finished();
                return;
            }
        }
        writeFileTime = QDateTime::currentDateTime().toMSecsSinceEpoch() - writeFileTime;
        writeFileTime = writeFileTime / loopWrite;
        message(QString("每次寫入資料平均耗時(不包含開啟關閉檔案): %1ms").arg(writeFileTime));//        message(QString(" 第%1次關閉檔案").arg(loopIndex + 1));
        outFile.close();
    }
    message(QString("==========================測試結果=============================="));
    totalTime = QDateTime::currentDateTime().toMSecsSinceEpoch() - totalTime;
    fileTotalTime = totalTime * 1.0f / loopTime;
    message(QString("操作建立檔案次數: %1, 單個檔案迴圈寫入次數: %2, 每次寫入固定資料長度: %3, %4")
            .arg(loopTime)
            .arg(loopWrite)
            .arg(dataSize)
            .arg(flush ? "每次使用flush" : "不使用flush"));
    message(QString("總耗時: %1ms").arg(totalTime));
    message(QString("單個檔案迴圈寫入平均總耗時(包括開啟關閉檔案): %1ms").arg(fileTotalTime));
    message(QString("每次寫入資料平均耗時(包括開啟關閉檔案: %1ms").arg(fileTotalTime * 1.0f / loopWrite));
    message(QString("==========================測試結束=============================="));
    emit signal_finished();
    return;}

工程模板v1.1.0

   在這裡插入圖片描述

後續

  會持續補充測試其他方式,ofstream本次測試比QFile的效能還差一些。


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/70010283/viewspace-2931538/,如需轉載,請註明出處,否則將追究法律責任。

相關文章