你曾经使用过ngen.exe吗?

47

这里有人用过ngen吗?在哪里使用?为什么要用它?有没有性能提升?什么时候和在什么情况下使用它是有意义的?


9
运行 ngen /show 命令可以查看谁在使用它 :) - Mehrdad Afshari
8个回答

31

我不会在日常使用中使用NGEN,但是一些旨在提高性能的工具会使用它;例如,Paint.NET在安装程序(或者可能是第一次使用)期间使用NGEN。某些微软工具也可能使用它,但我不确定。

基本上,NGEN会执行一个程序集的大部分JIT编译工作,以便在冷启动时减少延迟。当然,在大多数典型的使用情况下,并不会完全执行100%的代码,因此从某种程度上来说,这做了很多“不必要”的工作-但它无法事先判断。

我认为缺点是你需要使用GAC才能使用NGEN;我尽可能避免使用GAC,以便可以使用robocopy-deployment(到服务器)和ClickOnce(到客户端)。


4
使用NGEN时不必使用GAC。http://blogs.msdn.com/b/abhinaba/archive/2013/12/11/net-loading-native-ngen-images-and-its-interaction-with-the-gac.aspx - Shiv

19

是的,我看到了性能的提升。我的测量结果表明,如果我将我的程序集放入全局程序集缓存(GAC)中(因为我的程序集都是强名称的),启动性能会得到改善。如果您的程序集是强名称的,而没有使用GAC,则NGen不会有任何区别。原因是,如果您具有未在GAC中的强名称程序集,则.NET运行时将从磁盘加载整个托管程序集来验证它,这将规避NGen的主要优势。

对于我们的应用程序来说,这不是一个很好的选择,因为我们依赖于公司的公共程序集(也是强名称的)。许多使用不同版本的产品使用这些公共程序集,将它们放入GAC意味着如果我们的一个应用程序没有指定一个公共程序集的“使用特定版本”,则它将加载GAC中的版本,而不管其执行目录中的版本。我们认为NGen的好处不值得冒险。


1
我对这个说法“如果您的程序集是强名称的,则在不使用GAC的情况下,NGen不会有任何区别”并不确定。然而,这篇文章在一定程度上证实了这个说法。更准确地说,“当程序集位于GAC中时,ngen在性能和内存使用方面最为有效”。(请注意,此帖子早于引用的MSDN博客。) - Olly
自从.NET 3.5以来,NGEN图像绕过了GAC的强命名,因此这不再是一个问题。 - Abel

9

Ngen主要减少.NET应用程序的启动时间和工作集。但是,它也有一些缺点(来自Jeffrey Richter的《CLR Via C#》):

没有知识产权保护

NGen文件可能会失去同步

较差的加载时间性能(重新定位/绑定)

较差的执行时间性能

由于刚才列出的所有问题,考虑使用NGen.exe时应非常谨慎。对于服务器端应用程序,NGen.exe几乎没有意义,因为只有第一个客户端请求会受到性能影响;未来的客户端请求将以高速运行。此外,对于大多数服务器应用程序,只需要一个代码实例,因此没有工作集优势。

对于客户端应用程序,如果一个程序集被多个应用程序同时使用,NGen.exe可能有意义,可以提高启动时间或减少工作集。即使在一个程序集不被多个应用程序使用的情况下,NGen一个程序集也可以改善工作集。此外,如果为客户端应用程序的所有程序集使用NGen.exe,则CLR根本不需要加载JIT编译器,进一步减少工作集。当然,如果只有一个程序集没有被NGen,或者一个程序集的NGen文件无法使用,JIT编译器将加载,应用程序的工作集将增加。


1
为什么没有知识产权保护? - Andrei Rînea
2
你可能认为NGEN提供了比普通的.Net程序集更多的IP保护,因为它被编译成机器代码,更难以逆向工程,但由于NGEN还需要原始程序集存在于计算机上,因此仍然可以使用原始程序集轻松地进行逆向工程。 - Lars Truijens

7

ngen主要用于提高启动时间(通过消除JIT编译)。它可能会改善应用程序的性能(通过减少JIT时间),也可能会降低应用程序的整体性能(因为某些JIT优化不可用)。

.NET Framework本身在安装过程中使用ngen为许多程序集进行优化。


1
安装完 .net framework 并重启机器后,“.NET Runtime Optimization Service” 仍在努力“ngening”其所有的 dlls… - Tarnay Kálmán
是的。这是.NET 2.0安装中的新功能之一。我清楚地记得在.NET 1.1安装中有“生成本机映像”的状态。 - Mehrdad Afshari
那很有道理。框架 DLL 将在系统上的每个非微不足道的 .Net 应用程序中使用。在可能的情况下不进行 JIT 框架将提高为 .net 编写的每个程序的性能。您可能会注意到,Visual Studio 安装程序同步 ngen Visual Studio 的托管部分(顺便说一句,这就是为什么安装需要如此长时间的原因)。 - Spence

1

我曾经用过它,但只是为了研究目的。如果你确定你的部署环境的CPU架构(它不会改变),那么才使用它。

但是让我告诉你,JIT编译并不太糟糕,如果你在多个CPU环境下部署(例如经常更新的Windows客户端应用程序),则不要使用NGEN。这是因为有效的NGEN缓存取决于许多属性。如果其中一个失败,你的程序集就会回退到JIT。

JIT在这种情况下是明显的赢家,因为它根据正在运行的CPU架构实时优化代码。(例如,它可以检测是否有多个CPU)

而且CLR每次发布都越来越好,所以总之,除非你对你的部署环境非常确定,否则坚持使用JIT - 即使你的性能提升也很难证明使用ngen.exe(可能只有几百毫秒的收益)- 在我看来,这不值得努力。

此外,请查看关于此主题的这个真正不错的链接 - JIT Compilation and Performance - To NGen or Not to NGen?


2
微软建议在本地运行ngen,所以不理解禁止的原因...或者您是假设您将分发ngen的结果? - Richard
1
我不明白你如何从开发机器上运送 ngen 编译的程序集。你能详细说明一下吗? - Mehrdad Afshari
3
想法是在执行程序的机器上运行NGEN,例如在安装过程中运行。那么唯一的问题是,如果您在运行期间更改CPU(例如,在硬件故障后进行还原或使用P2V),就会出现问题。 - Marc Gravell
@Marc:我认为这是唯一的方法。你知道一种将之前生成的程序集发送到客户机器的方法吗? - Mehrdad Afshari
不必运送NGEN的程序集,你可以运送本地图像:http://msdn.microsoft.com/zh-cn/vstudio/dotnetnative.aspx - Shiv
显示剩余5条评论

0

是的,我尝试了一个小的单CPU密集型exe,并且使用ngen时速度稍微慢了一些!

我安装和卸载了ngen图像多次,并运行了基准测试。

我总是得到以下可重复的时间+/- 0.1秒: 没有33.9秒, 有35.3秒


0
作为对Mehrdad Afshari评论JIT编译的补充。如果通过XmlSerializer序列化具有许多属性的类,并且在64位系统上使用SGEN,NGEN组合,则可能会产生巨大的影响(在我们的情况下是千兆字节和几分钟)。
更多信息请参见此处: XmlSerializer startup HUGE performance loss on 64bit systems 特别是查看Nick Martyshchenko的答案。

0

是的。在一个WPF应用程序中使用,以加快启动时间。启动时间从9秒缩短到5秒。在我的博客中可以了解更多信息:

最近我发现NGEN在性能方面非常出色。我目前工作的应用程序有一个数据访问层(DAL)是自动生成的。数据库架构相当大,我们还将一些数据(值列表)直接生成到DAL中。结果是:许多类具有许多字段和许多方法。在分析应用程序时,JIT开销经常会显示出来,但在搜索JIT编译和NGEN后,我认为这不值得去做。安装时间开销是我的主要关注点,使我忽略了这些迹象,并专注于向应用程序添加更多功能。当我们将架构更改为“任何CPU”运行在64位机器上时,情况变得更糟:我们的应用程序在单个语句上经历了长达10秒的挂起,分析器仅显示该问题区域的JIT开销。NGEN解决了这个问题:该语句从10秒降至1毫秒。这个语句不是启动过程的一部分,所以我渴望知道对整个应用程序进行NGEN编译可以做些什么来缩短启动时间。它从8秒缩短到3.5秒。

结论:我真的建议您在您的应用程序上尝试NGEN!


NGEN所有东西的陷阱是内存使用。对于一个进程,当NGEN为DLL进行处理时,它们占用的内存大约是原来的两倍,因为.NET会将MSIL和NGEN版本都加载到内存中。这是不可避免的,所以如果您有进程内存限制(例如32位2GB内存空间限制)和一个大型程序,则NGEN会加剧问题。 - Shiv

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接