Core/IO 性能全景报告(Linux)
环境:Linux 6.8 / Ubuntu 24.04(ext4 on /tmp,SSD——无 fsync 地板),.NET 8,AMD Ryzen 9 6900HX 12C,BenchmarkDotNet + 探针。
持久化两档:默认档(journal 提交 + 载体 fsync)与挂载级载体写穿档(CarrierWriteThrough——写穿完成即单屏障提交,免 fsync)。写穿档为持久化热路径主推形态(数字见 §3 摘要/§8.4/fsync 谱系注记);读路径/元数据面/mem/零拷贝数字与档位无关。
虚拟文件系统六维(§8)与四类文件系统矩阵(§9)为空闲机正式跑(load < 1.2);网络文件系统 MinIO(§7)为本机 docker(loopback 网络——真云对照见 §7.3)。
性质:绝对值随硬件浮动,相对比较(比值列)是稳定结论。
复现:
dotnet run --project benchmarks/TC.Tier.Core.Benchmarks -c Release -- --filter "*FileIoBenchmarks*" --job short # 本地文件系统/抽象税
dotnet run --project benchmarks/TC.Tier.Core.Benchmarks -c Release -- --filter "*TierVolumeIo*" # Virtual 六维(16 项)
dotnet run --project probes/IoMediumMatrixProbe -c Release # 四类文件系统矩阵(含 MinIO)
dotnet run --project probes/IoConcurrencyProbe -c Release # 并发扩展性(5 形态 × 梯度)
配套:API 语义见 io.md;虚拟文件系统深指南 virtual-file-system.md。
0. 结论速查(把比值翻译成选型决策)
| 场景 |
数据支撑 |
决策 |
| 同文件反复打开(引擎段/索引页) |
池命中往返 26.9 ns vs 本地文件系统裸 Open 6.27 μs(233×) |
池是长生命周期访问的唯一合理形态 |
| 关心 Core/IO 抽象层的开销 |
读 +3.6% / 写 +0.4%(噪声量级) |
抽象税≈零——不必绕过本层手写 RandomAccess |
| 热数据反复读 |
Buffered 页缓存命中 2.7 μs vs DIO 53.2 μs(19.6×) |
常规读走 Buffered;DIO 用于绕缓存的有意场景(大扫描/自管缓存) |
| 文件间大块拷贝 |
copy_file_range 比手写循环快 26% |
Linux 置位 CopyRange——大拷贝走 CopyRange |
| 小写入持久化 |
fdatasync 比 fsync 快 22%(85 vs 109 μs) |
Linux 上 FlushData 是真实加速(FlushDataOnly 位);数据不变时优先它 |
| mem 热数据访问 |
Reserved 直址读 1.23 μs / 映射扫描 537 ns(比 Read 快 2.3×) |
零拷贝读走 Map;写走直址 Write |
| 本地持久化选文件系统 |
虚拟文件系统元数据面 Open 35× / Stat 176× / 枚举 18.7× vs 本地文件系统;数据面全维带内持平 |
虚拟文件系统 = 本地持久化推荐位(单工件 + 元数据内存直达,§8) |
| fsync 密集负载(Virtual) |
默认档钉在硬件 fsync 地板(WAL 单屏障 564 μs vs Disk 490 μs vs 裸 fsync ~548 μs);载体写穿档免 fsync——写穿完成即提交,本环境(SSD)p50 0.115–0.132 ms 四模式全达标,Windows 机械盘实测 p50 0.17–0.20 ms |
持久化热路径用载体写穿档(挂载级);默认档的地板是 OS fsync 语义(§8.4)——复现 --wal-meta-probe virtual 1000 all true |
| 四类文件系统怎么选 |
§9 矩阵:本地三类文件系统数据面全带内持平(追加 1.6 GB/s / 顺序读 23-37 GB/s);差异全在元数据面与一致性语义 |
按语义选不按速度选:测试隔离内存 / 目录树本地 / 单工件+元数据快虚拟 / 云归档网络 |
| 网络文件系统读缓存参数 |
随机读 4K:4MB 缓存边界颠簸 895 μs vs 32MB 缓存命中 4.1 μs(220×) |
网络文件系统随机访问必须把 ReadCacheBytes 调到热集以上(§7.2) |
| 并发怎么用 |
Virtual 读并行 3.6×(锁外快照)/ 写反扩展(单写者锁);Mem 写近线性 2.2×;Disk 混合最均衡 |
Virtual 单写者+Append;Mem 写密集同文件选 Reserved;并发读多句柄(§10) |
1. 池化 vs 非池化(FileHandlePool——Acquire/归还 完整往返)
| 路径 |
Mean |
分配 |
vs 池命中 |
Pool.Acquire+归还(命中,内存文件系统) |
26.9 ns |
40 B |
1× |
Pool.TryAcquire(命中) |
27.3 ns |
40 B |
1.01× |
裸 fs.Open+Dispose(mem) |
118.6 ns |
272 B |
4.4× |
裸 fs.Open+Dispose(disk,ext4) |
6,271 ns |
696 B |
233× |
- 本地文件系统差距 233× 是本表核心:本地文件系统 open 含 syscall + DIO/卷探测 + 句柄对象构建;池命中 = 锁读 + usage++(挂载式归还零系统调用)。
- mem 4.4×:无 syscall 但仍有对象构建 + 槽解析 + 池外 Dispose 关闭逻辑。
- 40 B 命中分配来自
FileOpenOptions 传递(record class)——消费者可缓存 options 实例进一步归零。
- 并发竞争(8 key 多线程)见
FileHandlePoolContentionBench——键控分桶下无全局锁串行。
2. 本地文件系统抽象税(DiskFileHandle vs 裸 RandomAccess——"要不要绕过本层")
| 操作 |
Core/IO |
裸 BCL |
差 |
| 读 64K(页缓存命中) |
2,830 ns |
2,732 ns |
+3.6% |
| 写 64K |
7.23 μs |
7.20 μs |
+0.4% |
结论:抽象税在噪声内(本层 = pwrite/pread 直通,校验与游标逻辑为纯托管几 ns 级)。手写绕过本层没有性能收益,反而失去能力协商/对齐校验/池协议。
3. DIO vs Buffered(O_DIRECT 的诚实标定——ext4)
| 路径 |
Mean |
说明 |
| 读 64K Buffered(页缓存命中) |
2.71 μs |
热数据——页缓存即速度 |
| 读 64K DIO(绕页缓存) |
53.2 μs |
真盘读——19.6× 差距 = 页缓存价值 |
| 写 64K DIO(绕页缓存) |
52.0 μs |
真盘写 |
DIO 的 19.6× "惩罚"是特性不是缺陷:自管缓存(引擎页表)场景下页缓存是双倍内存 + 额外拷贝。UnbufferedSupport 探测(overlay/tmpfs → Ignored)保证容器内静默降级不炸。
4. CopyRange vs 手写循环(4M,同盘)
| 路径 |
Mean |
比值 |
CopyRange(Linux copy_file_range) |
735 μs |
1×(快 26%) |
| 手写 Read/Write 循环(1M buffer) |
990 μs |
1.35× |
内核路径省一半用户态拷贝与系统调用数;内存文件系统为用户态回退(4M = 16.4 μs,内存带宽级),能力位如实表达"无零拷贝加速"。
5. 持久化谱系(fsync vs fdatasync——写 4K + 刷盘)
| 路径 |
Mean |
差 |
写 4K + Flush()(fsync 全量) |
109.2 μs |
— |
写 4K + FlushData()(fdatasync) |
85.4 μs |
-22% |
Linux 置位 FlushDataOnly 的实证价值:group commit 攒批后的最终刷盘用 FlushData 省元数据写放大。Win/macOS 未置位时 FlushData ≡ Flush 回退不抛。
6. mem Reserved 直址模型
| 路径 |
Mean |
说明 |
| 读 64K(直址) |
1.23 μs |
memcpy 64K ≈ 53 GB/s 有效带宽 |
| 写 64K(直址) |
1.15 μs |
同上 |
Map 视图顺序扫 64K |
537 ns |
零拷贝——比 Read 再快 2.3×(无 memcpy) |
| WriteVector 4×16K |
1.22 μs |
与逐段等价(mem 回退逐片——VectorIO 位未置位,无惩罚) |
| CopyRange 4M(用户态回退) |
16.4 μs |
内存带宽级 |
| Append 4K(原子预留) |
1.54 μs |
含 Sparse 页分配;预留成本 = 1 次 Interlocked(淹没在 memcpy 里) |
- Reserved 直址读写的 ~1.2 μs 是 memcpy 数据搬运下界——本层零开销。
- 本地文件系统 Append 4K 同基准 7.17 μs ≈ 同尺寸 pwrite(预留开销可忽略)。
7. 网络文件系统(RemoteFileSystem × MinIO 本机实测——2026-08-19)
环境:本机 docker minio/minio(loopback 网络,RTT < 1ms)——量化桥层成本结构(staging/Flush 编排/读缓存);
真云 WAN 数字见 §7.3 COS 对照。探针 probes/IoMediumMatrixProbe(与 §9 矩阵同源)。
7.1 元数据面与数据面(MinIO loopback)
| 维度 |
Remote |
Disk(对照) |
形态解释 |
| Open |
515 μs |
7.3 μs |
每次打开 = HeadObject 网络往返(记长度快照)——网络文件系统的固有税 |
| Stat |
513 μs |
6.6 μs |
同上 |
| 枚举 1000 |
25.5 ms |
2.45 ms |
ListObjectsV2 单页往返(恢复扫描一次到位) |
| 追加 64KB×N(不 Flush) |
554-703 MB/s |
1665 MB/s |
staging 内存写回层(零网络)——纯追加句柄永不加载历史 |
| 顺序读 4MB(1MB×4) |
2.7-3.3 GB/s |
25.4 GB/s |
读句柄 LRU 页缓存命中 + loopback;真云 WAN 受带宽限制 |
| 热随机读 4K |
895 μs → 4.1 μs(见 §7.2) |
919 ns |
缺页 = Range GET 网络往返 |
7.2 读缓存参数敏感度(ReadCacheBytes——网络文件系统性能的最大杠杆)
读句柄页缓存默认 4MB(RemoteFileSystemOptions.ReadCacheBytes)。4MB 测文件 = 64 × 64KiB 页,
恰好踩满缓存边界(LRU 互相驱逐)——热随机读每 op 都在重新 Range GET(895 μs/op);
调到 32MB(全量驻留)后 4.1 μs/op(220× 改善)。
消费规则:网络文件系统随机访问的工作集必须整体装进 ReadCacheBytes(热集的 1.5× 以上);纯顺序扫描不受此限
(预取窗口 PrefetchPages 流水线供应)。
7.3 持久化形态(Flush = 唯一持久化点)
| 路径 |
MinIO loopback |
说明 |
| 追加 64KB + 逐次 Flush |
26-40 ms/op |
每 Flush 一次 multipart PUT(对象式持久化粒度是"对象版本"不是"块")——逐写 Flush 网络文件系统反模式 |
| group commit(攒批 Flush) |
桥层 870 MB/s 级 |
staging 吸收 + 单次 multipart——正确姿势 |
| 增量 Flush(128MB 存量 + 32MB 增量) |
耗时比 38% |
未改 part 服务端自拷贝(UploadPartCopy)——出口流量 O(增量) |
真云 COS 对照(ap-chengdu,WAN):对象层 PUT 13.2 / GET 15.0 MB/s(本机带宽饱和);Range GET p50=48ms;
桥级全量 Flush 12.8 MB/s——网络是网络文件系统的第一性能决定量,桥层职责是不在网络上再加协议税。
7.4 网络文件系统性能规范(总结)
- 元数据面避免高频调用(Open/Stat 各一次网络往返)——枚举融合(FsEntry 含长度,恢复扫描零额外 Head)已内建;
- 随机读先量热集,再调
ReadCacheBytes(§7.2 的 220× 是免费收益);
- 持久化永远 group commit——逐写 Flush 在网络文件系统是 26-40ms/op 的反模式;
RandomWrite 不置位是诚实警告:GB 级既有对象随机覆写 = 逐区间拉取秒级——改追加式或重建。
8. 虚拟文件系统六维(空闲机终判——本地持久化推荐位的准入证)
方法:BDN 隔离进程(TierVolumeIoBenchmarks 16 项,定量工作/op——Mean = 每 op 成本,低 = 优);
环境 AMD Ryzen 9 6900HX 12C / 26GB 可用 / load < 1.2。验收线(设计 §12.4):数据面噪声内持平(±5%)、
元数据面不低于 Disk。六维全部达线。
8.1 六维总表(对照 DiskFileSystem 同机同形)
| 维度 |
Virtual |
Disk |
比值 |
判定 |
| Open(重复打开 d0/f0) |
236 ns |
8.29 μs |
35× |
✅ 元数据面 |
| Stat(单条目查询) |
36 ns |
6.34 μs |
176× |
✅ 元数据面 |
| 枚举(1000 条目目录) |
132 μs |
2.47 ms |
18.7× |
✅ 元数据面 |
| 随机读 4K(512 次/op,页缓存命中) |
123 μs(240 ns/读) |
465 μs(910 ns/读) |
3.8× |
✅ 数据面 |
| 顺序读 256MB 直达档(4MB 缓冲) |
31.1 ms |
29.8 ms |
-4.3% |
✅ ±5% 带内 |
| 顺序读 256MB 缓冲档 |
22.0 ms(11.6 GB/s) |
—(超热页形态) |
最快档 |
✅ |
| 追加 4MB(64KB×64,稳态) |
与 Disk 噪声带内持平(探针 1645 vs 1678 MB/s) |
— |
≈1.0× |
✅ |
| 追加+逐次 Flush(fsync 密集) |
564 μs/op |
490 μs/op |
0.87× |
✅ 钉硬件地板(§8.4) |
8.2 元数据面 35–176×:为什么 Disk 付 syscall 而 Virtual 不付
Virtual 的命名空间/区间表/位图全部内存直达(打开时装载,_sortedKeys 有序索引 O(log n) 维护)——
Open/Stat/枚举是纯内存操作零 syscall;Disk 每次 Open = open(2) + fstat + 句柄构建,Stat = fstat,枚举 = readdir 循环。
这是设计预言(§3.4"Open/Stat/枚举 = 内存元数据操作,零 syscall——明显更快")的实测兑现。
消费含义:海量小文件/高频元数据负载(段表扫描、恢复遍历、索引元数据)在 Virtual 上有一个数量级以上的免费加速。
8.3 数据面-读:自管页缓存 + O_DIRECT 读通道
- 热随机读 3.8×:自管页缓存命中 = ~100ns 级 memcpy(240 ns/读含接口层),Disk 热读要付 pread syscall(910 ns)。
- 顺序读两档形态:
- 缓冲档 11.6 GB/s:冷段批量装入(64 块/次载体读)+ 自动预读(内核 readahead 同构启发式)+ 读绕(大跨度直读不驻留);
- 直达档 -4.3%(带内):
NoBuffering 走文件载体专用 O_DIRECT 读通道——弹跳窗三重对齐 + 单段零拷贝,
与 Disk O_DIRECT 同 syscall 形态(空闲机实测 2229 vs 9955 MB/s 的缓冲对照)。
- 注意:O_DIRECT 的写侧是另一回事——同步小写每写一次设备往返(实测 64KB=189μs、
1MB=12ms 灾难段),文件载体缓冲档平权 Disk 的存在条件 = 内核 writeback 吸收。读写两侧分开定策是这套
两档模型的核心规范。
8.4 数据面-写:写放大与 WAL 单屏障
| 场景 |
默认档 |
载体写穿档(CarrierWriteThrough) |
| 追加(缓冲档) |
1481 MB/s(超 Disk 1315)——写放大归零(run 一次落位 + continue) |
同左(缓冲档与写穿档正交——写穿只改持久化路径) |
| 追加 + 逐次 Flush |
85 vs Disk 83 vs 裸 fsync 地板 66 MB/s——Flush = 排干 + 记录落区 + 单屏障;两段式组提交 |
免 fsync——写穿完成即单屏障:本环境(SSD)p50 0.115–0.132 ms,Windows 机械盘 p50 0.17–0.20 ms(p99.9 ≤1.74 ms) |
| 原地覆写 + Flush |
564 vs 490 μs/op——双 write + 记录机械 ≈ 1.9× 裸 fsync |
写穿形态下无双 write + fsync 串联——同写穿档口径 |
设计含义:默认档的 fsync 密集上限由设备 fsync 延迟决定(硬件地板);本层的职责是不在地板之上再加协议税。载体写穿档把"写数据 + journal + fsync"三段压成一次写穿——持久化成本与设备写穿延迟对齐而非 fsync 延迟(挂载级选项,MMF 直映射路径仍走 FlushCarrier 全屏障)。
8.5 调优速查(Virtual)
| 负载 |
打开姿势 |
| 大顺序扫描(不冲刷内存) |
Hints = NoBuffering + Advise(Sequential)(纯流式:载体直读、无页机制、无预取交互) |
| 热随机读 / 重读 |
默认缓冲档(自管缓存命中 memcpy);预算 PageCacheBytes(默认 64MB,0 = 纯直达) |
| 追加日志型(引擎段同构) |
PreallocateSize 预分配消分配税 + Append 原子预留;持久化节奏:FlushData(批)/ Flush(提交点)/ Hints.WriteThrough(逐写零窗口) |
| 全卷备份/迁移 |
RootSpaceImage.Transfer(Virtual↔Virtual 自动走 dd 字节直拷快道) |
9. 四类文件系统横向矩阵(2026-08-19 空闲机实测——probes/IoMediumMatrixProbe)
同一套形态跑遍四类文件系统(本地 ext4 / 内存 Sparse / 虚拟文件载体 / 网络 MinIO loopback)——
本地三类文件系统数据面全带内持平(差异在元数据面与一致性语义);网络文件系统是另一个物理世界(网络往返)。
9.1 元数据面(ns/op,3 轮取最小)
| 文件系统 |
Open |
Stat |
枚举 1000 |
形态 |
| Disk |
7,314 |
6,607 |
2,449,200 |
每次 = syscall(open/fstat/readdir) |
| Mem |
118 |
54 |
134,483 |
纯内存(槽/字典直达)——上界参照 |
| Virtual |
223 |
60 |
223,785 |
纯内存(元数据全量驻留 + 有序索引) |
| Remote |
515,155 |
512,926 |
25,506,325 |
每次 = 网络往返(Head/ListObjects) |
- Virtual vs Disk:Open 33× / Stat 110× / 枚举 11×——与 §8 BDN 隔离口径(35×/176×/18.7×)同量级;
- Virtual vs Mem(理论上界):同数量级(Open 223 vs 118——Virtual 多一层共享登记与游标;Stat 打平 60 vs 54)。
元数据面 虚拟 ≈ 内存 ≫ 本地 ≫ 网络 是四类文件系统的基本格局。
9.2 数据面
| 文件系统 |
顺序读 4MB(GB/s) |
热随机读 4K(ns/op) |
追加 64KB(MB/s) |
fsync 形态 64KB+Flush(ms/op) |
| Disk |
25.4 |
919(OS page cache) |
1,665 |
0.33 |
| Mem |
37.3 |
126(直址) |
1,627 |
0.04(no-op) |
| Virtual |
23.6 |
254(自管页缓存) |
1,606 |
0.38(WAL 单屏障) |
| Remote |
2.7(loopback) |
895,000(4MB 缓存边界)/ 4,086(32MB 缓存) |
554(staging) |
26-40(每 Flush 一次 multipart) |
- 本地三类文件系统数据面带内持平:追加 1.6 GB/s(设备写上限形态)、顺序读 23-37 GB/s(内存拷贝带宽形态)——
文件系统选择不由数据面速度决定;
- 随机读的缓存提供方不同(OS page cache / 直址 / 自管页缓存 / 桥级 LRU)——Virtual 254ns 含共享设施
(游标/epoch/快照),是"带一致性规范的缓存命中"价格;
- fsync 谱系:Mem 0.04ms(易失)→ Disk 0.33ms(OS fsync)→ Virtual 默认档 0.38ms(WAL 单屏障 + 载体 fsync)/ Virtual 载体写穿档 0.115–0.132ms(本环境 SSD,免 fsync)→
Remote 26-40ms(对象版本粒度)——持久化粒度与成本单调对应。
9.3 选型决策(数据面持平的前提下按语义选)
| 需求 |
文件系统 |
依据 |
| 单元测试 / CI 无盘 / 引擎内存设备 |
Mem |
进程内私有卷、易失、元数据最快 |
| 目录树形态 / 宿主直接可读 / 引导期 |
Disk |
宿主文件系统原样(工具链兼容) |
| 本地持久化主形态 |
Virtual |
单工件自描述 + 元数据面 11-33× + 精确卷几何 + 断电自恢复 + dd 级迁移 |
| 云归档 / 多地容灾 / 弹性容量 |
Remote |
对象存储生态(成本 + 持久性 SLA) |
10. 并发与扩展性(四类文件系统 × 5 负载形态 × 1-16 线程梯度——probes/IoConcurrencyProbe)
2026-08-19 空闲窗实测(12 核,两轮复跑格局一致)。读维为每线程独立句柄(引擎读池形态——
单句柄多线程读不在 IFileHandle 契约内:Remote 读句柄缓存非线程安全,Mem/Disk/Virtual 单句柄
并发虽巧可跑、不构成承诺)。追加为同句柄多线程(Append 文件级原子预留——契约内)。
10.1 并发追加(同文件 64KB,MB/s)
| 线程 |
Disk |
Mem(Sparse) |
Mem(Reserved) |
Virtual |
Remote(staging) |
| 1 |
1,108-1,330 |
1,296-1,520 |
~22(换租税) |
1,250-1,270 |
380-420 |
| 4 |
290-1,250 |
2,470-2,750 |
~23 |
300-600 |
120-320 |
| 16 |
50-1,050 |
2,840-3,300 |
~21 |
28-590 |
130-410 |
- Mem(Sparse) 近线性扩展(1.5→3.6 GB/s,2.4×):RW Gate + 免清零租借(整页覆写零清零税)
- 逐页池化分配——写并发的主力形态;
PreallocateSize 预分配后页表全命中,
追加 = 纯 memcpy 热道(1415→1568 MB/s 单写者);
- Mem(Reserved) 追加恒 ~22 MB/s 不是并发问题:Reserved 追加越过 EOF 必经 Grow 换租
(O(n) memcpy/次——文件系统固有,io.md §8.10);原地覆写形态下 Reserved 写 13-26 GB/s(§10.3);
- Disk 波动大(内核 inode 锁 + 回写竞争,环境负载敏感);
- Virtual 多线程反扩展(1,250→~300):已知形态——当前写路径全局元数据锁(单写者模型,正确性优先),
多写线程 = 争用税无并行收益。消费含义:Virtual 上的并发写应该用单写者句柄 +
Append 原子预留
(多线程共用一个句柄天然串行化),或上层自己做写聚合;写路径锁分段是后续优化方向;
- Remote staging 层并发追加 ~150-420 MB/s(内存层 + 连接管理竞争)。
10.2 并发热随机读(同文件 16MB 热集,每线程独立句柄,M ops/s)
| 线程 |
Disk |
Mem(Sparse) |
Mem(Reserved) |
Virtual |
Remote |
| 1 |
1.0-1.1 |
6.1-6.4 |
6.4-6.7 |
3.0-3.6 |
0.14-0.15 |
| 4 |
3.6-3.9 |
4.3-4.4 → 18.0-23.1† |
20.1-23.1 |
8.6-10.1 |
0.13 |
| 8 |
6.5-7.1 |
3.6-4.2 → 21.9† |
31.7-37.5 |
12.0-14.5 |
0.11 |
| 16 |
6.1-7.8 |
3.8-4.3 → 14.0† |
35.4-40.7 |
8.2-9.0 |
0.02-0.03 |
† Sparse 的 RW Gate 升级(原裸 monitor 读者互斥且被写者饿死):读共享后并行 4-5×。
- Mem(Reserved) 读扩展 5-6×(6.4→35-40M ops/s):epoch 锁外读者 + freeze 屏障的完全兑现——
读者互不阻塞、不被写者阻塞(§10.3 混合形态同样成立);
- Mem(Sparse) 升级后读也并行(4-22M):per-file Gate 从裸 monitor 换
SpinRWLock(LockWord 时代)RW 语义——
并发读者互不阻塞;16 线程回落 = CAS 读计数热点;
- Virtual 读路径并行扩展 3.3-4×(3.0→12-14.5M ops/s @8 线程):锁外快照读(区间列表 CoW + epoch
延迟回收)的实测兑现;16 线程回落 = 12 核物理上限 + 环境负载;
- Disk 随内核 pread 并行扩展(7.8×@16);Remote 受连接与缓存装载竞争限制。
10.3 混合读写(1 写者 64KB 原地覆写 + N-1 读者 4K 随机读同文件;写 MB/s / 读 M ops/s)
写者用既有数据内轮转覆写(引擎页更新形态)——消除 Reserved 追加越 EOF 的 Grow 换租混杂变量
(Reserved 追加换租是文件系统固有成本,见 io.md §8.10)。
| 总线程 |
Disk |
Mem(Sparse)† |
Mem(Reserved) |
Virtual |
| 2 |
5,929 / 1.0 |
19,205 / 0.00 → 6.1† |
22,793 / 6.1 |
4,188 / 0.00 |
| 4 |
4,941 / 2.6 |
10,416 / 6.3† |
20,277 / 16.6 |
2,900 / 0.00 |
| 8 |
4,730 / 5.6 |
3,299 / 9.4† |
13,876 / 27.9 |
3,037 / 0.01 |
| 16 |
3,396 / 6.0 |
1 / 12.5†(写者饿死) |
9,227 / 27.8 |
3,598 / 0.03 |
† Mem(Sparse) 的 per-file Gate 已升级 RW 语义(原裸 monitor):
升级前读者 0.2-0.5M ops/s(高频写者下饿死——monitor 无公平性)→ 升级后 6.3-12.5M(30-60×),
读写并存成为可用形态;代价 = ≥16 读者极端下写者退化(RW 锁无公平队列,读者持续涌入时排他难插)。
- Mem(Reserved) 仍是混合负载的生产答案:写 9-22 GB/s 与读 6-28M ops/s 同时成立且无饿死面
(epoch 锁外读者 + freeze 屏障);Sparse 2-8 线程内读写并存可用(写 3-19GB/s + 读 6-9M),
极端读并发(≥16)或写延迟敏感场景仍选 Reserved;
- Disk 混合最均衡:pread 无锁(读者 8.1M)+ 缓冲写 4-6 GB/s;
- Virtual 单写者模型的已知代价:数据面覆写本身很快(3-6.6 GB/s——无分配无结构变更),但每写过
全局元数据锁,饱和写者下读者快照捕获排队(0.00-0.03M);写静止时读并行如常(§10.2 的 12M ops/s)。
消费含义:Virtual 上读写并发负载 = 写者限速/攒批,或读写分文件(段模型天然如此);锁分段是后续优化方向。
10.4 并发 Open/Close(K ops/s)
| 线程 |
Disk |
Mem |
Virtual |
Remote |
| 1 |
107 |
7,161 |
3,894 |
2 |
| 8 |
687 |
3,535 |
3,416 |
9 |
- Virtual 单线程 3.9M ops/s = Disk 的 36×(内存元数据直达);多线程缓降(登记/共享设施竞争)但
8 线程仍是 Disk 的 5×;
- Mem 同型态(7.2M 单线程最高,反扩展至 3.2M);
- 网络文件系统每次 Open = 网络往返(2K ops/s)——网络文件系统高频开关是反模式。
10.5 并发独立文件追加(N 文件 N 线程,MB/s)
| 线程 |
Disk |
Mem |
Virtual |
Remote(staging) |
| 1 |
1,400 |
1,400 |
1,300 |
300 |
| 16 |
560-1,260 |
3,400-3,600 |
19-24 |
560-750 |
- Mem 独立文件近线性(数据面隔离 + 逐文件并行)——多文件并发写的主力形态;
- Virtual 全局元数据锁在多文件写下争用放大(每文件追加都过同一把锁——19-24 MB/s):与 §10.1 同根
(单写者模型),多文件形态更吃亏;消费含义:Virtual 卷上的多写入者负载应在上层聚合为单写者
(这正是存储引擎段模型的标准形态——一个段一个写者);
- Disk 独立文件并行最好情形 ~1.3 GB/s(内核 per-inode 锁真隔离)。
10.6 并发规范总结
- Virtual = 单写者模型(v1 已知边界):写路径全局锁——并发写(同文件/多文件)反扩展。正确姿势 =
单写句柄 +
Append 原子预留(多线程共句柄自然串行)或上层写聚合;读路径锁外快照真并行(3.6×)。
- Mem 模式分工:Sparse 的 per-file Gate 已是 RW 语义(读共享写独占)——混合负载
读写并存(2-8 线程写 3-19GB/s + 读 6-9M ops/s);Reserved 仍是读写双高的生产答案(无锁直址 +
epoch 锁外读,无饿死面);≥16 读者极端下 Sparse 写者退化(RW 锁无公平队列)——此时必须 Reserved。
- Disk = 混合负载最均衡:无锁 pread 让读者不吃写锁;多文件并行真隔离。
- Remote = 并发收益在网络侧不在桥侧:staging 内存层并发有限;
MaxConcurrency(默认 4)才是
网络文件系统并发的正确旋钮(Flush 并行上传)。
- 跨文件系统通用:
Append 同句柄多线程安全(原子预留——契约内);单句柄多线程 Read 不在契约内
——并发读用多句柄(Virtual/Mem/Disk 恰好能跑也不依赖)。
10.7 生产可用性判定(按负载形态逐项给结论)
| 负载形态 |
判定 |
依据 |
| 单写者追加/日志卷(Virtual) |
✅ 生产就绪 |
追加 1.2-1.6 GB/s(Disk 持平);fsync 钉硬件地板(564μs vs Disk 490μs);断电自恢复契约测试锁定 |
| 多读者并发扫描/点查(Virtual) |
✅ 生产就绪 |
读扩展 3.3-4×(14.5M ops/s @8T);随机读热 240ns/读(Disk 3.8×) |
| 高并发读写并存(Mem) |
✅ 生产就绪 |
Reserved:写 9-22 GB/s 与读 6-28M ops/s 同时成立(§10.3);Sparse(RW Gate)2-8 线程读写并存可用 |
| 元数据面重负载(Virtual) |
✅ 生产就绪 |
Open 4.6M ops/s(Disk 35×);并发 Open/Close 8T 仍 3.2M(Disk 5×) |
| 网络文件系统 group commit |
✅ 生产就绪 |
桥层 870 MB/s;增量 Flush 出口流量 O(增量);网络侧按部署实测 |
| 读写并发同文件(Virtual) |
⚠️ 形态受限(有明确姿势) |
饱和写者下读者排队(0.01M)——写者限速/攒批或读写分文件(段模型天然如此);锁分段是后续优化方向 |
| 多写入者(Virtual) |
⚠️ 形态受限(有明确姿势) |
并发写反扩展(单写者模型)——上层聚合为单写者 + Append(存储引擎段模型的标准形态) |
| 逐写 Flush(网络文件系统) |
❌ 反模式 |
26-40ms/op(对象版本粒度)——网络文件系统持久化永远 group commit |
总判:IO 层在契约承诺的负载形态内全部达到生产性能(数据面带内持平 + 元数据面一个数量级优势 +
并发读真扩展 + fsync 硬件地板);两个受限形态(Virtual 混合读写/多写者)是 v1 单写者模型的已知边界而非
缺陷——消费姿势已在 §10.6 钉死,与存储引擎"一个段一个写者"的段模型天然对齐。后续优化方向:
Virtual 写路径锁分段 / Mem Reserved 追加快道(Grow 换租)/ Sparse RW Gate 公平性(极端读者下写者退化——
高并发场景用 Reserved 即绕开)。
11. 方法学规范(数字可信的前提)
- 定量工作/op(BDN):每 op 固定工作量,Mean = 每 op 成本、Ratio 可比、Alloc/op 有意义。
自旋窗式(while elapsed < N ms)已废弃——Mean 恒等于窗长、Ratio 失义(曾因此返工,防重蹈)。
- 迭代间重置:追加维每 op 删建文件(
IterationSetup)——否则预分配 × 迭代数打满卷(DiskFull 假阴性)。
- 空闲机终判 ±5%:共享机负载波动 3× 时数字失真(Disk 自身可退化 100×);正式结论 load < 1.2 实测。
- fsync 维沉降:前序基准的内核回写积压会污染 fsync 段(单 inode fsync 付全部积压 vs 多 inode 的测量不对称)。
- 探针 vs BDN:探针(DiskVsRawProbe)快速肉眼对照;正式数字走 BDN(进程隔离 + 预热 + 多轮)。
12. 已知边界
- dev 机基线:绝对值不可外推到生产硬件(NVMe/云盘差异大);比值与结论跨硬件稳定。
- Virtual 追加维 0.86×(BDN create 重载形态——每 op 删建文件,建文件路径税 vs ext4 内联建文件;稳态持平)
——观察项:海量小文件建卷负载再议。
- 4Kn 真扇区/Windows 载体/dm-flakey 故障注入矩阵未跑(需 root/Windows 环境)。
- MinIO loopback ≠ 真云:RTT < 1ms 掩盖了 WAN 延迟(真云 Range GET p50=48ms——§7.3 COS 对照);
§7/§9 的 Remote 数字量化的是桥层成本结构(staging/缓存/Flush 编排),网络侧按部署实测。
- Virtual 写路径锁分段未做(§10.1/§10.5 反扩展的根):单写者模型下多线程写无并行收益——
后续优化方向 = 写锁分段(段级/文件级)+ 位图分块锁;当前消费姿势 = 单写者 + Append。