寻求Win32无高内核开销的异步/重叠文件读取方案
关于Win32重叠I/O(Overlapped I/O)的性能问题与替代方案需求
我对Win32的ReadFile()重叠I/O(Overlapped I/O)并不满意,它不仅不可靠,读取400MB文件时,在Visual Studio的DEBUG配置下内核开销达8-10毫秒,RELEASE配置下更是25-30毫秒,且内核开销与读取字节数成正比。我已提交相关反馈。
复现步骤
- 在Visual Studio中新建控制台应用项目
- 将下方代码复制到项目中
- 将代码中的“Here could be your file!!!”替换为大小大于或等于
READ_SIZE宏的文件路径 - 在DEBUG模式下多次运行,获取重叠读取请求的平均耗时
- 在RELEASE模式下多次运行,获取重叠读取请求的平均耗时
- 对比平均耗时……
#include <iostream> #include <chrono> #include <Windows.h> #define READ_SIZE 400000000 int main() { // init void* data = new unsigned char[READ_SIZE]; HANDLE file = CreateFileW(L"Here could be your file!!!", // set file path to file with size of READ_SIZE GENERIC_READ, NULL, NULL, OPEN_EXISTING, FILE_FLAG_NO_BUFFERING | FILE_FLAG_OVERLAPPED, NULL); if (file == INVALID_HANDLE_VALUE) { std::cout << "failed to CreateFile!\n"; std::cin.ignore(); return 1; } // request overlapped read OVERLAPPED overlapped{}; std::chrono::high_resolution_clock::time_point begin = std::chrono::high_resolution_clock::now(); ReadFile(file, data, READ_SIZE, NULL, &overlapped); if (GetLastError() != ERROR_IO_PENDING) { std::cout << "failed to request overlapped file read\n"; std::cin.ignore(); return 1; } std::chrono::high_resolution_clock::time_point end = std::chrono::high_resolution_clock::now(); int readFile_duration = std::chrono::duration_cast<std::chrono::milliseconds>(end - begin).count(); // wait for overlapped read to complete begin = std::chrono::high_resolution_clock::now(); DWORD bytesRead; GetOverlappedResult(file, &overlapped, &bytesRead, TRUE); end = std::chrono::high_resolution_clock::now(); int getOverlappedResult_duration = std::chrono::duration_cast<std::chrono::milliseconds>(end - begin).count(); // print results std::cout << readFile_duration + getOverlappedResult_duration << "(ms) for " << bytesRead / 1000000 << "(mb)\n"; std::cout << readFile_duration << "(ms) to request overlapped file read\n"; std::cout << getOverlappedResult_duration << "(ms) for overlapped read to complete\n"; // cleanup CloseHandle(file); std::cin.ignore(); }
但我认为该问题不会很快得到修复,且8毫秒的内核开销对我而言仍过高。我希望找到一种无需内核干预,直接向SSD/HDD/M.2等设备的驱动器发送指令的方法。
我了解到可通过IRP(I/O Request Package)实现,但这需要代码运行在内核模式,而我认为这并非良策。
若您知晓Win32下低内核开销的异步/重叠文件读取方法,或跨平台方案,还请不吝赐教!
内容的提问来源于stack exchange,提问作者Schrottiy
相关产品推荐
相关产品推荐

