Flier's Sky

天空,蓝色的天空,眼睛看不到的东西,眼睛看得到的东西

导航

to NGen or not to NGen, that is the question

Posted on 2004-07-08 10:46  Flier Lu  阅读(1040)  评论(0编辑  收藏  举报
to NGen or not to NGen, that is the question

http://www.blogcn.com/user8/flier_lu/index.html?id=1550010&run=.04005F8

    Jeffrey Richter曾在CodeGuru上发表过一篇讨论是否应该使用NGen的文章。(ngen.exe支持将CLR格式的IL代码编译成Native的代码,避免载入时再次JIT编译)

     JIT Compilation and Performance - To NGen or Not to NGen?

     文中的观点是应该在大多数程序中避免使用ngen预编译IL代码为Native代码,因为JIT编译器可能比ngen更了解用户的系统。例如JIT编译器有以下优势:

     1.可以知道用户正在使用的什么类型的CPU,是PII、PIII还是P4,并编译生成相应的优化指令
     2.可以知道用户当前是使用单CPU还是多CPU,以便优化线程锁定机制
     3.可以避免ngen静态编译带来的DLL载入时重定位问题等等

     而且使用ngen预编译代码还会带来一些潜在的问题:

     1.没有知识产权保护:与某些人预期的不同,ngen生成的Native代码不能独立发布。因为其中没有包含Metadata信息,所以还是必须与原始的IL代码一同发布
     2.ngen生成的文件可能不同步:CLR在载入ngen生成的文件时,要检测其编译时的属性是否与当前环境匹配,不匹配则使用缺省的JIT编译
     3.难以管理:ngen生成的文件不能自动删除,因此违背了.NET架构程序的XCOPY分发策略
     4.低劣的载入时性能(重定位):如果ngen生成的DLL文件的基址已经被占用,则载入时需要重定位(rebase)
     5.低劣的运行时性能:ngen生成的文件采用较为保守的假定环境,因此代码效率低于JIT编译
     6.某些应用程序域(domain)的载入策略会忽略ngen生成的文件:assembly可以以应用程序域相关(non-domain-neutral)和无关(domain-neutral)的方式被载入,但ngen生成的文件假设只有mscorlib.dll以应用程序域无关的方式被载入。因此当某个assembly通过应用程序域无关的方式被使用,则ngen生成的代码无法使用,还是要通过JIT编译。例如ASP.NET中所有具有strongly-named的assembly都会被通过应用程序域无关的方式载入。

     因此Jeffrey Richter认为,只有对于客户端程序能够有可测量的载入性能提升的情况下,才应该使用ngen预编译代码,而对于其他程序,特别是服务器端程序,都应该避免ngen的使用。
     
     不过CLR组的Junfeng Zhang并不十分赞同上述观点,故而在其BLog上发表了一篇批驳的文章
     
     JIT Compilation and Performance - To NGen or Not to NGen? 
     
     文中对Jeffrey Richter提出的ngen的几个潜在问题逐条反驳:

     1.ngen并不是用来保护知识产权的工具,只是优化载入时性能而已,可以通过其他工具如混淆器(obfuscator)保护知识产权
     2.一般只有在维护.NET Framework和自己的程序后,才会导致不同步问题,而此时可以使用ngen重新生成预编译文件
     3.ngen支持 /delete 命令行参数,因此可以通过写一个批处理文件完成自动删除
     4.重定位是所有dll都存在的问题,并不能为了避免重定位就不使用dll而采用巨大的exe文件,因此这不能作为不使用ngen的理由。而且CLR载入dll的时候会检测这种情况的发生,并在合适的情况下拒绝使用ngen生成的文件
     5.CLR目前的JIT编译器对所有代码只编译一次,而不是象Sun的Hotspot那样,监视已JIT的代码,根据动态行为重新JIT优化性能。而ngen具有的JIT无法达到的优势是可以跨assembly做一些代码的优化。不过ngen代码还是比JIT编译平均有5%-10%的性能损失,单能大大提高载入速度。
     6.ngen编译的文件的确在某些情况下无法被使用,但这并不能作为不使用ngen的理由
     
     此外ngen还有个优点是其生成的代码可以被多个进程共享,而JIT编译生成的代码在私有地址空间中。
     
     因此ngen在客户端代码的处理上还是有价值的,呵呵
     
     后面MS的Josh Williams又补充说,在64位版本的.NET中,ngen生成代码的性能可能比JIT代码有较大改善,因为ngen包含了一些对JIT来说过于复杂的全局优化措施。
     
     最后Junfeng Zhang还给出了一个性能优化的指导性文章的链接
     
     Profile-Guided Optimization with Microsoft Visual C++ 2005
     
     有趣的讨论,通过这种BLog的论战,很容易就能够获得一些通过正规渠道文章无法了解的内幕消息,呵呵