最近我决定优化我正在做的一些文件读取,因为正如大家所说,将大量数据读取到缓冲区然后使用它比使用大量小读取要快。而且我的代码现在当然要快得多,但是在进行了一些分析之后,memcpy 似乎占用了很多时间。
我的代码的要点是...
ifstream file("some huge file");
char buffer[0x1000000];
for (yada yada) {
int size = some arbitrary size usually around a megabyte;
file.read(buffer, size);
//Do stuff with buffer
}
我正在使用 Visual Studio 11,在分析我的代码后,它说ifstream::read()
最终调用xsgetn()
从内部缓冲区复制到我的缓冲区。这个操作占用了80%以上的时间!排在第二位的是uflow()
占用 10% 的时间。
有什么办法可以绕过这种复制吗?我可以以某种方式告诉将ifstream
我需要的大小直接缓冲到缓冲区中吗?C 风格是否FILE*
也使用这样的内部缓冲区?
更新:由于人们告诉我使用 cstdio ......我做了一个基准测试。
编辑:不幸的是,旧代码充满了失败(它甚至没有读取整个文件!)。你可以在这里看到它:http: //pastebin.com/4dGEQ6S7
这是我的新基准:
const int MAX = 0x10000;
char buf[MAX];
string fpath = "largefile";
int main() {
{
clock_t start = clock();
ifstream file(fpath, ios::binary);
while (!file.eof()) {
file.read(buf, MAX);
}
clock_t end = clock();
cout << end-start << endl;
}
{
clock_t start = clock();
FILE* file = fopen(fpath.c_str(), "rb");
setvbuf(file, NULL, _IOFBF, 1024);
while (!feof(file)) {
fread(buf, 0x1, MAX, file);
}
fclose(file);
clock_t end = clock();
cout << end-start << endl;
}
{
clock_t start = clock();
HANDLE file = CreateFile(fpath.c_str(), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_ALWAYS, NULL, NULL);
while (true) {
DWORD used;
ReadFile(file, buf, MAX, &used, NULL);
if (used < MAX) break;
}
CloseHandle(file);
clock_t end = clock();
cout << end-start << endl;
}
system("PAUSE");
}
时间是:
185
80
78
嗯...看起来使用 C 风格的 fread 比 ifstream::read 快。同样,使用windows ReadFile 仅提供微不足道的优势(我查看了代码,fread 基本上是ReadFile 的包装器)。看来我毕竟要改用 fread 了。
伙计,编写一个真正正确测试这些东西的基准是令人困惑的。
结论:使用<cstdio>
比<fstream>
. fstream 较慢的原因是因为 c++ 流有自己的内部缓冲区。这会在您读/写时导致额外的复制,并且这种复制占 fstream 所花费的全部额外时间。更令人震惊的是,额外花费的时间比实际读取文件所花费的时间还要长。