优化 .txt 文件创建速度

Optimizing .txt files creation speed

我编写了以下简单的测试代码,它在一个子目录中创建了 10 000 个空的 .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;
}

一切正常。所有 10 000 个 .txt 文件都是在 ~3.55 秒内创建的。 (使用我的电脑)

问题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 秒似乎正常且经过优化?

感谢分享您的见解!

创建文件的速度取决于硬件,驱动器越快,您创建文件的速度就越快。

我 运行 你的代码在 ARM 处理器上(Snapdragon 636,在移动 phone 上使用 termux)这一事实可以看出这一点,现在 phone 手机的闪存速度非常快 I/O。所以 它 运行 大部分时间不到 3 秒,有时 5 秒 。这种变化是预期的,因为驱动器必须处理多进程读写。 您报告说您的硬件花费了 47 秒。 因此您可以放心地得出结论,I/O 速度在很大程度上取决于硬件。


None 我想对您的代码做一些优化的次数越少,我使用了 2 种不同的方法。

  • 为 I/O

    使用 C 对应物
  • 使用C++,一次写成一个块。

我运行在我的phone上模拟。我 运行 它 50 次,这是结果。

  • C 使用 fprintf

    在 10000 个文本文件上写字平均耗时 2.73928 秒最快
  • C++一次写完整行用了2.7899秒。我使用 sprintf 将完整的行放入 char[] 然后使用 << operator on ofstream.

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

这种行为是预料之中的,分块写入速度更快。阅读 个答案以了解原因。 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 作为编译器。

如果你有任何其他方法让我知道,我也会测试它。如果您发现错误请告诉我,我会尽快更正。