由于 memcpy,C++ ifstream::read 变慢

标签 c++ performance visual-c++ fstream memcpy

最近我决定优化我正在做的一些文件读取,因为正如每个人所说,将大块数据读取到缓冲区然后使用它比使用大量小读取更快。我的代码现在当然快多了,但是在进行一些分析之后,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 占用的全部额外时间。更令人震惊的是,额外花费的时间比实际读取文件的时间还要长。

最佳答案

Can I somehow tell the ifstream to buffer the size I need directly into my buffer?

是的,这就是pubsetbuf()是为了。

但是,如果您关心的是在读取文件的同时进行复制,那么还要考虑内存映射,boost 有一个 portable implementation .

关于由于 memcpy,C++ ifstream::read 变慢,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10324582/

相关文章:

c++ - 使用 vector 创建二维数组

c++ - 通用 lambda 在 C++14 中如何工作?

java - Alpha beta 修剪没有产生好的结果

c++ - 在 IMMDeviceEnumerator 上调用 SAFE_RELEASE 时崩溃

c++ - 删除 C++ 指针

c++ - unsafe.cpp 如何链接到 openJDK 构建系统中的 Unsafe.java

c++ - 为什么转置 CUDA 网格(但不是它的线程 block )仍然会减慢计算速度?

javascript - 有没有更好的方法来对对象数组进行排序以动态生成按值分隔的 HTML 元素?

c++ - VC++ 中的动态数组大小和动态数组分配器

c++ - 什么时候应该明确地赋予 noexcept 属性?