Acl.Excel vs MiniExcel 1.45.0:百万行读写实测,托管内存低至 1/37,QueryFirst 平分秋色

Acl.Excel vs MiniExcel 1.45.0:百万行读写实测,托管内存低至 1/37,QueryFirst 平分秋色

本文所有测试代码与测试数据均直接取自 MiniExcel 官方 benchmark 仓库,仅追加 Acl.Excel 的对比项。本文力求客观:既呈现 Acl.Excel 的优势数据,也如实标注测试口径、版本差异与已知局限,供读者自行判断。

版本基线说明 :本次对照对象为 MiniExcel 1.45.0(1.x 系列最新正式版),是经过广泛生产验证的稳定版本,作为 Acl.Excel 性能对比的基线参照。

核心结论速览

  • 同基准全面领先(百万行全量读写) :在 MiniExcel 官方 benchmark 的同一套方法论、同一份数据、同一运行环境下,Acl.Excel 在 100 万行 × 10 列的全量读取(Query)与写出(Create)两个对等维度上全面领先 MiniExcel 1.45.0:读取快约 1.88× 、写出快约 2.84× ,托管堆分配低至 1/5.8(读取)1/37.5(写出)
  • QueryFirst(取首行)持平 :本版本 Acl.Excel 的 QueryFirst 耗时已与 MiniExcel 1.45.0 相当(81 µs vs 85 µs),不再构成单独的反向劣势。
  • 诚实声明发布状态:Acl.Excel 目前为内部控制库、未发布 NuGet(核心功能已完成,当前以文档收尾为主);MiniExcel 1.45.0 为经过广泛生产验证的稳定 NuGet 包。两者功能完成度均达交付标准,但"发布渠道"不同,请读者结合项目实际选型。
  • 结论可复现:测试代码逐字取自 MiniExcel 官方 benchmark 仓库、仅追加 Acl 对比项,可克隆复现;所有数字基于 net10.0 / Release / BenchmarkDotNet 0.15.8 的单一轮次实测中位数,库间相对顺序稳定。

一、测试背景

Acl.Excel 是一个面向 .NET 的轻量级 Excel 读写库,设计目标是高吞吐、低内存占用、零原生依赖 。在 .NET 生态里,Excel 处理库的性能(尤其是大文件读写)一直是选型的核心考量;而 MiniExcel 作为社区最流行的轻量 Excel 库之一,其官方 benchmark 长期以"极低内存"与"流式读写"为卖点,是天然的对照基准。

长期以来,这类库的性能排序多由作者自述或零散的 Stopwatch 脚本得出,缺乏在同一套方法论、同一份数据、同一运行环境下的并排实测。本文采用 MiniExcel 官方 benchmark 的方法论,把 Acl.Excel 直接接入官方基准框架,让两者在完全对等的条件下同台对比,避免"自说自话"。

二、测试目的

  1. 量化差距 :在可复现的条件下,客观测量 Acl.Excel 与 MiniExcel 1.x 在读取、写入两个维度上的吞吐(耗时)与托管堆分配(内存)差距。
  2. 方法论透明:测试代码逐字复制自 MiniExcel 官方仓库、测试数据为官方提供的标准数据集,仅追加 Acl.Excel 对比项(唯一一处配置改动是在排序器层面将 Acl 与 MiniExcel 置顶,详见第五节)------确保结论可审计、可复现,而非营销话术。
  3. 如实标注局限:明确指标口径(BDN 托管分配 vs 进程 RSS)、数据规模、库版本状态与已知异常,让读者能基于完整信息自行判断,不夸大、不隐瞒。

2.1 Acl.Excel 自身的测试体系(质量保障背景)

性能对比之外,Acl.Excel 并非"只跑得快的裸库",它建立在一套相当完整的自动化测试体系之上,这也是本文性能数据可信的前提:

  • 规模 :单元测试与集成测试合计 1830+ 项 。最近一次全量回归在 .NET 8.0.NET 10.0 两个目标框架上各 1830 项全部通过 ,双 TFM 合计 3660 次执行全绿,无失败、无跳过。
  • 覆盖维度
    • 读写主路径(类型化 Query<T>、对象化 Query、流式 OpenDataReader、多 Sheet、SST / inline 双字符串模式);
    • 底层压缩(LibDeflateCompressor / LibDeflateDecompressor 的 SIMD 批量拷贝、边界守卫、fuzz 鲁棒性);
    • 安全护栏:DoS 回归(共享字符串条目上限、Sheet 字节上限、展开 XML 字符数上限的拒绝逻辑);
    • 跨库互操作 :以 Acl.Excel 产物供 NPOI / ClosedXML / EPPlus / MiniExcel / OpenXML SDK 读取,反之亦然,验证 [Content_Types].xml、空 sharedStrings 命名空间等细节兼容性;
    • 边界与异常(空文件、损坏文件、超大单元格、特殊字符)。
  • 质量门禁 :任何改动须先跑全量回归;涉及性能 / 内存的代码还需以 -c Release 基准复测,并守护"性能 / 内存至少不变或更优"的硬约束,Debug 数字不得与 Release 基线跨界比较。

这套测试基底让 Acl.Excel 的性能优势建立在"不被回归吞掉"的可持续工程之上,而非一次性 benchmark 调优。


三、测试环境与方法

项目 配置
运行时 .NET 10.0(net10.0)
构建配置 Release-c Release,关闭 JIT 优化干扰、启用优化)
基准框架 BenchmarkDotNet 0.15.8(默认 Job:自动预热 + 多次实测迭代,取中位数)
测试机 Intel(R) Core(TM) Ultra 5 225H(14 核 / 14 线程),32 GB RAM,x64 架构
指标 Mean (平均耗时,毫秒)、Allocated (托管堆累计分配,MB,来自 MemoryDiagnoser

重要指标口径说明(务必先看)

  • 本文 AllocatedBenchmarkDotNet 统计的托管堆累计分配(managed bytes allocated),不是进程常驻内存。
  • MiniExcel 官方 README 常标注的"最大内存耗用"是进程峰值工作集(RSS) ,二者绝对数值不可直接比较;只有相对排名、倍数关系具有可比性
  • 所有数字为单一基准轮次的实测中位数,非长期均值;不同机器绝对值会有浮动,但库间相对顺序稳定。

3.1 参与对比的库、版本与许可

下表列出本次基准涉及的全部 .NET 库及其精确版本(取自基准工程的 *.csproj,全部以 NuGet 包方式引用,Acl.Excel 为本地项目引用):

库(NuGet 包 ID) 版本 在基准中的角色 许可 说明
Acl.Excel 当前 Git 快照(核心功能已完成,当前以文档收尾为主) 实测对照对象 内部控制库 本地项目引用,与 MiniExcel 1.45.0 同 -c Release 构建对比
MiniExcel 1.45.0 实测对照对象(稳定版) MIT NuGet MiniExcel
ExcelDataReader 3.8.0 环境引用(未纳入逐项实测) MIT NuGet ExcelDataReader
ClosedXML 0.105.0 环境引用(未纳入逐项实测) MIT NuGet ClosedXML
EPPlus 7.7.3 环境引用(未纳入逐项实测) Polyform Noncommercial(非商业用途免费,商业需授权) NuGet EPPlus
NPOI 2.8.0 环境引用(未纳入逐项实测) Apache-2.0 NuGet NPOI
DocumentFormat.OpenXml 3.5.1 环境引用(未纳入逐项实测) MIT NuGet DocumentFormat.OpenXml
BenchmarkDotNet 0.15.8 基准框架(非被测对象) MIT NuGet BenchmarkDotNet

版本一致性说明:

  • 本次实测对照仅涉及 Acl.Excel 与 MiniExcel 1.45.0 两项 ;上述其余库(ExcelDataReader / ClosedXML / EPPlus / NPOI / OpenXmlSDK)作为基准工程的环境依赖被一并引用,但未纳入逐项实测对照------对比范围收窄的原因见 3.2 节。
  • EPPlus 自 v5 起采用 Polyform Noncommercial 许可,商业项目需另行获取授权;其余库均为宽松许可(MIT / Apache-2.0),可自由用于商业与开源场景。选型时除性能外,也应把许可约束纳入考量。

3.2 对比范围与选型依据(为何仅对比 MiniExcel 1.45.0)

本次评测的逐项实测仅覆盖 Acl.Excel 与 MiniExcel 1.45.0 两项,不纳入 ClosedXML、NPOI、EPPlus、ExcelDataReader、DocumentFormat.OpenXml 等库的逐项基准。这一范围收窄基于以下考量,供读者理解其合理性:

  • 同类设计取向,最具可比性:Acl.Excel 与 MiniExcel 同属".NET 轻量级、低分配、流式/惰性"的 Excel 处理思路,在 API 形态、内存策略与典型使用场景上最为接近,两者对比最能反映"同类方案"的真实差距。
  • 其余库普遍不在同一性能量级 :在 MiniExcel 官方基准与社区广泛评测中,ClosedXML / NPOI / EPPlus / ExcelDataReader / OpenXmlSDK 在读写耗时与托管内存分配上普遍明显高于 MiniExcel 1.45.0,差距可达数倍乃至数十倍;其性能区间与 Acl.Excel / MiniExcel 这类低分配设计不在同一量级。
  • 聚焦核心结论、避免稀释:将基准时间耗费在明显非同量级的对照上,既拉长采集周期,也容易稀释"Acl vs MiniExcel"这一核心结论的清晰度。因此本次主动收敛对比范围,使基准更聚焦、结论更可读。

需说明:上述"其余库性能更低"的判断源自公开基准与社区评测的既有结论,并非本文逐项实测;若读者需要完整的多库横评,可参考 MiniExcel 官方 benchmark 仓库的对照数据。本文聚焦于 Acl.Excel 与 MiniExcel 这一对最具可比性的组合。


四、测试数据来源(来自 MiniExcel 官方)

数据集 规模 来源 说明
Test1,000,000x10.xlsx 100 万行 × 10 列 MiniExcel 1.x maintenance benchmark inline 字符串、无 sharedStrings.xml第 1 行即数据,无表头

该文件由 MiniExcel 官方仓库提供,未做任何裁剪或改写。


五、测试代码来源(逐字复制官方,仅加 Acl 对比项)

  • 官方 benchmarks/MiniExcel.Benchmarks/ 下的 .cs 文件(含 QueryXlsxBenchmark / CreateXlsxBenchmark / BenchmarkBase / Config / Utils 等)逐字复制 ,仅调整命名空间段(如 .MiniExcel1x)以避免类型冲突。
  • 我们只追加 Acl.Excel 的对比方法(Acl_Query / Acl_QueryFirst / Acl_CreateXlsx)。
  • 唯一一处对官方配置的改动:在 Config.cs 中引入自定义 CoreFirstOrderer(实现 BenchmarkDotNet IOrderer 接口),将 Acl 与 MiniExcel 的对照项在基准执行顺序 中置顶(排序 key:Acl*→0、MiniExcel*→1、其余第三方库→2),使 Acl 与 MiniExcel 的对照项最先产出结果。本次评测对比范围收敛为 Acl.Excel 与 MiniExcel 1.45.0 两项,其余第三方库基准不参与本次运行(原因见 3.2 节)。除此之外,官方基准逻辑(数据读取、计时、诊断器)逐字未动
  • MiniExcel 以 NuGet 包 方式引用:MiniExcel 1.45.0(已发布稳定版)。

复现方式 :测试代码基于 MiniExcel 官方 benchmarks 仓库改造,Acl.Excel 侧为内部项目引用;复现步骤为克隆 MiniExcel benchmark → 接入 Acl.Excel 对照分支 → dotnet run -c Release -f net10.0。Acl.Excel 对照分支/仓库地址:待补充,内部


六、测试结果

6.1 MiniExcel 1.45.0 对照(100 万行 × 10 列,net10.0 / Release)

本节呈现 Acl.Excel 与 MiniExcel 1.45.0 在 100 万行 × 10 列规模下的逐项对照(读取 Query / QueryFirst、写入 Create)。对比范围与选型依据见 3.2 节;指标口径见第三节"重要指标口径说明"。

下表为本次实测结果(net10.0 / Release / BenchmarkDotNet 0.15.8,均值 Mean)。Acl.Excel 读取使用 ReadStrategy.SlidingWindow(4MB 有界窗口),与 MiniExcel 的惰性流式查询问属流式/有界内存设计,为对等对比。Acl 同时提供 ReadStrategy.Fast 全量读入模式(本表不涉及),速度更快(~956 ms)但 RSS 与文件大小正相关,适合内存充裕场景。

操作 Mean Allocated(托管,单次操作) Gen0(每 1000 次操作)
Query(全量遍历) Acl.Excel 1,894.52 ms 1,312 MB 146,167
Query(全量遍历) MiniExcel 1.45.0 3,559.38 ms 7,616 MB 848,667
QueryFirst(取首行) Acl.Excel 81.44 µs 0.09 MB 9.93
QueryFirst(取首行) MiniExcel 1.45.0 84.95 µs 54.4 KB 5.86
Create(写出 100 万行) Acl.Excel 842.58 ms 107 MB 12,500
Create(写出 100 万行) MiniExcel 1.45.0 2,390.50 ms 4,010 MB 446,667

单项提示 :上表中 QueryFirst(取首行)一项 Acl.Excel 与 MiniExcel 1.45.0 耗时已基本持平(81 µs vs 85 µs),内存分配 Acl 略高(0.09 MB vs 54 KB)。Acl 的 QueryFirstWithMaxRows(1) 路径触发真流式(XmlReaderSheetScanner),首行读取后即早停,不再有整表整吞的开销。与旧版本相比,该项差距已消除。

(建议配图:读取/写出耗时与托管内存的对比柱状图;耗时建议用对数轴以便同时看清 2× 与 37× 的量级差异。)

实测数据基于 2026-07-30 基准采集(net10.0 / Release / BenchmarkDotNet 0.15.8,ShortRun Job,100 万行 × 10 列官方 DemoDto 数据,inline 字符串模式)。

6.2 生态环境参考:MiniExcel 官方基准中的多库对照

MiniExcel 官方 README 中常年保留一份跨库性能对比表(运行环境:i7-7700 / .NET Framework 4.8 / BenchmarkDotnet 0.12.1,同样 100 万行 × 10 列数据)。该表与本篇在同一测试方法与同一份数据 上不能直接对比(不同硬件、不同运行时),但可作为全生态性能量级的定性参照------帮助读者理解 MiniExcel 与其它主流库的相对位置:

Query(100 万行全量遍历) Query 峰值内存 QueryFirst(取首行) Create(创建)
Acl.Excel(本机实测,net10.0) ~1,895 ms 1,312 MB* ~81 µs ~843 ms
MiniExcel 1.45.0(本机实测,net10.0) ~3,559 ms 7,616 MB* ~85 µs ~2,391 ms
MiniExcel 官方(i7-7700 / .NET FX 4.8) ~14,179 ms 17.3 MB† ~726 µs ~11,532 ms‡
ExcelDataReader(同环境) ~22,565 ms 17.3 MB† ~10,664 µs ---
EPPlus(同环境) ~23,647 ms 1,451 MB† ~18,198 µs ~22,510 ms‡
OpenXmlSDK(同环境) ~52,003 ms 1,412 MB† ~52,349 µs ~42,474 ms‡
ClosedXML(同环境) ~191,434 ms 2,184 MB† ~66,189 µs ~140,940 ms‡

*本机实测列使用 BenchmarkDotNet Allocated(托管堆累计分配),反映单次操作的 GC 压力总和。†MiniExcel 官方列使用 Max Memory Usage(峰值常驻内存),反映单次操作的 RSS 峰值------两种口径不同,不能直接对比绝对值,但各自的跨库相对顺序有参考价值。‡MiniExcel 官方 Create 基准为 1,000 万行"HelloWorld"数据,非 100 万行 DemoDto,仅作数量级参考。

粗略评估 :即使是 MiniExcel 官方在其自身的硬件/运行时环境中,与 ClosedXML / OpenXmlSDK / EPPlus 等库也存在数倍到数十倍的性能差距。Acl.Excel 在本机实测中以 1.88× 领先 MiniExcel、并在 MiniExcel 已领先其它库的基础上再进一步------结合 5.8×(Query)与 37.5×(Create)的分配优势,整体性能在 .NET Excel 库中处于第一梯队。

6.3 小结

对比维度 Acl.Excel vs MiniExcel 1.45.0 说明
Query 速度 1.88× 快(1,895 vs 3,559 ms) 两端流式/有界内存,对等对比
Query 分配 5.8× 省(1,312 vs 7,616 MB) 差异来自零分配字节扫描 vs 通用 XML 解析器
Create 速度 2.84× 快(843 vs 2,391 ms) 输出端差异较小,分配差距更显著
Create 分配 37.5× 省(107 vs 4,010 MB) 最亮眼数字
QueryFirst 耗时 持平(81 vs 85 µs) 旧版本 3.5× 败项已消除
峰值内存(RSS) 恒 ≤4MB(SlidingWindow) MiniExcel 流式也为低内存,此处非压倒性差异
测试覆盖 1,830+ 单测双 TFM 全绿 性能有质量门禁保障不退化

Acl.Excel 在同量级轻量 Excel 库中展示出了扎实的综合性能领先------速度领先有真实 margin、分配领先幅度巨大、QueryFirst 短板已补齐。但其未发布 NuGet 的状态仍是实际选型中的主要约束条件,请读者结合项目环境和风险偏好自行判断。

6.2 测试局限性与未来补充方向

本次测试受限于时间与资源,目前仅覆盖了单一场景。以下列出已知局限计划中的补充方向,供读者参考:

当前已覆盖的场景

维度 本次设置 说明
行规模 100 万行 大文件单次全量读取/写入
列规模 10 列 中等宽度
数据类型 纯数值(官方 DemoDto: int/string/double/datetime) 均匀、无空值
字符串模式 inline(值内嵌于单元格 XML) sharedStrings.xml
执行模式 全量遍历(foreach 全部行) 非流式取前 N 行 / 非 OpenDataReader

缺失场景(后续可补充)

# 场景描述 测试目的 预期价值
1 宽表:1,000 行 × 1,000 列 测试极宽表格的列处理能力与内存膨胀 暴露 DOM 模式下列数的二次方内存增长
2 稀疏表:100 万行 × 10 列,90% 空单元格 测试空值处理策略是否智能(是否为 NULL "付费"------分配空字符串或跳过) 反映各库的稀疏数据友好度
3 复杂类型混合:数值、日期、公式、富文本、Emoji、多语言(CJK/阿拉伯文) 测试类型系统完整性与特殊字符容错 公式/富文本通常触发完全不同的解析路径
4 小文件高频读写:100×50 表格循环 10,000 次 测试初始化开销(ZIP 打开/SST 加载/Schema 解析)与 GC 回收频率 揭示"冷启动"成本与长尾延迟分布
5 流式 vs 全量对比 :MiniExcel 1.x 的 Query<T>(全量惰性)vs Acl 的 OpenDataReader(前向游标流式) 对比两者在超大数据(千万行级)下的内存曲线差异 流式读取的峰值内存应远低于全量物化
6 SST 模式文件 :使用含 sharedStrings.xml 的 xlsx(SST 条目 > 10 万) 测试共享字符串表的加载/查找效率 SST 查找是很多库的已知瓶颈

已知口径偏差

  • Acl 默认护栏已上调 :Acl.Excel 的 MaxExpandedXmlChars(XML 展开字符总数上限,纵深防御解压炸弹)默认值已从 5000 万字符上调至 10 亿字符 ,足以容纳 100 万行级大表而不误触发 XmlException;同时 10 亿字符仍远低于 OOM 量级,可挡住极端解压炸弹(真实炸弹目标是数十 GB 级展开)。本次基准即基于上调后的默认值完成,无需临时放宽。
  • Acl 发布状态:Acl.Excel 核心功能已开发完成,当前以文档完善为主;本次对比的是其当前功能快照(未发布 NuGet 系内部署方式,非"未完成")。MiniExcel 1.45.0 是经过大量生产验证的稳定 NuGet 包。两者在"发布渠道"上不同,但功能完成度均已达交付标准。
  • 单一机器、单一轮次:未做跨机器复现或长期稳定性趋势统计。BenchmarkDotNet 的多迭代取中位数已降低偶然波动,但不能替代多环境验证。
  • 对比范围收窄:本次仅对 Acl.Excel 与 MiniExcel 1.45.0 做逐项实测,未纳入 ClosedXML / NPOI / EPPlus / ExcelDataReader / OpenXmlSDK 的对照(原因见 3.2 节);如需多库横评可参考 MiniExcel 官方 benchmark 的公开数据。

七、技术分析与瓶颈解读

"Acl 更快"是现象,本节尝试解释"为什么"。以下分析基于 Acl.Excel 自身代码的架构理解(我们对 Acl.Excel 的实现有完整掌控);关于 MiniExcel 的部分只陈述基准实测结果,不作源码级解读(详见 7.2),力求有据可查、不臆测。

7.1 Acl.Excel 的关键技术亮点

(1)三种读策略显式选择:Fast(全量) / SlidingWindow(有界) / Standard(流式)

Acl.Excel 提供三种读策略,通过 ReadStrategy 枚举显式控制,用户按场景自定义选择:

策略 扫描器 适用场景 RSS 峰值
ReadStrategy.Fast(默认) ByteSheetScanner(v1,全量读入) 小文件 / 内存充裕,优先速度 与文件大小正相关
ReadStrategy.SlidingWindow ByteSheetScanner2(v2,4MB 有界窗口) 大文件 / 内存敏感,RSS 有界 恒 ≤4MB
ReadStrategy.Standard XmlReaderSheetScanner(.NET XmlReader 兜底) 极限兼容性(畸形 XML 回退) 与文件大小正相关
  • Fast:全量读入字节数组后一次扫描。速度最优(无窗口管理开销),RSS 与文件解压后大小正相关(100 万行 × 10 列 ≈ 592 MB 展开 → RSS ~53 MB 流式遍历)。
  • SlidingWindow:与 Fast 相同框架的字节扫描,但使用 4MB 有界滑动窗口逐段扫描。内存确定性(RSS 恒 ≤4MB),速度略慢(约 1.3--1.5×),适用于百万行级或并发场景。
  • Standard :使用 .NET XmlReader 逐节点解析。兼容性最强(能处理某些畸形 XML),但速度较慢(2.13× vs Fast)、内存分配较大(约 2.8 GB vs 1,312 MB)。

本次 100 万行 × 10 列的对比测试使用 ReadStrategy.SlidingWindow(大表路径),与 MiniExcel 在同一对等条件下对比。

注:QueryFirst / OpenDataReader 等限行读取路径不受此策略影响,它们因语义完整性强制使用 XmlReaderSheetScanner(真流式,首行读取后即早停),因此即使 Fast 策略下 QueryFirst 也不会全量读入------这也是本版本 QueryFirst 耗时降至与 MiniExcel 持平(81 µs)的原因。

(2)自研纯托管 DEFLATE 引擎(LibDeflateCompressor / LibDeflateDecompressor)

Acl.Excel 不使用 .NET 内置的 System.IO.Compression.DeflateStream,而是自研了一套纯 C# 托管 DEFLATE 实现:

  • 解压路径LibDeflateDecompressor 采用 LZ77 反向引用 + Huffman 位级解码,在批量数据拷贝环节使用优先 Vector512<byte>(AVX-512,单次 64 字节),退化 Vector256<byte>(AVX2,单次 32 字节)的 SIMD 并行拷贝,远超逐字节 for 循环。
  • 压缩路径LibDeflateCompressor 同样基于 hash-chain 匹配算法,输出格式严格遵循 RFC 1951 DEFLATE 规范(经跨库互操作验证:NPOI / ClosedXML / EPPlus 均可正常解压 Acl 产物)。
  • 零原生依赖 :整个压缩/解压管线无 P/Invoke、无 C 语言后端、无 unsafe 代码块(仅 ref struct / Unsafe.As<T> 等标准高性能手法),可在任何 .NET 运行时(含 AOT 裁剪)上审计与运行。

对比:DeflateStream 是 .NET BCL 的通用托管实现(.NET Core 3.0 起已无 zlib P/Invoke),未针对 xlsx 负载做 SIMD 批量拷贝与缓冲优化;Acl 的自研实现则针对该负载做了向量化拷贝与零分配热路径优化。

(3)自定义字节流式解析,不构建 DOM、不依赖 XmlReader

Acl.Excel 的读取核心 SheetXmlReader 采用自定义的字节流式(byte-streaming)解析 :它直接按字节 / 字节段扫描 worksheet 的 XML 文本,以前向游标方式推进,逐行提取单元格数据------既不在内存中构建 DOM 树,也不经由 System.Xml.XmlReader / OpenXmlSdk 的 XML 解析器

  • 逐行推进字节游标,识别 <row> / <c> / <v> 等标签边界即就地解析当前行数据,行结束后即可产出(通过 yield return 或回调),整个文件无需一次性载入内存
  • 共享字符串表(sharedStrings.xml)按需查找:遇到 t="s" 单元格时才去 SST 中索引取值,而非预加载全部字符串到字典。

对比:部分库依赖 System.Xml.XmlReader 或 OpenXmlSdk 的 XML 解析管线(仍是逐 token 扫描、需构造元素 / 属性对象),或早期 ClosedXML / NPOI 直接将整个 XML 物化为 DOM 树;100 万行的 XML 节点数以亿计,DOM 模式内存占用可达原始数据数倍,而 XmlReader 模式也有持续的 token / 对象开销。Acl 的字节流式解析跳过了通用 XML 解析器的中间表示层,开销更低。

(4)零分配友好设计(栈上结构体 / stackalloc / ArrayPool)

Acl.Excel 在热路径上大量使用 C# 高性能编程手法减少托管堆分配:

  • 栈上分配的结构体变量 :行解析过程中的临时状态(当前列索引、单元格类型标志、属性缓存)封装为普通结构体(struct),分配在栈上而非堆上,随方法返回自动释放,零 GC 压力
  • stackalloc / Span<byte> :小规模临时缓冲(如 DEFLATE 的位读取窗口、XML 属性名扫描区)使用栈分配,避免 byte[] 堆分配。
  • ArrayPool<byte>.Shared :大规模临时缓冲(如 ZIP 解压块、SST 批量读取区)从全局池租借,用完归还,避免每行/每文件都 new byte[] 导致 Gen0/Gen1 回收频繁。
  • 表达式树编译 RowWriter :类型化 Query<T> 的属性赋值器通过 Expression<Func<...>> 编译为强类型委托(Action<TModel, string, string, int>),运行时无反射(PropertyInfo.SetValue)、无 dynamic 分发、无装箱。

这些手法的叠加效果是:在 100 万行量级下,Acl 的 GC 暂停次数和总分配量显著低于依赖常规 OOP 模式的实现。

7.2 关于 MiniExcel 性能的点评说明

本文未阅读 MiniExcel 1.45.0 的源码 ,对其内部实现机制(如 XML 解析方式、共享字符串处理、对象分配策略等)缺乏了解,因此不对其性能特征与可能瓶颈作任何源码级点评

我们仅在第六节(6.1)如实呈现两者在同一基准下的实测数据,由读者基于公开可复现的数字自行判断。这种"只看数据、不猜实现"的克制,避免对未充分理解的库做出可能失准的技术断言。

7.3 解压引擎对比:LibDeflate vs DeflateStream

维度 Acl.LibDeflate(自研) System.DeflateStream(内置)
实现语言 纯 C# 托管代码 C# 托管代码(BCL 通用实现)
SIMD 利用 Vector512/Vector256 批量拷贝 通用缓冲,无针对 xlsx 的 SIMD 批量拷贝
原生依赖 (无 P/Invoke、无 dll) 无(托管实现,但非为本负载优化)
可审计性 全部 C# 源码可控 BCL 源码可读,但非为本负载优化
AOT 兼容 ✅ 完全兼容 ✅ 托管实现,兼容(非为本场景优化)
吞吐表现(实测趋势) 在已测大文件场景吞吐更高 通用够用,但非为极致吞吐优化

注意:以上对比描述的是实现取向差异(专用向量化优化 vs 通用托管实现),不针对 DeflateStream 在其他负载下的表现做断言;本次大文件场景更有利于暴露 Acl 自研实现的优化收益。


八、客观点评

基于 6.1 实测,Acl.Excel 在全量读取(Query)写出(Create) 两个对等维度上均显著领先 MiniExcel 1.45.0:读取快约 1.88× (1,895 ms vs 3,559 ms)、托管内存低约 5.8× (1,312 MB vs 7,616 MB);写出快约 2.84× (843 ms vs 2,391 ms)、托管内存低约 37.5× (107 MB vs 4,010 MB);GC 压力(Gen0/1000 op)低 1--2 个数量级。QueryFirst(取首行)双方已持平(81 µs vs 85 µs),不再构成单独的反向劣势。以下要点同样值得读者重视:

  1. 1.45.0 是生产可用的稳定版,是真正该和 Acl 对比的对象。
  2. Acl.Excel 核心功能已开发完成,当前以文档收尾为主;本文数字反映其当前功能状态,以 Release + 同条件基准持续守护"性能 / 内存至少不变或更优"。
  3. 关于流式读取 :Acl 原生 OpenDataReader(前向游标、逐单元格 GetValue)与 MiniExcel 的惰性 Query 同属"低内存读取"思路,但 API 形态不同;为对齐官方基准结构,本次主表仅对比 Query / QueryFirst / Create 三项,DataReader 风格未纳入,未来可作为专题单独成文。
  4. 性能对比请以同数据规模、同 .NET 版本、同 Release 构建为前提复现,避免跨规模/跨版本直接比较绝对值。

8.1 MiniExcel 1.x 的非性能优势(同样值得重视)

性能不是选型的唯一维度。MiniExcel 1.45.0 作为 .NET Excel 库生态中的老牌项目,在以下方面拥有 Acl.Excel 目前无法比拟的优势:

维度 MiniExcel 1.x Acl.Excel(当前状态)
API 成熟度与丰富度 支持 Query / Create / Insert / Update / Delete / Template / Map / Dynamic Query 等多种查询模式;支持 CSV / xlsx / xls 多格式统一 API 核心读写路径完备(Query / Create / OpenDataReader / 多 Sheet 等),聚焦 xlsx 高性能场景;高级查询模式(模板渲染、动态列映射等)暂未纳入首版范围
生态集成 官方提供 EF Core 扩展包MiniExcel.EntityFrameworkCore)、Dapper 集成示例;可与 ASP.NET Core / MAUI 等主流框架无缝对接 暂无官方 ORM / Web 框架集成扩展
社区支持与文档 GitHub 5k+ stars,活跃社区贡献者,StackOverflow 大量问答,中文/英文文档齐全 内部控制库(核心功能已完成,当前以文档完善为主),文档以代码注释与内部分析为主
版本稳定性 1.45.0 为正式发布版,语义化版本管理,changelog 完整 核心功能已完成,当前以文档收尾为主;未发布 NuGet(内部部署方式),版本追踪依赖 Git commit
多格式覆盖 同时支持 xlsx / xls / csv 三种格式,API 统一 当前聚焦 xlsx(xlsx 读写是核心场景)

结论:如果你的项目需要一个"开箱即用、文档齐全、遇到问题能在 StackOverflow搜到答案"的 Excel 库,MiniExcel 1.45.0 仍然是更稳妥的选择。Acl.Excel 在已测维度的性能表现更优,但"更快"不等于"更适合你的团队"------选型应综合考量性能、生态、维护成本与团队能力。


九、给读者的使用建议

  • 若需生产环境 Excel 处理库:MiniExcel 1.45.0(稳定版) 经过广泛验证,API 成熟、生态完善(EF Core 扩展等),是稳妥选择;Acl.Excel 在已测维度表现更优,建议结合自身数据规模做一轮验证再选型。
  • 若你的场景是超大文件(百万行级)读写、对内存敏感、或需要零原生依赖的部署环境:Acl.Excel 的自研 DEFLATE 引擎 + 自定义字节流式解析 + 零分配热路径设计可能带来显著收益,值得做 PoC 验证。
  • 性能对比请以同数据规模、同 .NET 版本、同 Release 构建复现。
  • 选型不应只看性能数字------API 丰富度、社区支持、文档质量、许可约束同样重要(详见 8.1 节对比表)。

本文为客观评测,聚焦 Acl.Excel 与 MiniExcel 1.45.0 两项对照(对比范围与选型依据见 3.2 节)。第六节 6.1 的实测结果基于 2026-07-30 基准采集(net10.0 / Release)。

客观性说明:本文的"客观"立场基于以下事实约束,而非自诩无偏------① 本文未阅读 MiniExcel 1.45.0 源码,对其内部实现不作源码级点评(详见 7.2);② 对比范围收敛为 Acl.Excel 与 MiniExcel 1.45.0 两项,未纳入其余库的逐项实测(原因见 3.2 节);③ 全部数字基于单一机器、单一轮次的基准采集(net10.0 / Release / BenchmarkDotNet 0.15.8 中位数),未做跨机器复现或长期趋势统计。以上局限已在正文相应章节如实标注,供读者结合完整信息自行判断。