SSD环境下C++文件搜索程序的性能优化咨询
C++文件搜索程序优化求助
我写了一个C++文件搜索程序,现在遇到两个问题:一是搜索速度极慢,比如搜索视频文件耗时达94秒;二是结果中出现大量重复路径。我使用SSD存储(总容量465GB,已占用279GB),Visual Studio已开启最高速度优化(/O2),改写代码后性能无明显提升,现寻求加速及修复重复问题的方案。
核心搜索函数
void searchFiles(const std::string& searchQuery, const std::string& rootDir, std::vector<std::string>& results) { std::queue<fs::path> dirs; dirs.push(rootDir); while (!dirs.empty()) { fs::path currentDir = dirs.front(); dirs.pop(); try { for (const auto& entry : fs::directory_iterator(currentDir)) { if (fs::is_directory(entry)) { dirs.push(entry.path()); } else { if (entry.path().filename().string().find(searchQuery) != std::string::npos) { results.push_back(entry.path().string()); } } } } catch (const std::exception& e) { } } }
调用代码
void ScannerFile::ScanningFile() { for (size_t i = 0; i < defaultPath.size(); i++) { searchFiles(defaultPath[i], "C:\\", ModuleManager::resultFile); } }
测试结果示例
C:\Users\mgrr\Videos\Desktop\Desktop 2024.10.20 - 16.03.16.04.mp4 C:\Users\mgrr\AppData\Roaming\Microsoft\Windows\Recent\Desktop 2024.10.20 - 16.03.16.04.lnk C:\Users\mgrr\Videos\Desktop\Desktop 2024.10.20 - 16.03.16.04.mp4 C:\Users\mgrr\AppData\Roaming\Microsoft\Windows\Recent\Desktop 2024.10.20 - 16.03.16.04.lnk C:\Users\mgrr\Videos\Desktop\Desktop 2024.10.20 - 16.03.16.04.mp4 C:\Users\mgrr\AppData\Roaming\Microsoft\Windows\Recent\Desktop 2024.10.20 - 16.03.16.04.lnk Execution time: 94.0131 seconds
优化方案
1. 修复重复结果问题
重复的根源是调用逻辑错误:你循环多次调用searchFiles,每次都从C:\根目录全量搜索,且所有结果都写入同一个全局向量ModuleManager::resultFile,导致同一文件被多次添加。
解决办法
将多查询合并为单次目录遍历,避免重复扫描:
void ScannerFile::ScanningFile() { ModuleManager::resultFile.clear(); // 先清空旧结果 std::queue<fs::path> dirs; dirs.push("C:\\"); while (!dirs.empty()) { fs::path currentDir = dirs.front(); dirs.pop(); try { for (const auto& entry : fs::directory_iterator(currentDir)) { if (fs::is_directory(entry)) { dirs.push(entry.path()); } else { const std::string filename = entry.path().filename().string(); // 一次性匹配所有查询条件 for (const auto& query : defaultPath) { if (filename.find(query) != std::string::npos) { ModuleManager::resultFile.push_back(entry.path().string()); break; // 匹配到一个条件就停止检查 } } } } } catch (const std::exception& e) { } } }
2. 性能加速优化
(1)减少字符串转换开销
entry.path().filename().string()会频繁生成临时字符串,改用C++20的fs::path::contains方法直接匹配,或缓存字符串减少重复转换:
// C++20及以上推荐用法,避免string转换 if (entry.path().filename().contains(searchQuery)) { results.push_back(entry.path().string()); } // 旧标准缓存字符串写法 const std::string filename = entry.path().filename().string(); if (filename.find(searchQuery) != std::string::npos) { results.push_back(entry.path().string()); }
(2)并行遍历目录
SSD支持并行IO,单线程遍历会浪费性能,用多线程处理子目录:
#include <future> #include <mutex> void searchFilesRecursive(const std::string& searchQuery, const fs::path& currentDir, std::vector<std::string>& results, std::mutex& mtx) { try { std::vector<std::future<void>> futures; for (const auto& entry : fs::directory_iterator(currentDir)) { if (fs::is_directory(entry)) { // 异步处理子目录 futures.emplace_back(std::async(std::launch::async, &searchFilesRecursive, std::ref(searchQuery), entry.path(), std::ref(results), std::ref(mtx))); } else { if (entry.path().filename().contains(searchQuery)) { std::lock_guard<std::mutex> lock(mtx); results.push_back(entry.path().string()); } } } // 等待所有子线程完成 for (auto& f : futures) f.get(); } catch (const std::exception& e) { } } void searchFiles(const std::string& searchQuery, const std::string& rootDir, std::vector<std::string>& results) { std::mutex mtx; searchFilesRecursive(searchQuery, rootDir, results, mtx); }
(3)跳过无关目录
提前过滤系统目录、缓存目录等无需搜索的路径,减少遍历量:
const std::unordered_set<std::string> skip_dirs = { "Windows", "System Volume Information", "AppData\\Local\\Temp", "Program Files", "Program Files (x86)" }; // 判断目录时跳过指定路径 if (fs::is_directory(entry)) { std::string dir_name = entry.path().filename().string(); if (skip_dirs.find(dir_name) == skip_dirs.end()) { dirs.push(entry.path()); } }
(4)预分配结果向量空间
提前预估结果数量,用reserve预分配内存,避免push_back频繁扩容:
// 在搜索前调用,比如预估最多10000个结果 results.reserve(10000);
(5)改用Windows原生API遍历
标准库fs::directory_iterator在Windows平台的性能不如原生FindFirstFileW/FindNextFileW,以下是简化示例:
#include <windows.h> void searchFilesWinAPI(const std::wstring& searchQuery, const std::wstring& rootDir, std::vector<std::wstring>& results) { WIN32_FIND_DATAW findData; HANDLE hFind = FindFirstFileW((rootDir + L"\\*").c_str(), &findData); if (hFind == INVALID_HANDLE_VALUE) return; do { if (wcscmp(findData.cFileName, L".") == 0 || wcscmp(findData.cFileName, L"..") == 0) continue; std::wstring fullPath = rootDir + L"\\" + findData.cFileName; if (findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { searchFilesWinAPI(searchQuery, fullPath, results); } else { if (std::wstring(findData.cFileName).find(searchQuery) != std::wstring::npos) { results.push_back(fullPath); } } } while (FindNextFileW(hFind, &findData)); FindClose(hFind); }
3. 其他实用建议
- 优先搜索用户目录(如
C:\Users)而非全盘遍历,除非必须; - 缓存搜索结果,相同查询直接返回缓存;
- 按后缀名搜索时,直接匹配
entry.path().extension()比find更高效,例如entry.path().extension() == ".mp4"。
内容的提问来源于stack exchange,提问作者cold vinar
相关产品推荐
相关产品推荐

