龙空技术网

.NET8极致性能优化VM

opendotnet 676

前言:

目前朋友们对“虚拟机vmnet8”大体比较关切,兄弟们都想要知道一些“虚拟机vmnet8”的相关知识。那么小编同时在网上收集了一些关于“虚拟机vmnet8””的相关知识,希望你们能喜欢,朋友们一起来了解一下吧!

前言

VM是CLR的一部分,但是它不包括GC和JIT。它主要的作用是进行类型的识别和DLL(托管以及非托管)的加载。可以看到VM是一个比较重要的部分,.NET8里面对它也进行了优化,属于核心级的优化。本篇看下

概述

.NET8里面针对VM的其中一个优化是将指令集映射(内存映射,关于内存映射这一点,之前提到过。参考:断点+内存映射终章(CLR问题) 以及文章,绝顶技术:断点+内存映射组合的超强BUG?)到MethodDesc上,关于MethodDesc它是CLR里面所有托管方法的方法描述结构体。也即是描述方法所在的类,方法级别,方法是否被编译,方法签名信息,方法数据结构等等。

这种优化主要是针对比如堆栈的遍历,委托创建的时候,提高它们的转换性能,而且是无锁的状态(性能提升点)。从字面分析即可理解这种优化的程度是较高级别的。

一:委托创建的优化

看一个例子:

public class Tests{ public void InSerial() { for (int i = 0; i < 10_000; i++) { CreateDelegate<string>(); } } public void InParallel() { Parallel.For(0, 10_000, i => { CreateDelegate<string>(); }); }

[MethodImpl(MethodImplOptions.NoInlining)] private static Action<T> CreateDelegate<T>() => new Action<T>(GenericMethod);

private static void GenericMethod<T>(T t) { }}

比如以上委托创建的操作,.NET7和.NET8性能对比

MethodRuntimeMeanRatioInSerial.NET 7.01,868.4 us1.00InSerial.NET 8.0706.5 us0.38InParallel.NET 7.01,247.3 us1.00InParallel.NET 8.0222.9 us0.18

可以看到.NET8提升了3到6倍的性能

2.分配器ExecutableAllocator 的优化

另外一个优化是提高了 ExecutableAllocator 的性能,它叫做分配器。负责CLR中所有可执行内存相关的分配。比如说,JIT用它来获取内存,把代码写入到获取的内存里,然后执行这些代码。当ExecutableAllocator获取的这段内存被映射的时候,ExecutableAllocator可以决定对这个内存进行读或者写,或者执行,或者其它的操作。ExecutableAllocator维护一个缓存,通过减少缓存未命中的次数和减少这些缓存未命中时的成本来提高分配器的性能。

3.R2R的优化

R2R是预编译机器码的一种格式,AOT编译和JIT编译是两个极端,一个是完全预编译,一个则是即时编译。R2R介于这两者之间,如果检测到函数有预编译代码则进行AOT化的运行,如果没有则调用JIT进行即时编译运行。

这里优化的是R2R的启动时间,旨在减少 R2R 图像中验证类型所花费的时间,由于 R2R 图像中有专用的元数据,使得在 R2R 图像中查找泛型参数和嵌套类型变得更快,通过在方法描述中存储一个额外的索引,将 O(n^2) 的查找转变为 O(1) 的查找,以及确保 vtable 块始终被共享。

分配器ExecutableAllocator和R2R的优化是C++级的,托管的 C#代码无法完全呈,所以这里就不上代码了。了解这些优化即可,更深入可以参考之前的文章。

欢迎加入.NET技术交流群

标签: #虚拟机vmnet8