Windows基于IOCP异步模型实现高并发文件写入示例

#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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值