我尝试使用 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)上的运行时性能远远低于我的预期:
从循环中提取
std::ifstream file
对象并在循环中使用 file.open
/file.close
甚至使用 C 风格 fopen
/fclose
代替 std::ifstream
没有什么区别。
我错过了什么吗?我不敢相信仅仅打开(甚至还没有处理)几千个小文件就需要几分钟......
我稍微重写了你的内容,以显示一些数字。不幸的是,这对你的问题没什么帮助,但它不适合评论。
#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
所以即使这对我来说也没有太大改变......