我一直在尝试尽可能快地写入文件数据。
由于某种原因,fstream比fopen快。
我听说C的文件I / O更快(这很有意义)
<fstream>
包括<stdio.h>
,但我无法让fopen这么快地执行。
注意(旧问题):
还意识到fstream.put(char)比fstream << char
更快
(否则,如果缓冲区<〜256,则fopen比fstream快)
这是我的测试
#include <iostream>
#include <fstream>
#include <ctime>
int filesize; // total bytes (individually "put" in buffered stream)
int buffsize; // buffer size
void writeCPP(){
std::ofstream file;
char buffer[buffsize]; file.rdbuf()->pubsetbuf(buffer,buffsize); // set buffer (before opening)
file.open("test.txt",std::ios::binary); // open file
for(int i=0; i<filesize; i++) file.put('a'); // write bytes
file.close(); // close
}
void writeC(){
FILE* file=fopen("test.txt","wb"); // open file
char buffer[buffsize]; setvbuf(file,buffer,_IOFBF,buffsize); // set buffer
for(int i=0; i<filesize; i++) fputc('a',file); // write bytes
fclose(file); // close
}
#define getTime() double(clock())/CLOCKS_PER_SEC // good enough
double start;
void test(int s){ // C++ vs C (same filesize / buffsize)
buffsize=s;
std::cout<<" buffer: "<<buffsize<<"\t"<<std::flush;
start=getTime();
writeCPP();
std::cout<<" C++: "<<getTime()-start<<",\t"<<std::flush;
start=getTime();
writeC();
std::cout<<" C: "<<getTime()-start<<std::endl;
}
#define MB (1024*1024)
int main(){
filesize=10*MB;
std::cout<<"size: 10 MB"<<std::endl;
// C++ fstream faster
test(64); // C++ 0.86 < C 1.11 (1.29x faster)
test(128); // C++ 0.44 < C 0.79 (1.80x faster) (+0.51x)
test(256); // C++ 0.27 < C 0.63 (2.33x faster) (+0.53x)
test(512); // C++ 0.19 < C 0.56 (2.94x faster) (+0.61x)
test(1024); // C++ 0.15 < C 0.52 (3.46x faster) (+0.52x)
test(2048); // C++ 0.14 < C 0.51 (3.64x faster) (+0.18x)
test(4096); // C++ 0.12 < C 0.49 (4.08x faster) (+0.44x)
test(8192); // C++ 0.10 < C 0.48 (4.80x faster) (+0.72x)
}
答案 0 :(得分:2)
fprintf
有额外的开销,因为它需要扫描其输入字符串以查找格式说明符,因此您并没有进行苹果对苹果的比较。
更好的比较是使用fputs
而不是fprintf
或使用fputc
,然后在file << 'a'
版本中使用iostream
。
答案 1 :(得分:2)
在WriteCPP
中,您必须在打开文件之前设置缓冲区,如下所示:
std::ofstream file;
char buffer[BUFF]; file.rdbuf()->pubsetbuf(buffer, BUFF); // set buffer
file.open ("test.txt", std::ios::binary); // open file
然后,您将获得预期的结果(时间是使用显示的缓冲区大小写入20MB):
writeCPP, 32: 2.15278
writeCPP, 128: 1.21372
writeCPP, 512: 0.857389
我还将您从WriteC
更改为fprintf
的情况下对fputc
进行了基准测试,并得到了以下内容(再次写入20MB):
writeC, 32: 1.41433
writeC, 128: 0.524264
writeC, 512: 0.355097
测试程序在这里:
答案 2 :(得分:0)
std::basic_filebuf::setbuf
的唯一标准定义行为是setbuf(0, 0)
将流设置为无缓冲输出,即使那样我也不会指望它。
setbuf
的 actual 行为因实现而异:
setbuf
仅在打开文件之前调用时有效。除此之外,它还可以满足您的期望。每次缓冲区满时,您将获得对基础write
系统调用的一个调用。setbuf
可以在打开文件后但未完成任何I / O之前调用。每次缓冲区满时,您都会调用基础fwrite
上的FILE*
。这意味着仍使用FILE
的内部缓冲区来缓冲输出。无法访问内部FILE*
到setbuf
或setvbuf
上的内容,因此您将无法使用默认的缓冲区大小(在glibc的实现中,当前为4096字节)。 / li>
basic_filebuf
与基础FILE
对象共享其缓冲区。 setbuf
只是将您提供的缓冲区传递给对基础setvbuf
的{{1}}的调用。可以随时调用,但是会丢弃任何先前缓冲的数据。