网站建设交流论坛地址,wordpress可视化编辑在那里,android开发工具有哪些,WordPress手机访问乱码我对几个应用进行严格的启动性能评估#xff0c;对比了在 .NET Framework 和 dotnet 6 下的应用启动性能#xff0c;非常符合预期的可以看到#xff0c;在用户的设备上#xff0c;经过了 NGen 之后的 .NET Framework 可以提供非常优越的启动性能#xff0c;再加上 .NET Fr… 我对几个应用进行严格的启动性能评估对比了在 .NET Framework 和 dotnet 6 下的应用启动性能非常符合预期的可以看到在用户的设备上经过了 NGen 之后的 .NET Framework 可以提供非常优越的启动性能再加上 .NET Framework 本身就是属于系统组件的部分很少存在冷启动的时候大部分的 DLL 都在系统里预热。启动性能方面依然是 .NET Framework 比 dotnet 6 快非常多。而在破坏了 .NET Framework 的运行时框架层的 NGen 之后可以发现 .NET Framework 的启动性能就比不过 dotnet 6 的启动性能。为了在 dotnet 6 下追平和 .NET Framework 的启动性能差异引入与 NGen 的同等级的 ReadyToRun 用来提升整体的性能。本文将告诉大家如何在 dotnet 6 的应用里面使用 Crossgen2 工具给 DLL 生成 AOT 数据提升应用启动性能我预计本文是具有时效的各个概念都在变更本文是在 2022.05 编写的。如果你阅读本文的时间距离本文编写时间过长那请小心本文过期的知识误导开始之前还请理清一下概念在 dotnet 里面这些概念都在变来变去还没有完全定下来。在聊 dotnet 里面的 AOT 之前是必须先来做一个辟谣的。第一个谣言是 AOT 意味着性能更高其实不然采用 AOT 能减少应用启动过程中从 IL 转换为本机代码的损耗但通过分层编译(TieredCompilation)技术这部分的差异不会特别特别大再加上 dotnet 6 引入 的 QuickJit 技术还能进一步缩小差距。但即使这么说启动性能方面采用 AOT 还是很有优势的因为启动过程是性能敏感的再加上大型项目在启动过程中将需要执行大量的代码逻辑即使 JIT 再快和加上动态 PGO 的辅助下依然由于需要工作的量太多而在性能上不如采用 AOT 的方式。由于 AOT 是生产静态逻辑只取平台最小集而无法和 JIT 一样根据所运行设备进行动态优化这就是为什么运行过程中的性能在 JIT 进入 Tier 2 优化之后的性能要远远超过 AOT 的方式。换句话说全程都使用 AOT 而不加入任何 JIT 只是提升启动性能但是降低了运行过程的性能那如果我启动性能也要运行过程的性能也要呢这个就是 ReadyToRun 技术的概念了在 DLL 的进入调用时先采用 AOT 技术将部分逻辑预先跑了 JIT 且将跑了之后的二进制逻辑也记录到 DLL 里面。如此可以实现在首次调用方法时减少 JIT 的戏份尽可能使用之前 AOT 的内容从而提升应用启动性能。而在应用跑起来之后依然跑的是 JIT 的优化如此即可兼顾启动性能和运行过程的性能如何实现 ReadyToRun 这个概念就需要用到几项技术和工具其中 Crossgen2 就是进行 ReadyToRun 的工具。通过 Crossgen2 工具可以对 DLL 进行静态 AOT 编入 DLL 内但是如此做法也不是没有缺点的那就是额外编入 DLL 的 AOT 的内容将会增大 DLL 的体积。而 DLL 体积的增大将会降低启动过程中读取文件的性能再加上 AOT 和 JIT 过程的切换也是需要判断逻辑加上了这部分损耗之后再对比一下 QuickJit 技术实际上采用 Crossgen2 进行 ReadyToRun 不是对所有的 DLL 都能提升启动性能为了解决以上问题在 dotnet 里再引入了 PGO 的概念。启动过程里面调用的方法是有限的如果可以了解到应用启动过程将会调用哪些方法只是将这部分方法进行 AOT 那么对 DLL 体积的影响将会小非常多。这就是 PGO 需要解决的问题通过引入 PGO 这个概念在应用运行过程里面了解应用启动过程将会碰到哪些 IL 逻辑将这部分逻辑记录下来用于指导 ReadyToRun 过程进行 AOT 哪些方法。从而让 AOT 过程不需要针对所有的 IL 逻辑而是仅对应用启动过程需要用到的才进行 AOT 过程。如此即可更大的提升应用的启动性能。不过 PGO 可以做的事情可不只是 ReadyToRun 的指导还可以作为 JIT 过程中让 JIT 了解可以预先在后台线程里面跑哪些 IL 转换从而达到更高的启动性能。必须说明的是我询问了几位大佬了解到当前的 PGO 还是一个玩具虽然性能评测上可以达到很好的效果然而还没有具备发布环境使用的能力对于 AOT 不可反编译的辟谣。如上文可以看到 ReadyToRun 技术上依然是保留 IL 逻辑只是在 DLL 里面再加入 AOT 生成的二进制数据从而减少启动过程的 JIT 的损耗。也就是说如果采用 ReadyToRun 的技术可以让应用有更快不一定是更快的启动性能同时也拥有原本的运行过程的性能。但是否可以做到不可反编译自然是做不到的原本的 IL 代码依然还在也就是说采用 ReadyToRun 技术没有任何额外的保护能力。那第二个问题如果采用纯 AOT 技术能否达到代码保护能力嗯能加一点点。如果配合上混淆的话感觉上是差不多了。如果要说防破解能力的话两个的打分一个是 60 分一个是 70 分满分是 100 分。真要别人看不懂代码写垃圾些就好了我全力发挥的时候保证连自己都看不懂回到主题如何在 dotnet 里面通过 Crossgen2 工具进行 ReadyToRun 提升应用性能千万别被官方骗了如果只是在 csproj 上或者是在发布的时候加上 ReadyToRun 的命令参数恭喜你是真的用了 Corssgen2 工具。但优化呢只是优化了入口程序集而已真的想要有比较大的优化是需要将除了入口程序集之外的其他程序集也通过 Crossgen2 工具进行 ReadyToRun 才可以有比较大的提升的。例如我的一个大型应用在启动过程里面将 WPF 框架里面大概十分之一的模块都碰了一次使用 JitInfo.GetCompiledMethodCount 了解到在第一个窗口 Show 出来之前就有 5 万个方法调用。这个应用的入口程序集占比太小了如果使用官方的方法只是对入口程序集进行 ReadyToRun 那么性能上还真被 .NET Framework 完虐为了让 dotnet 6 应用的启动性能能媲美 .NET Framework 应用的启动性能可以采用 ReadyToRun 对标 .NET Framework 的 NGen 技术。以下将告诉大家如何使用 Crossgen2 工具对 DLL 进行 ReadyToRun 提升启动性能默认的 Crossgen2 工具是采用 NuGet 分发的 DotnetPlatform 类型的 NuGet 包里面包含了独立发布的 Crossgen2 工具。换句话说可以在 %localappdata%\..\..\.nuget\packages\microsoft.netcore.app.crossgen2.win-x64 找到此工具。如果没有找到的话那试试用一句 dotnet publish -c Release -r win-x64 -p:PublishReadyToRuntrue 命令让 dotnet 为了构建 ReadyToRun 而帮你将 Crossgen2 下载以上的 Crossgen2 工具放在 microsoft.netcore.app.crossgen2.win-x64 文件夹里面这里的 win-x64 指的不是 Crossgen2 工具的能力不是说这个文件夹的工具只能构建出 win-x64 的。而是说这个工具本身是 win-x64 的。这个工具是能构建出其他的平台的 AOT 的。换句话说是在 Windows 的 32 位系统里面将会拉的工具是 microsoft.netcore.app.crossgen2.win-x86 的包进入版本号文件夹再进入 Tools 文件夹即可找到 Crossgen2.exe 可执行文件这就是工具本文。例如在我的设备上的工具路径是C:\Users\lindexi\.nuget\packages\microsoft.netcore.app.crossgen2.win-x64\6.0.5\tools\Crossgen2.exe接下来将告诉大家如何使用这个工具这个工具的使用需要传入的参数推荐是一个 rsp 文件大概的命令行调用如下C:\Users\lindexi\.nuget\packages\microsoft.netcore.app.crossgen2.win-x64\6.0.5\tools\Crossgen2.exe C:\lindexi\Fxx\F1.rsp具体的参数都放在 rsp 文件里面大概内容如下--targetos:windows--targetarch:x86--pdb-O-r:C:\Program Files (x86)\dotnet\shared\Microsoft.NETCore.App\6.0.5\api-ms-win-core-console-l1-1-0.dll-r:C:\Program Files (x86)\dotnet\shared\Microsoft.NETCore.App\6.0.5\api-ms-win-core-console-l1-2-0.dll-r:C:\Program Files (x86)\dotnet\shared\Microsoft.NETCore.App\6.0.5\api-ms-win-core-datetime-l1-1-0.dll-r:C:\Program Files (x86)\dotnet\shared\Microsoft.NETCore.App\6.0.5\api-ms-win-core-debug-l1-1-0.dll-r:C:\Program Files (x86)\dotnet\shared\Microsoft.NETCore.App\6.0.5\api-ms-win-core-errorhandling-l1-1-0.dll-r:C:\Program Files (x86)\dotnet\shared\Microsoft.NETCore.App\6.0.5\api-ms-win-core-fibers-l1-1-0.dll-r:C:\Program Files (x86)\dotnet\shared\Microsoft.NETCore.App\6.0.5\api-ms-win-core-file-l1-1-0.dll-r:C:\Program Files (x86)\dotnet\shared\Microsoft.NETCore.App\6.0.5\api-ms-win-core-file-l1-2-0.dll--out:C:\Users\linde\AppData\Local\Temp\Crossgen2\Crossgen2\KokicakawheeyeeWhemhedawfelawnemhel.dllC:\lindexi\Code\empty\KokicakawheeyeeWhemhedawfelawnemhel\KokicakawheeyeeWhemhedawfelawnemhel\bin\release\net6.0-windows\win-x86\publish\KokicakawheeyeeWhemhedawfelawnemhel.dll大概由以下几个部分组成。每一行都是一个独立的参数分别内容如下--targetos:windows: 准备执行的系统平台。进行 ReadyToRun 将生成 AOT 代码这是平台强相关的必须说明是哪个平台--targetarch:x86准备生成的对应平台是 x86 还是 x64 等--pdb: 这是可选的表示要生成 PDB 符号文件。如不加上这一句将不生成 PDB 文件。生成的 PDB 文件是 ni.pdb 文件配合原本的 DLL 的 PDB 文件即可方便进行调试-O: 这是可选的表示需要进行优化。相当于 Release 版本。推荐默认都加上否则将几乎没有优化效果或者说只有反向优化效果-r:xxx.dll: 这里将会重复很多行一行一个程序集文件的本地路径。让工具了解到有哪些引用可以去找到。工具在准备 AOT 过程需要找到所引用的程序集。这些参数就是告诉工具对应的程序集放在哪。可以多加入很多程序集因为只是给工具使用的参考引用工具会根据自己的需求去找到对应的程序集文件。如果工具发现传入的有多余的那将会自动忽略多余的。推荐将整个 dotnet runtime 都加入但是要注意加入的版本必须是和发布的版本是一致的否则启动过程如果炸了那就凉凉。如果应用是独立发布的那就列出应用独立发布文件夹里面的所有 DLL 文件不需要加上额外的运行时文件夹--out:xx.dll: 处理之后的输出文件路径xxxxx.dll 输入程序集的路径构建出 rsp 文件作为参数调用 Crossgen2 工具即可完成对程序集的 ReadyToRun 过程。多个程序集就多次重复以上过程即可必须画重点的是调用 Crossgen2 工具进行 ReadyToRun 是不一定能提升启动性能的这是一个需要测量的过程。每个 DLL 在调用了 Crossgen2 工具进行 ReadyToRun 是会修改文件体积的整个变更也是会影响启动性能的。推荐在优化应用启动性能进行足够的测量方法如下使用 Crossgen2 工具对每个 DLL 来一次包括框架层的 DLL 也来一次。然后逐个 DLL 替换测量应用启动性能。如果发现某些 DLL 进行了 ReadyToRun 反而降低启动性能或者某些 DLL 加大的文件体积对比启动性能的优化来说不划算那就不对这些 DLL 进行优化以下是测试的对 dotnet runtime 底层和 WPF 框架的 DLL 进行 ReadyToRun 优化之后对 walterlv 大佬的某个应用的启动性能的影响值得一提的是对于不同的应用测试的数据将会存在很大的出入核心原因在于不同的应用启动过程将访问的模块有所不同这个数据是没有多少参考价值的因为对于不同的应用来说以上的结果将会有变化。如果你想要采用 ReadyToRun 技术提升应用启动性能还请必须测量每个 DLL 在经过 ReadyToRun 对启动性能的影响。如果你的时间充裕的话还可以测量对多个 DLL 优化的组合对启动性能的影响我所在团队的某个大型应用在经过了 ReadyToRun 技术的优化启动性能提升百分之三十但也必须说明的是不是所有的应用使用 ReadyToRun 都能有优化启动性能例如我的一个小应用只要采用了 ReadyToRun 技术启动性能基本上都是降低了。总的来说采用 ReadyToRun 技术是需要进行性能测量的参考文档WPF dotnet 使用本机映像 native 优化 dotnet framework 二进制文件WPF 通过 ReadyToRun 提升性能Conversation about crossgen2 - .NET Blogruntime/crossgen2-compilation-structure-enhancements.md at main · dotnet/runtimeruntime/Program.cs at main · dotnet/runtime编译配置设置 - .NET Microsoft DocsReadyToRun deployment overview - .NET Microsoft Docs利用 PGO 提升 .NET 程序性能 - hez2010 - 博客园JitInfo.GetCompiledMethodCount(Boolean) Method (System.Runtime) Microsoft Docs