.NET 11 性能全解读:从 JIT 到基础库,这一版到底快了多少 - 张善友

.NET 11 性能全解读:从 JIT 到基础库,这一版到底快了多少 - 张善友

💡 原文中文,约105200字,阅读约需251分钟。
📝

内容提要

.NET 11 对 JIT 与运行时进行了持续优化:Arm64 可伸缩向量、SIMD 掩码归约与寄存器分配改进;GC 写屏障、依赖句柄老化与协变检查消除;启动路径、Monitor、BigInteger 及浮点解析大幅提速;UTF-8、Base64、正则与 SearchValues 等文本搜索显著加快;集合与 LINQ 减少重复计算。

🔎

延伸解读

升级即提速,但别盲目乐观

文章强调 .NET 11 无需改代码或配置即可获得性能提升,但所有数据均来自微基准测试。真实应用中的收益取决于具体负载:若某 API 调用频率低,几纳秒的优化毫无意义;若在热路径上高频调用,累积效果才显著。作者建议不要对着基准表格做优化,而应基于自己的火焰图定位瓶颈。

分配归零比耗时下降更值得关注

文中多次指出,许多优化虽然只让耗时降低约 20%,但分配从数十字节变为零分配。零分配对 GC 压力和 P99 延迟抖动的影响往往比墙钟时间更重要。例如可空装箱、枚举器、委托等场景的逃逸分析改进,直接消除了堆分配,这对高吞吐、低延迟服务尤为关键。

runtime async 是实验性开关,需实测

runtime async 将 async/await 的状态机变换从编译器移到 JIT,可减少中间 Task 分配并加速异常传播。但该功能在 .NET 11 中需通过编译器特性开关启用,且尚未完全优化,存在已知低效场景。作者建议在应用和服务中实验并测量,而非默认开启;预计 .NET 12 才可能默认启用。

unsafe 代码值得重新评估

文章提到 .NET 团队审计基础库中的 unsafe 代码,发现许多为规避边界检查而手写的指针或 Unsafe 循环已不再必要。JIT 的边界检查消除和范围分析进步,使安全代码性能接近甚至超过 unsafe 版本。如果你有类似代码,建议在 .NET 11 上用安全 C# 重写并重新测量,可能省去维护风险。

Q&A

升级到 .NET 11 需要修改代码或开启什么配置吗?

不需要。.NET 11 的性能提升是自动生效的,没有新的 API 要学,也没有配置要打开或“高性能模式”要手动切换。你什么都不用改,升级就变快。

.NET 11 在 JIT 方面主要做了哪些优化?

JIT 优化包括:去抽象化(如逃逸分析、泛型虚方法去虚拟化、委托瘦身)、边界检查消除(范围分析、断言传播、循环克隆)、常量折叠、向量化(SIMD)以及简化冗余检查等。这些改进能减少指令数、消除分配,从而提升性能。

什么是 runtime async?它有什么好处?

runtime async 是 .NET 11 引入的异步基础设施重构,将 async/await 的状态机变换从 C# 编译器移到 JIT 运行时。好处包括:减少中间 Task 分配、提升同步完成调用链的性能(快 3 倍以上)、降低异常处理开销、减小二进制体积,并保持 100% 行为兼容。

.NET 11 如何减少边界检查?

通过改进范围分析(如处理 != 常量、合并 OR 操作数上界)、断言传播(跨基本块和块内累积事实)、循环克隆(支持 != 循环)以及识别常见模式(如 span 切片、前瞻访问),JIT 能在更多场景下证明索引安全,从而消除边界检查。

.NET 11 在文本处理方面有哪些性能提升?

文本处理提升包括:UTF-8 解码、Base64 编码/解码、正则表达式匹配、SearchValues 查找等显著加快。例如,Decode、ToBase64String、正则匹配等操作在基准测试中提速超过 1.6 倍。

runtime async 目前有哪些限制?

runtime async 目前不支持 async void、async 迭代器以及带自定义构建器的任意自定义 task-like 返回类型,这些仍使用传统的编译器变换。此外,它尚未完全优化,存在已知会产生较低效代码的场景,建议在 .NET 11 中实验性开启并测量。

🏷️

标签

➡️

继续阅读