优化 .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:忽略从int
到std::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 作为编译器。
如果你有任何其他方法让我知道,我也会测试它。如果您发现错误请告诉我,我会尽快更正。
我编写了以下简单的测试代码,它在一个子目录中创建了 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:忽略从int
到std::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 秒
这种行为是预料之中的,分块写入速度更快。阅读
您可能会注意到这里的差异并不那么显着,但如果您使用的硬件速度较慢 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 作为编译器。
如果你有任何其他方法让我知道,我也会测试它。如果您发现错误请告诉我,我会尽快更正。