这个项目并不是为了改进性能的,而是为托管 RyuJIT 提供更好的体系结构,在不需要或者不启动运行时的情况下以“离线”方式生成代码,以便更好地支持交叉编译。
动态 PGO动态 PGO是 .NET 正在探索和启用的PGO模式之一。一方面,可以将其视为“无需训练” 的 PGO。在文章的前面,我描述了 PGO 的使用过程,而动态PGO的优点是不需要任何这些,但是缺点是过程需要更长的时间才能达到最佳性能。
另一方面,动态 PGO 可以被认为是当今分层编译所使用的更为简单(且效果较差)的策略的替代品。
最引人注目案例中,动态 PGO 和静态 PGO 组合到了一起。在运行时, JIT 可以细化一小部分经过静态编译的 PGO 优化代码,以提供最大的好处。
例如,JIT 可以注意到,在到目前为止已加载的过程中,只有一个类实现了给定的接口,然后,JIT 可以生成通过类直接调用的代码,而不是通过接口间接调用。
这种经典的编译器技术称为去虚拟化,它通过消除方法调用中的间接操作并启用内联来提高性能。
作为启用动态 PGO 的一部分,.NET 已经做出了如下改动:
Guarded devirtualization:通过类概要文件和针对类类型的探针启用受保护的去虚拟化
Flowgraph visualizations:带有配置文件数据的流程图的图形转储
Redundant branch elimination:优化完全确定分支结果的分支
Enable CSE for PGO scenarios:为 PGO 引入的类型测试启用 CSE
ARM64 性能Preview 1 中包含了以下改进:
Stack frame zeroing:使用 SIMD 清零初始帧
上图展示了改进带来的影响,数值越低越好。绿色线是改进之后的,橘色是另一个实验性改进的,蓝色是原来的。
硬件加速的 structstruct 值类型是 .NET 中很重要的性能工具,被频繁使用,但是此前 struct 并没有在 JIT 中得到应得的优化。在 .NET 5 和 .NET 6 中,将针对 struct 进行性能优化,一部分是确保 struct 能够被加载到 CPU 寄存器中进行访问。
Preview 1 中包含如下改进:
Struct promotion for HFAs:Struct promotion for HFA and non-HFA multireg args on x64 and Arm64
Enregister HFAs:Enregister HFAs and other structs with matching fields
结语以上就是个人认为值得关注的 .NET 6 Preview 1 带来的新特性了,后续还会有十个左右的预览版本,敬请期待吧。