#include <Windows.h>
#include <iostream>
#include <atomic>
#include <vector>
#include <chrono>
#define BUFFER_SIZE (1024 * 1024) // 1MB缓冲区
#define MAX_CONCURRENT_IO 8 // 并发IO数量
#define TEST_DURATION_SEC 5 // 测试持续时间
// 异步操作上下文结构
struct IoContext {
OVERLAPPED ov = { 0 };
HANDLE hFile = INVALID_HANDLE_VALUE;
char* buffer = nullptr;
DWORD bytesToWrite = 0;
LARGE_INTEGER writeOffset;
};
// 全局统计变量
std::atomic<ULONGLONG> totalBytesWritten(0);
std::atomic<ULONGLONG> totalOperations(0);
void PostNextWrite(IoContext* ctx) {
ctx->ov.Offset = ctx->writeOffset.LowPart;
ctx->ov.OffsetHigh = ctx->writeOffset.HighPart;
if (!WriteFile(ctx->hFile, ctx->buffer, BUFFER_SIZE, nullptr, &ctx->ov)) {
if (GetLastError() != ERROR_IO_PENDING) {
std::cerr << "WriteFile failed: " << GetLastError() << std::endl;
}
}
}
// IOCP工作线程
DWORD WINAPI WorkerThread(LPVOID lpParam) {
HANDLE hIOCP = (HANDLE)lpParam;
DWORD bytesTransferred;
ULONG_PTR completionKey;
LPOVERLAPPED lpOverlapped;
while (true) {
BOOL status = GetQueuedCompletionStatus(
hIOCP, &bytesTransferred, &completionKey, &lpOverlapped, INFINITE);
if (lpOverlapped == nullptr) break; // 退出信号
IoContext* ctx = CONTAINING_RECORD(lpOverlapped, IoContext, ov);
if (status && bytesTransferred == ctx->bytesToWrite) {
totalBytesWritten += bytesTransferred;
totalOperations++;
// 更新偏移量并提交新IO(流式持续写入)
ctx->writeOffset.QuadPart += BUFFER_SIZE;
PostNextWrite(ctx);
}
else {
std::cerr << "Write failed! Error: " << GetLastError() << std::endl;
}
}
return 0;
}
int main() {
// 创建测试文件
HANDLE hFile = CreateFile(L"D:/test.dat", GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
FILE_FLAG_OVERLAPPED | FILE_FLAG_NO_BUFFERING, NULL);
// 初始化IOCP
HANDLE hIOCP = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 0);
CreateIoCompletionPort(hFile, hIOCP, 1, 0);
// 创建线程池(CPU核心数*2)
SYSTEM_INFO sysInfo;
GetSystemInfo(&sysInfo);
std::vector<HANDLE> threads(sysInfo.dwNumberOfProcessors * 2);
for (auto& t : threads) {
t = CreateThread(NULL, 0, WorkerThread, hIOCP, 0, NULL);
}
// 初始化IO上下文池
std::vector<IoContext> ioContexts(MAX_CONCURRENT_IO);
for (auto& ctx : ioContexts) {
ctx.hFile = hFile;
ctx.buffer = (char*)_aligned_malloc(BUFFER_SIZE, 4096); // 内存对齐
ctx.bytesToWrite = BUFFER_SIZE;
memset(ctx.buffer, 0xAA, BUFFER_SIZE); // 填充测试数据
PostNextWrite(&ctx);
}
// 启动计时器
auto start = std::chrono::high_resolution_clock::now();
Sleep(TEST_DURATION_SEC * 1000);
// 停止线程
for (size_t i = 0; i < threads.size(); ++i) {
PostQueuedCompletionStatus(hIOCP, 0, 0, nullptr);
}
WaitForMultipleObjects((DWORD)threads.size(), threads.data(), TRUE, INFINITE);
// 计算速率
auto duration = std::chrono::duration_cast<std::chrono::seconds>(
std::chrono::high_resolution_clock::now() - start).count();
double mbps = (totalBytesWritten.load() / (1024.0 * 1024.0)) / duration;
std::cout << "写入统计: \n"
<< "持续时间: " << duration << "秒\n"
<< "总数据量: " << (totalBytesWritten / (1024 * 1024)) << " MB\n"
<< "吞吐量: " << mbps << " MB/s\n"
<< "IOPS: " << (totalOperations / duration) << " 次/秒\n";
// 清理资源
for (auto& ctx : ioContexts) {
_aligned_free(ctx.buffer);
}
CloseHandle(hFile);
CloseHandle(hIOCP);
return 0;
}
08-03
659
