std::fstream 性能缓慢

问题描述 投票:0回答:1

我尝试使用 C++ 可执行文件处理一堆文件(数千个,每个大小约为 500KB),但在顺序读取文件时遇到性能非常差的情况。核心C++代码基本上是这样的:

int main() {
  std::vector<std::string> filePaths{ "file1", "file2", ... }; // Many file paths
  int i = 0;
  for (const std::string& filePath : filePaths) {
    std::ifstream file(filePath, std::ios::binary);
    std::cout << i++ << std::endl;
  }
  return 0;
}

我使用 MSVC 2022 和 MinGW (GCC 13.1.0) 编译了此文件,两者都启用了标准 CMake 版本优化。然而,我相当现代的机器(Win11、32GB RAM、Ryzen 9、SSD)上的运行时性能远远低于我的预期:

runtime performance

从循环中提取

std::ifstream file
对象并在循环中使用
file.open
/
file.close
甚至使用 C 风格
fopen
/
fclose
代替
std::ifstream
没有什么区别。

我错过了什么吗?我不敢相信仅仅打开(甚至还没有处理)几千个小文件就需要几分钟......

c++ windows
1个回答
0
投票

我稍微重写了你的内容,以显示一些数字。不幸的是,这对你的问题没什么帮助,但它不适合评论。

#include <iostream>
#include <fstream>
#include <boost/timer/timer.hpp>
#include <memory>
#include <filesystem>
#include <vector>

static const std::string dir("/usr/include/");

int main()
{
    std::vector<std::string> filePaths;

    {
        boost::timer::auto_cpu_timer timer;
        for (auto const& entry : std::filesystem::recursive_directory_iterator(dir))
        {
            if (entry.is_regular_file())
            {
                filePaths.push_back(entry.path().native());
            }
        }
    }
    std::cout << "got " << filePaths.size() << " paths\n";

    {
        boost::timer::auto_cpu_timer timer;
        for (const std::string& filePath : filePaths)
        {
            std::ifstream file(filePath, std::ios::binary);
            if (!file.good())
            {
                std::cerr << "problem\n";
                return 1;
            }
            // std::cout << filePath << "\n";
        }
    }
    std::cout << "opened " << filePaths.size() << " paths\n";

    return 0;
}
stieber@gatekeeper:~ $ g++ Test.cpp -lboost_timer && ./a.out
 0.161745s wall, 0.080000s user + 0.080000s system = 0.160000s CPU (98.9%)
got 19386 paths
 0.349939s wall, 0.100000s user + 0.240000s system = 0.340000s CPU (97.2%)
opened 19386 paths

你最感兴趣的是第二块,但我懒得创建 1000 个文件,所以我只是从系统中取出它们。不过,正如您所看到的,这两个块都不需要花费大量时间,因此您的问题要么是文件系统非常糟糕,要么是控制台输出。

所以,让我们取消注释输出并重试:

...
/usr/include/iproute2/bpf_elf.h
/usr/include/fmtmsg.h
/usr/include/getopt.h
 0.652310s wall, 0.220000s user + 0.440000s system = 0.660000s CPU (101.2%)
opened 19386 paths

所以即使这对我来说也没有太大改变......

© www.soinside.com 2019 - 2024. All rights reserved.