优化.txt文件的创建速度

时间:2018-12-26 21:37:32

标签: c++ file optimization fstream ofstream

我编写了以下简单的测试代码,该代码在子目录中创建10000个空的.txt文件。

#include <iostream>
#include <time.h>
#include <string>
#include <fstream>

void CreateFiles()
{
    int i = 1;
    while (i <= 10000) {
        int filename = i;
        std::string string_i = std::to_string(i);
        std::string file_dir = ".\\results\\"+string_i+".txt";
        std::ofstream outfile(file_dir);
        i++;
    }
}

int main()
{
    clock_t tStart1 = clock();
    CreateFiles();
    printf("\nHow long it took to make files: %.2fs\n", (double)(clock() - tStart1)/CLOCKS_PER_SEC);
    std::cin.get();
    return 0;
}

一切正常。所有10000个.txt文件都在~3.55秒内创建。 (使用我的PC)

问题1:忽略了从intstd::string的转换,等等,我有什么可以优化的程序来更快地创建文件吗?我特别是指std::ofstream outfile的用法-也许使用其他方法会更快一些?

无论如何,与以下情况相比,~3,55秒是令人满意的:

我已经修改了该函数,所以现在它还会用一些随机i整数数据和一些常量文本填充.txt文件:

void CreateFiles()
{
    int i = 1;
    while (i <= 10000) {
        int filename = i;
        std::string string_i = std::to_string(i);
        std::string file_dir = ".\\results\\"+string_i+".txt";
        std::ofstream outfile(file_dir);

        // Here is the part where I am filling the .txt with some data
        outfile << i << " some " << i << " constant " << i << " text " << i << " . . . " 
        << i << " --more text-- " << i << " --even more-- " << i;
        i++;
    }
}

现在,所有操作(创建.txt文件并用短数据填充)都在... ~37秒内执行。那是巨大的差异。而且只有10,000个文件。

问题2:我在这里可以优化什么?也许有一些替代方法可以更快地填充.txt文件。还是我忘记了一些很明显的事情,这些事情会减慢整个过程?

或者,也许我有点夸张,~37秒似乎是正常的并且已经优化了?

感谢您分享见解!

1 个答案:

答案 0 :(得分:4)

文件的创建速度取决于硬件,更快的驱动器可以更快地创建文件。

我在ARM处理器上运行您的代码(在使用termux的手机上使用Snapdragon 636)证明了这一点,现在手机的闪存非常快到I / O。因此,大多数情况下,运行时间少于3秒,而5秒则是。由于驱动器必须处理多进程读写,因此预计会出现这种变化。 您报告说硬件花费了47秒。 因此,您可以放心地得出结论,I / O速度很大程度上取决于硬件。


我一直想对您的代码做一些优化,所以我使用了两种不同的方法。

  • 为I / O使用C副本

  • 使用C ++,但一次性编写大块代码。

我在手机上运行了模拟。我运行了50次,结果如下。

  • C使用fprintf最快可以平均花费2.73928秒将单词写在10000个文本文件上

  • 一次完成整行的C ++编写花费了2.7899秒。我使用sprintf将完整的行放入char []中,然后在流上使用<<操作符编写。

  • C ++普通(您的代码)花费了2.8752秒

这种现象是可以预期的,分块写入速度更快。阅读this答案以了解原因。毫无疑问,C是最快的。

您可能会在这里注意到,差异并不明显,但是如果您使用的是I / O较慢的硬件,那么这会变得很重要。


这是我用于仿真的代码。您可以自己进行测试,但请确保使用您自己的命令替换std::system参数(对于Windows,则不同)。

#include <iostream>
#include <time.h>
#include <string>
#include <fstream>
#include <stdio.h>

void CreateFiles()
{
    int i = 1;
    while (i <= 10000) {
       // int filename = i;
        std::string string_i = std::to_string(i);
        std::string file_dir = "./results/"+string_i+".txt";
        std::ofstream outfile(file_dir);

        // Here is the part where I am filling the .txt with some data
        outfile << i << " some " << i << " constant " << i << " text " << i << " . . . " 
        << i << " --more text-- " << i << " --even more-- " << i;
        i++;
    }
}

void CreateFilesOneGo(){
    int i = 1;
    while(i<=10000){
        std::string string_i = std::to_string(i);
        std::string file_dir = "./results3/" + string_i + ".txt";
        char buffer[256];
        sprintf(buffer,"%d some %d constant %d text %d . . . %d --more text-- %d --even more-- %d",i,i,i,i,i,i,i);
        std::ofstream outfile(file_dir);
        outfile << buffer;
        i++;
    }
}

void CreateFilesFast(){
    int i = 1;
    while(i<=10000){
    // int filename = i;
    std::string string_i = std::to_string(i);
    std::string file_dir = "./results2/"+string_i+".txt";
    FILE *f = fopen(file_dir.c_str(), "w");
    fprintf(f,"%d some %d constant %d text %d . . . %d --more text-- %d --even more-- %d",i,i,i,i,i,i,i);
    fclose(f);
    i++;
    }
}

int main()
{
    double normal = 0, one_go = 0, c = 0;
    for (int u=0;u<50;u++){
        std::system("mkdir results results2 results3");

        clock_t tStart1 = clock();
        CreateFiles();
        //printf("\nNormal : How long it took to make files: %.2fs\n", (double)(clock() - tStart1)/CLOCKS_PER_SEC);
        normal+=(double)(clock() - tStart1)/CLOCKS_PER_SEC;

        tStart1 = clock();
        CreateFilesFast();
        //printf("\nIn C : How long it took to make files: %.2fs\n", (double)(clock() - tStart1)/CLOCKS_PER_SEC);
        c+=(double)(clock() - tStart1)/CLOCKS_PER_SEC;

        tStart1 = clock();
        CreateFilesOneGo();
        //printf("\nOne Go : How long it took to make files: %.2fs\n", (double)(clock() - tStart1)/CLOCKS_PER_SEC);
        one_go+=(double)(clock() - tStart1)/CLOCKS_PER_SEC;

        std::system("rm -rf results results2 results3");
        std::cout<<"Completed "<<u+1<<"\n";
    }

    std::cout<<"C on average took : "<<c/50<<"\n";
    std::cout<<"Normal on average took : "<<normal/50<<"\n";
    std::cout<<"One Go C++ took : "<<one_go/50<<"\n";

    return 0;
}

我也使用clang-7.0作为编译器。

如果您有其他方法,请告诉我,我也会进行测试。如果您发现错误,请告诉我,我会尽快纠正。