windows没有cfq、deadline、noop等i/o调度器,它们是linux内核块层算法,与c#无关;c#文件io性能取决于fileoptions、缓冲区大小、异步配置及ntfs设置。

Windows 没有 CFQ、Deadline、NOOP 这些调度器——它们是 Linux 内核块层的 I/O 调度算法,和 C# 完全无关。
为什么 C# 程序员会搜到这些 Linux 调度器?
常见错误现象:在 Windows 上用 dotnet 做高吞吐文件读写(比如日志批量刷盘、数据库快照导出),性能上不去,顺手去查“IO 调度优化”,结果撞进 Linux 文档里。
根本原因在于混淆了两个层级:
- Linux 的
CFQ/Deadline/NOOP是内核对磁盘请求队列的排序与合并策略,运行在 block layer,用户态程序(包括 .NET)无法直接控制或感知 - C# 的
FileStream、MemoryMappedFile或Span<byte></byte>IO 行为,只受 Windows I/O 子系统(如 NTFS 缓存策略、I/O 优先级、异步完成端口)和硬件驱动影响
Windows 下真正影响 C# 文件 IO 性能的关键点
不是调度器,而是以下几项实际可调、易踩坑的设置:
-
FileStream构造时传入FileOptions.WriteThrough会绕过系统缓存,强制直写磁盘——适合关键数据但吞吐暴跌;不加则依赖FILE_ATTRIBUTE_NOT_CONTENT_INDEXED和FILE_FLAG_NO_BUFFERING(后者在 .NET 中需 P/Invoke) - 同步写
Write()vs 异步写WriteAsync():后者默认走 I/O Completion Ports,线程复用好,但若未await或漏掉ConfigureAwait(false),可能卡住线程池 - 缓冲区大小:默认
FileStream缓冲区是 4KB,对 SSD 随机小写不利;大文件顺序读写建议设为 64KB–1MB(通过bufferSize参数),但要避开 128KB 以上导致内存碎片(尤其在 Server GC 下) - NTFS 日志模式:
fsutil behavior set disablelastaccess 1可关掉最后访问时间更新,避免每次读都触发元数据写入
如何验证你的 C# IO 瓶颈真正在哪?
别猜调度器,用真实工具定位:
- 用
PerfView录制Microsoft-Windows-Kernel-IOETW 事件,看WriteFile耗时是否卡在IRP_MJ_WRITE等待,而非用户代码 - 用
Process Monitor过滤进程名 +WriteFile操作,检查是否频繁FASTIO_DISALLOWED回退到 IRP,说明缓冲区太小或文件锁冲突 - 对比开启/关闭 Windows SuperFetch(
sysmain服务)对冷启动读取的影响——它会预加载常用文件进内存,和 Linux 的page cache类似,但和调度器无关
真正要调的从来不是“调度器”,而是你创建 FileStream 时传的那几个 FileOptions、缓冲区大小、是否 await、以及 NTFS 卷本身的格式化参数。Linux 那套术语混进来,只会让你在错误的方向上优化更久。











