文件IO操作开发笔记(二):使用Cpp的ofstream对磁盘文件存储进行性能测试以及测试工具

简介: 在做到个别项目对日志要求较高,要求并行写入的数据较多,尽管写入数据的线程放在子线程,仍然会造成界面程序的假死(实际上Qt还是在跑,只是磁盘消耗超过瓶颈,造成假死(注意:控制台还能看到打印输出,linux则能看到打印输出)。本篇升级了测试工具,并且测试了ofstream在USB3.0和M.2SSD上的写入性能。

前言

  在做到个别项目对日志要求较高,要求并行写入的数据较多,尽管写入数据的线程放在子线程,仍然会造成界面程序的假死(实际上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的性能还差一些。

相关实践学习
通过性能测试PTS对云服务器ECS进行规格选择与性能压测
本文为您介绍如何利用性能测试PTS对云服务器ECS进行规格选择与性能压测。
相关文章
|
5月前
|
存储 数据可视化 测试技术
一个测试工程师的实战笔记:我是如何在Postman和Apipost之间做出选择的?
优秀的API测试工具应该具备: 分层设计:既有可视化操作,也开放代码层深度定制 场景感知:自动识别加密需求推荐处理方案 协议包容:不强迫开发者为了不同协议切换工具 数据主权:允许自主选择数据存储位置
134 7
|
9月前
|
机器学习/深度学习 弹性计算 自然语言处理
前端大模型应用笔记(二):最新llama3.2小参数版本1B的古董机测试 - 支持128K上下文,表现优异,和移动端更配
llama3.1支持128K上下文,6万字+输入,适用于多种场景。模型能力超出预期,但处理中文时需加中英翻译。测试显示,其英文支持较好,中文则需改进。llama3.2 1B参数量小,适合移动端和资源受限环境,可在阿里云2vCPU和4G ECS上运行。
403 1
|
9月前
|
JSON 算法 数据可视化
测试专项笔记(一): 通过算法能力接口返回的检测结果完成相关指标的计算(目标检测)
这篇文章是关于如何通过算法接口返回的目标检测结果来计算性能指标的笔记。它涵盖了任务描述、指标分析(包括TP、FP、FN、TN、精准率和召回率),接口处理,数据集处理,以及如何使用实用工具进行文件操作和数据可视化。文章还提供了一些Python代码示例,用于处理图像文件、转换数据格式以及计算目标检测的性能指标。
182 0
测试专项笔记(一): 通过算法能力接口返回的检测结果完成相关指标的计算(目标检测)
|
9月前
|
机器学习/深度学习 并行计算 数据可视化
目标分类笔记(二): 利用PaddleClas的框架来完成多标签分类任务(从数据准备到训练测试部署的完整流程)
这篇文章介绍了如何使用PaddleClas框架完成多标签分类任务,包括数据准备、环境搭建、模型训练、预测、评估等完整流程。
594 0
目标分类笔记(二): 利用PaddleClas的框架来完成多标签分类任务(从数据准备到训练测试部署的完整流程)
|
9月前
|
机器学习/深度学习 JSON 算法
语义分割笔记(二):DeepLab V3对图像进行分割(自定义数据集从零到一进行训练、验证和测试)
本文介绍了DeepLab V3在语义分割中的应用,包括数据集准备、模型训练、测试和评估,提供了代码和资源链接。
1767 0
语义分割笔记(二):DeepLab V3对图像进行分割(自定义数据集从零到一进行训练、验证和测试)
|
9月前
|
机器学习/深度学习 数据采集 算法
目标分类笔记(一): 利用包含多个网络多种训练策略的框架来完成多目标分类任务(从数据准备到训练测试部署的完整流程)
这篇博客文章介绍了如何使用包含多个网络和多种训练策略的框架来完成多目标分类任务,涵盖了从数据准备到训练、测试和部署的完整流程,并提供了相关代码和配置文件。
294 0
目标分类笔记(一): 利用包含多个网络多种训练策略的框架来完成多目标分类任务(从数据准备到训练测试部署的完整流程)
|
9月前
|
机器学习/深度学习 JSON 算法
实例分割笔记(一): 使用YOLOv5-Seg对图像进行分割检测完整版(从自定义数据集到测试验证的完整流程)
本文详细介绍了使用YOLOv5-Seg模型进行图像分割的完整流程,包括图像分割的基础知识、YOLOv5-Seg模型的特点、环境搭建、数据集准备、模型训练、验证、测试以及评价指标。通过实例代码,指导读者从自定义数据集开始,直至模型的测试验证,适合深度学习领域的研究者和开发者参考。
2885 3
实例分割笔记(一): 使用YOLOv5-Seg对图像进行分割检测完整版(从自定义数据集到测试验证的完整流程)
|
9月前
|
测试技术 数据安全/隐私保护 Python
自动化测试项目实战笔记(四):测试用户登录(账号密码错误,成功,出现弹框等情况)
本文介绍了使用Selenium进行自动化测试时如何测试用户登录的不同情况,包括账号密码错误、登录成功以及处理登录时出现的弹框,并提供了相应的Python代码实现。
478 0
自动化测试项目实战笔记(四):测试用户登录(账号密码错误,成功,出现弹框等情况)
|
9月前
|
测试技术
自动化测试项目实战笔记(三):测试用户注册(验证码错误,成功,出现弹框时处理)
本文是关于自动化测试项目实战笔记,主要介绍了如何测试用户注册功能,包括验证码错误、注册成功以及弹框处理的测试步骤和代码实现。
309 2
自动化测试项目实战笔记(三):测试用户注册(验证码错误,成功,出现弹框时处理)
|
9月前
|
人工智能 算法 测试技术
自动化测试项目实战笔记(二):解决验证码识别问题
这篇文章介绍了三种自动化测试中验证码识别的方法:使用Python的pytesseract和PIL模块、利用第三方API如万维易源,以及使用开源的ddddocr库,还提到了一些注意事项,比如如何获取验证码区域的截图。
254 2